From f65c7c3fd8568310c7039433c95f8f1df8bd2bbf Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 19 Apr 2026 15:33:24 -0400 Subject: [PATCH 01/31] feat(api): add GET /runs/{id}/files spec + RunFilesMeta schema Reintroduces the endpoint deleted in the April 5 server-only cleanup, this time targeted at the web UI (not the CLI). Route registered with not_implemented; real handler lands in Unit 5. - FileDiff gains optional change_kind, truncated, truncation_reason, binary, sensitive fields (all additive, back-compat) - New RunFilesMeta replaces PaginationMeta on PaginatedRunFileList (truncated, total_changed, to_sha, to_sha_committed_at, degraded, degraded_reason, patch, files_omitted_by_budget) - from_sha / to_sha query params reserved for future use (non-default values 400 in v1) Generated TS client picks up the new model; typecheck + openapi conformance tests pass. No existing consumers of PaginatedRunFileList['meta'] found in the monorepo. Refs plan docs/plans/2026-04-19-002-feat-run-files-changed-tab-plan.md Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/api-reference/fabro-api.yaml | 146 +++++++++++++++++- lib/crates/fabro-server/src/server.rs | 2 + .../src/.openapi-generator/FILES | 1 + .../src/api/run-outputs-api.ts | 108 +++++++++++++ .../fabro-api-client/src/models/file-diff.ts | 40 ++++- .../fabro-api-client/src/models/index.ts | 1 + .../src/models/paginated-run-file-list.ts | 6 +- .../src/models/run-files-meta.ts | 63 ++++++++ 8 files changed, 360 insertions(+), 7 deletions(-) create mode 100644 lib/packages/fabro-api-client/src/models/run-files-meta.ts diff --git a/docs/api-reference/fabro-api.yaml b/docs/api-reference/fabro-api.yaml index c00368aa2..8d6bcec5e 100644 --- a/docs/api-reference/fabro-api.yaml +++ b/docs/api-reference/fabro-api.yaml @@ -1013,6 +1013,61 @@ paths: schema: $ref: "#/components/schemas/ErrorResponse" + /api/v1/runs/{id}/files: + get: + operationId: listRunFiles + tags: [Run Outputs] + summary: List Run Files Changed + description: | + Returns the set of file changes produced by a run as a list of before/after diffs. + + While the run's sandbox is reachable, diffs are resolved live against the sandbox working tree at the current HEAD. Once the sandbox is gone, the response may degrade to the unified-patch string captured at run end (see `meta.degraded` and `meta.patch`). + + Responses are bounded by per-file (256 KiB / 20k lines), per-run aggregate (5 MiB), and per-request (200 files) caps. Files exceeding a cap are returned with `truncated: true` and empty `contents`. Sensitive paths (credentials, keys) are elided with `sensitive: true` and empty `contents`. + parameters: + - $ref: "#/components/parameters/RunId" + - $ref: "#/components/parameters/PageLimit" + - $ref: "#/components/parameters/PageOffset" + - name: from_sha + in: query + required: false + description: Reserved for future use. Only the default value is accepted in the current API version; any other value returns 400. + schema: + type: string + pattern: "^[0-9a-f]{7,40}$" + - name: to_sha + in: query + required: false + description: Reserved for future use. Only the default value is accepted in the current API version; any other value returns 400. + schema: + type: string + pattern: "^[0-9a-f]{7,40}$" + responses: + "200": + description: File diffs for the run + content: + application/json: + schema: + $ref: "#/components/schemas/PaginatedRunFileList" + "400": + description: Malformed query parameter (invalid SHA format, or non-default value for `from_sha`/`to_sha`). + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "404": + description: Run not found (or caller lacks access; returned as 404 to prevent enumeration). + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "503": + description: Transient sandbox subprocess failure (timeout, process kill). Safe to retry. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /api/v1/runs/{id}/stages/{stageId}/artifacts: get: operationId: listStageArtifacts @@ -4204,7 +4259,14 @@ components: example: 'import { parseArgs } from "node:util";' FileDiff: - description: A before/after pair showing changes to a single file. + description: | + A before/after pair showing changes to a single file. + + Contents conventions for non-modify cases: + - Added: `old_file.contents` is empty string; `new_file` holds the added contents. + - Deleted: `new_file.contents` is empty string; `old_file` holds the removed contents. + - Renamed (no content change): both sides hold identical contents; `old_file.name != new_file.name`. + - Symlink / submodule / binary / sensitive / truncated: contents are empty strings; consumers must render a placeholder based on the flag set. type: object required: - old_file @@ -4214,6 +4276,35 @@ components: $ref: "#/components/schemas/DiffFile" new_file: $ref: "#/components/schemas/DiffFile" + change_kind: + type: string + description: Optional classification of the change. Clients that don't recognize a value should fall back to inspecting the old/new contents. + enum: + - added + - modified + - deleted + - renamed + - symlink + - submodule + example: modified + truncated: + type: boolean + description: When `true`, `new_file.contents` and `old_file.contents` are empty strings because the file exceeded a cap (see `truncation_reason`). + example: false + truncation_reason: + type: string + description: Reason this file's contents were omitted. Absent when `truncated` is `false` or omitted. + enum: + - file_too_large + - budget_exhausted + binary: + type: boolean + description: When `true`, the file is non-textual; `contents` on both sides are empty strings. + example: false + sensitive: + type: boolean + description: When `true`, the file path matched the server's sensitive-path denylist; `contents` on both sides are empty strings regardless of truncation or binary flags. + example: false DiffStats: description: Aggregate line-change statistics for a diff. @@ -4231,8 +4322,57 @@ components: description: Total lines deleted. example: 234 + RunFilesMeta: + description: | + Metadata for a `PaginatedRunFileList` response. + + Replaces `PaginationMeta` on the files endpoint — the naturally-bounded list does not use cursor pagination but exposes caps and a degraded-response path instead. + type: object + required: + - truncated + - total_changed + properties: + truncated: + type: boolean + description: True when any cap (file count, per-file size, or aggregate size) was hit for this response. + example: false + files_omitted_by_budget: + type: integer + description: Number of files dropped because the aggregate 5 MiB budget was exhausted. Zero or absent when no files were dropped for budget reasons. + example: 0 + total_changed: + type: integer + description: Total files changed in the run (before caps were applied). May exceed `data.length` when truncation occurred. + example: 3 + to_sha: + type: string + description: Head SHA the diff (or patch) was resolved against. + pattern: "^[0-9a-f]{7,40}$" + example: "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0" + to_sha_committed_at: + type: string + format: date-time + description: Commit time of `to_sha`, used by the UI for the "Checkpoint Xm ago" freshness label on Running runs. + degraded: + type: boolean + description: When `true`, this response carries only a unified patch string in `patch` (no per-file contents in `data`). The UI should render via a unified-patch component. + example: false + degraded_reason: + type: string + description: Why the response degraded to patch-only form. Absent when `degraded` is `false` or omitted. + enum: + - sandbox_unreachable + - sandbox_gone + - provider_unsupported + patch: + type: string + description: Unified-patch text captured at run end. Present only when `degraded` is `true`. Capped at 5 MiB; denylisted file sections are stripped and replaced with a placeholder line. + PaginatedRunFileList: - description: Paginated list of file diffs produced by a run. + description: | + List of file diffs produced by a run, with metadata describing truncation and degraded-response state. + + Naturally bounded: at most 200 files per response. Consumers should inspect `meta.truncated` rather than assuming `data.length` equals the run's total change count. type: object required: - data @@ -4243,7 +4383,7 @@ components: items: $ref: "#/components/schemas/FileDiff" meta: - $ref: "#/components/schemas/PaginationMeta" + $ref: "#/components/schemas/RunFilesMeta" # ── Billing Schemas ────────────────────────────────────────────────── diff --git a/lib/crates/fabro-server/src/server.rs b/lib/crates/fabro-server/src/server.rs index 81fe5bebe..bb62a3645 100644 --- a/lib/crates/fabro-server/src/server.rs +++ b/lib/crates/fabro-server/src/server.rs @@ -1030,6 +1030,7 @@ fn demo_routes() -> Router> { .route("/runs/{id}/graph", get(demo::get_run_graph)) .route("/runs/{id}/stages", get(demo::get_run_stages)) .route("/runs/{id}/artifacts", get(demo::list_run_artifacts_stub)) + .route("/runs/{id}/files", get(not_implemented)) .route( "/runs/{id}/stages/{stageId}/turns", get(demo::get_stage_turns), @@ -1110,6 +1111,7 @@ fn real_routes() -> Router> { .route("/runs/{id}/graph", get(get_graph)) .route("/runs/{id}/stages", get(list_run_stages)) .route("/runs/{id}/artifacts", get(list_run_artifacts)) + .route("/runs/{id}/files", get(not_implemented)) .route("/runs/{id}/stages/{stageId}/turns", get(not_implemented)) .route( "/runs/{id}/stages/{stageId}/artifacts", diff --git a/lib/packages/fabro-api-client/src/.openapi-generator/FILES b/lib/packages/fabro-api-client/src/.openapi-generator/FILES index 8cfd5d2aa..42b42198a 100644 --- a/lib/packages/fabro-api-client/src/.openapi-generator/FILES +++ b/lib/packages/fabro-api-client/src/.openapi-generator/FILES @@ -145,6 +145,7 @@ models/run-checkpoint.ts models/run-control-action.ts models/run-error.ts models/run-event.ts +models/run-files-meta.ts models/run-list-item.ts models/run-manifest.ts models/run-projection-checkpoints-inner-inner.ts diff --git a/lib/packages/fabro-api-client/src/api/run-outputs-api.ts b/lib/packages/fabro-api-client/src/api/run-outputs-api.ts index 03e1fa7c0..60cd60a0f 100644 --- a/lib/packages/fabro-api-client/src/api/run-outputs-api.ts +++ b/lib/packages/fabro-api-client/src/api/run-outputs-api.ts @@ -24,12 +24,74 @@ import { BASE_PATH, COLLECTION_FORMATS, type RequestArgs, BaseAPI, RequiredError // @ts-ignore import type { ErrorResponse } from '../models'; // @ts-ignore +import type { PaginatedRunFileList } from '../models'; +// @ts-ignore import type { RunBilling } from '../models'; /** * RunOutputsApi - axios parameter creator */ export const RunOutputsApiAxiosParamCreator = function (configuration?: Configuration) { return { + /** + * Returns the set of file changes produced by a run as a list of before/after diffs. While the run\'s sandbox is reachable, diffs are resolved live against the sandbox working tree at the current HEAD. Once the sandbox is gone, the response may degrade to the unified-patch string captured at run end (see `meta.degraded` and `meta.patch`). Responses are bounded by per-file (256 KiB / 20k lines), per-run aggregate (5 MiB), and per-request (200 files) caps. Files exceeding a cap are returned with `truncated: true` and empty `contents`. Sensitive paths (credentials, keys) are elided with `sensitive: true` and empty `contents`. + * @summary List Run Files Changed + * @param {string} id Unique run identifier (ULID). + * @param {number} [pageLimit] Maximum number of items to return per page. + * @param {number} [pageOffset] Number of items to skip before returning results. + * @param {string} [fromSha] Reserved for future use. Only the default value is accepted in the current API version; any other value returns 400. + * @param {string} [toSha] Reserved for future use. Only the default value is accepted in the current API version; any other value returns 400. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listRunFiles: async (id: string, pageLimit?: number, pageOffset?: number, fromSha?: string, toSha?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('listRunFiles', 'id', id) + const localVarPath = `/api/v1/runs/{id}/files` + .replace(`{${"id"}}`, encodeURIComponent(String(id))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication SessionCookie required + + // authentication BearerAuth required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + if (pageLimit !== undefined) { + localVarQueryParameter['page[limit]'] = pageLimit; + } + + if (pageOffset !== undefined) { + localVarQueryParameter['page[offset]'] = pageOffset; + } + + if (fromSha !== undefined) { + localVarQueryParameter['from_sha'] = fromSha; + } + + if (toSha !== undefined) { + localVarQueryParameter['to_sha'] = toSha; + } + + localVarHeaderParameter['Accept'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * Returns token counts and billed totals broken down by stage and model for a specific run. * @summary Retrieve Run Billing @@ -79,6 +141,23 @@ export const RunOutputsApiAxiosParamCreator = function (configuration?: Configur export const RunOutputsApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = RunOutputsApiAxiosParamCreator(configuration) return { + /** + * Returns the set of file changes produced by a run as a list of before/after diffs. While the run\'s sandbox is reachable, diffs are resolved live against the sandbox working tree at the current HEAD. Once the sandbox is gone, the response may degrade to the unified-patch string captured at run end (see `meta.degraded` and `meta.patch`). Responses are bounded by per-file (256 KiB / 20k lines), per-run aggregate (5 MiB), and per-request (200 files) caps. Files exceeding a cap are returned with `truncated: true` and empty `contents`. Sensitive paths (credentials, keys) are elided with `sensitive: true` and empty `contents`. + * @summary List Run Files Changed + * @param {string} id Unique run identifier (ULID). + * @param {number} [pageLimit] Maximum number of items to return per page. + * @param {number} [pageOffset] Number of items to skip before returning results. + * @param {string} [fromSha] Reserved for future use. Only the default value is accepted in the current API version; any other value returns 400. + * @param {string} [toSha] Reserved for future use. Only the default value is accepted in the current API version; any other value returns 400. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async listRunFiles(id: string, pageLimit?: number, pageOffset?: number, fromSha?: string, toSha?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listRunFiles(id, pageLimit, pageOffset, fromSha, toSha, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['RunOutputsApi.listRunFiles']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, /** * Returns token counts and billed totals broken down by stage and model for a specific run. * @summary Retrieve Run Billing @@ -101,6 +180,20 @@ export const RunOutputsApiFp = function(configuration?: Configuration) { export const RunOutputsApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { const localVarFp = RunOutputsApiFp(configuration) return { + /** + * Returns the set of file changes produced by a run as a list of before/after diffs. While the run\'s sandbox is reachable, diffs are resolved live against the sandbox working tree at the current HEAD. Once the sandbox is gone, the response may degrade to the unified-patch string captured at run end (see `meta.degraded` and `meta.patch`). Responses are bounded by per-file (256 KiB / 20k lines), per-run aggregate (5 MiB), and per-request (200 files) caps. Files exceeding a cap are returned with `truncated: true` and empty `contents`. Sensitive paths (credentials, keys) are elided with `sensitive: true` and empty `contents`. + * @summary List Run Files Changed + * @param {string} id Unique run identifier (ULID). + * @param {number} [pageLimit] Maximum number of items to return per page. + * @param {number} [pageOffset] Number of items to skip before returning results. + * @param {string} [fromSha] Reserved for future use. Only the default value is accepted in the current API version; any other value returns 400. + * @param {string} [toSha] Reserved for future use. Only the default value is accepted in the current API version; any other value returns 400. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listRunFiles(id: string, pageLimit?: number, pageOffset?: number, fromSha?: string, toSha?: string, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.listRunFiles(id, pageLimit, pageOffset, fromSha, toSha, options).then((request) => request(axios, basePath)); + }, /** * Returns token counts and billed totals broken down by stage and model for a specific run. * @summary Retrieve Run Billing @@ -118,6 +211,21 @@ export const RunOutputsApiFactory = function (configuration?: Configuration, bas * RunOutputsApi - object-oriented interface */ export class RunOutputsApi extends BaseAPI { + /** + * Returns the set of file changes produced by a run as a list of before/after diffs. While the run\'s sandbox is reachable, diffs are resolved live against the sandbox working tree at the current HEAD. Once the sandbox is gone, the response may degrade to the unified-patch string captured at run end (see `meta.degraded` and `meta.patch`). Responses are bounded by per-file (256 KiB / 20k lines), per-run aggregate (5 MiB), and per-request (200 files) caps. Files exceeding a cap are returned with `truncated: true` and empty `contents`. Sensitive paths (credentials, keys) are elided with `sensitive: true` and empty `contents`. + * @summary List Run Files Changed + * @param {string} id Unique run identifier (ULID). + * @param {number} [pageLimit] Maximum number of items to return per page. + * @param {number} [pageOffset] Number of items to skip before returning results. + * @param {string} [fromSha] Reserved for future use. Only the default value is accepted in the current API version; any other value returns 400. + * @param {string} [toSha] Reserved for future use. Only the default value is accepted in the current API version; any other value returns 400. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + public listRunFiles(id: string, pageLimit?: number, pageOffset?: number, fromSha?: string, toSha?: string, options?: RawAxiosRequestConfig) { + return RunOutputsApiFp(this.configuration).listRunFiles(id, pageLimit, pageOffset, fromSha, toSha, options).then((request) => request(this.axios, this.basePath)); + } + /** * Returns token counts and billed totals broken down by stage and model for a specific run. * @summary Retrieve Run Billing diff --git a/lib/packages/fabro-api-client/src/models/file-diff.ts b/lib/packages/fabro-api-client/src/models/file-diff.ts index bae602244..b3d90709b 100644 --- a/lib/packages/fabro-api-client/src/models/file-diff.ts +++ b/lib/packages/fabro-api-client/src/models/file-diff.ts @@ -18,10 +18,48 @@ import type { DiffFile } from './diff-file'; /** - * A before/after pair showing changes to a single file. + * A before/after pair showing changes to a single file. Contents conventions for non-modify cases: - Added: `old_file.contents` is empty string; `new_file` holds the added contents. - Deleted: `new_file.contents` is empty string; `old_file` holds the removed contents. - Renamed (no content change): both sides hold identical contents; `old_file.name != new_file.name`. - Symlink / submodule / binary / sensitive / truncated: contents are empty strings; consumers must render a placeholder based on the flag set. */ export interface FileDiff { 'old_file': DiffFile; 'new_file': DiffFile; + /** + * Optional classification of the change. Clients that don\'t recognize a value should fall back to inspecting the old/new contents. + */ + 'change_kind'?: FileDiffChangeKindEnum; + /** + * When `true`, `new_file.contents` and `old_file.contents` are empty strings because the file exceeded a cap (see `truncation_reason`). + */ + 'truncated'?: boolean; + /** + * Reason this file\'s contents were omitted. Absent when `truncated` is `false` or omitted. + */ + 'truncation_reason'?: FileDiffTruncationReasonEnum; + /** + * When `true`, the file is non-textual; `contents` on both sides are empty strings. + */ + 'binary'?: boolean; + /** + * When `true`, the file path matched the server\'s sensitive-path denylist; `contents` on both sides are empty strings regardless of truncation or binary flags. + */ + 'sensitive'?: boolean; } +export const FileDiffChangeKindEnum = { + ADDED: 'added', + MODIFIED: 'modified', + DELETED: 'deleted', + RENAMED: 'renamed', + SYMLINK: 'symlink', + SUBMODULE: 'submodule' +} as const; + +export type FileDiffChangeKindEnum = typeof FileDiffChangeKindEnum[keyof typeof FileDiffChangeKindEnum]; +export const FileDiffTruncationReasonEnum = { + FILE_TOO_LARGE: 'file_too_large', + BUDGET_EXHAUSTED: 'budget_exhausted' +} as const; + +export type FileDiffTruncationReasonEnum = typeof FileDiffTruncationReasonEnum[keyof typeof FileDiffTruncationReasonEnum]; + + diff --git a/lib/packages/fabro-api-client/src/models/index.ts b/lib/packages/fabro-api-client/src/models/index.ts index 77c22ec8b..2f416e7a4 100644 --- a/lib/packages/fabro-api-client/src/models/index.ts +++ b/lib/packages/fabro-api-client/src/models/index.ts @@ -125,6 +125,7 @@ export * from './run-checkpoint'; export * from './run-control-action'; export * from './run-error'; export * from './run-event'; +export * from './run-files-meta'; export * from './run-list-item'; export * from './run-manifest'; export * from './run-projection'; diff --git a/lib/packages/fabro-api-client/src/models/paginated-run-file-list.ts b/lib/packages/fabro-api-client/src/models/paginated-run-file-list.ts index 09e6cda56..9f9eaf440 100644 --- a/lib/packages/fabro-api-client/src/models/paginated-run-file-list.ts +++ b/lib/packages/fabro-api-client/src/models/paginated-run-file-list.ts @@ -18,13 +18,13 @@ import type { FileDiff } from './file-diff'; // May contain unused imports in some cases // @ts-ignore -import type { PaginationMeta } from './pagination-meta'; +import type { RunFilesMeta } from './run-files-meta'; /** - * Paginated list of file diffs produced by a run. + * List of file diffs produced by a run, with metadata describing truncation and degraded-response state. Naturally bounded: at most 200 files per response. Consumers should inspect `meta.truncated` rather than assuming `data.length` equals the run\'s total change count. */ export interface PaginatedRunFileList { 'data': Array; - 'meta': PaginationMeta; + 'meta': RunFilesMeta; } diff --git a/lib/packages/fabro-api-client/src/models/run-files-meta.ts b/lib/packages/fabro-api-client/src/models/run-files-meta.ts new file mode 100644 index 000000000..8c84ff985 --- /dev/null +++ b/lib/packages/fabro-api-client/src/models/run-files-meta.ts @@ -0,0 +1,63 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Fabro Run API + * HTTP API for managing Fabro workflow run executions. + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * Metadata for a `PaginatedRunFileList` response. Replaces `PaginationMeta` on the files endpoint — the naturally-bounded list does not use cursor pagination but exposes caps and a degraded-response path instead. + */ +export interface RunFilesMeta { + /** + * True when any cap (file count, per-file size, or aggregate size) was hit for this response. + */ + 'truncated': boolean; + /** + * Number of files dropped because the aggregate 5 MiB budget was exhausted. Zero or absent when no files were dropped for budget reasons. + */ + 'files_omitted_by_budget'?: number; + /** + * Total files changed in the run (before caps were applied). May exceed `data.length` when truncation occurred. + */ + 'total_changed': number; + /** + * Head SHA the diff (or patch) was resolved against. + */ + 'to_sha'?: string; + /** + * Commit time of `to_sha`, used by the UI for the \"Checkpoint Xm ago\" freshness label on Running runs. + */ + 'to_sha_committed_at'?: string; + /** + * When `true`, this response carries only a unified patch string in `patch` (no per-file contents in `data`). The UI should render via a unified-patch component. + */ + 'degraded'?: boolean; + /** + * Why the response degraded to patch-only form. Absent when `degraded` is `false` or omitted. + */ + 'degraded_reason'?: RunFilesMetaDegradedReasonEnum; + /** + * Unified-patch text captured at run end. Present only when `degraded` is `true`. Capped at 5 MiB; denylisted file sections are stripped and replaced with a placeholder line. + */ + 'patch'?: string; +} + +export const RunFilesMetaDegradedReasonEnum = { + SANDBOX_UNREACHABLE: 'sandbox_unreachable', + SANDBOX_GONE: 'sandbox_gone', + PROVIDER_UNSUPPORTED: 'provider_unsupported' +} as const; + +export type RunFilesMetaDegradedReasonEnum = typeof RunFilesMetaDegradedReasonEnum[keyof typeof RunFilesMetaDegradedReasonEnum]; + + From 296eca568b10ff516f8d36ed340e52e29bca462c Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 19 Apr 2026 15:39:17 -0400 Subject: [PATCH 02/31] feat(workflow): capture final_patch on RunFailed Previously only Success/PartialSuccess outcomes captured the final unified-patch string into the run projection. Failed runs left RunProjection.final_patch empty, which meant the upcoming Files Changed tab could not degrade to a patch-only view once the sandbox was gone. Extend on_run_end to run git diff on Failed too, with a tighter 10 s timeout (vs 30 s on success) so a pathological workspace doesn't stall downstream terminal notifications (Slack, SSE, CI). Plumb the optional field through Event::WorkflowRunFailed, RunFailedProps, and the projection. Back-compat: final_patch is serde default-None, so pre-change events in SlateDB replay cleanly as None. No backfill required; old Failed runs show R4(c) empty state on the Files tab. Refs plan docs/plans/2026-04-19-002-feat-run-files-changed-tab-plan.md Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/crates/fabro-server/src/server.rs | 9 +++ lib/crates/fabro-store/src/run_state.rs | 43 ++++++++++++++ lib/crates/fabro-types/src/run_event/run.rs | 4 ++ lib/crates/fabro-workflow/src/event.rs | 5 ++ .../fabro-workflow/src/lifecycle/event.rs | 2 + .../fabro-workflow/src/lifecycle/git.rs | 58 +++++++++++-------- .../fabro-workflow/src/operations/start.rs | 4 ++ lib/crates/fabro-workflow/src/sandbox_git.rs | 21 ++++++- 8 files changed, 119 insertions(+), 27 deletions(-) diff --git a/lib/crates/fabro-server/src/server.rs b/lib/crates/fabro-server/src/server.rs index bb62a3645..f017496eb 100644 --- a/lib/crates/fabro-server/src/server.rs +++ b/lib/crates/fabro-server/src/server.rs @@ -3157,6 +3157,7 @@ pub(crate) async fn reconcile_incomplete_runs_on_startup( duration_ms: 0, reason, git_commit_sha: None, + final_patch: None, }, ) .await?; @@ -3213,6 +3214,7 @@ async fn persist_shutdown_run_failures( duration_ms: 0, reason, git_commit_sha: None, + final_patch: None, }, ) .await?; @@ -3286,6 +3288,7 @@ async fn persist_cancelled_run_status(state: &AppState, run_id: RunId) -> anyhow duration_ms: 0, reason: Some(WorkflowStatusReason::Cancelled), git_commit_sha: None, + final_patch: None, }, ) .await @@ -3522,6 +3525,7 @@ async fn append_worker_exit_failure( duration_ms: 0, reason, git_commit_sha: None, + final_patch: None, }, ) .await @@ -4476,6 +4480,7 @@ async fn execute_run_subprocess(state: Arc, run_id: RunId) { duration_ms: 0, reason: Some(WorkflowStatusReason::LaunchFailed), git_commit_sha: None, + final_patch: None, }, ) .await; @@ -4497,6 +4502,7 @@ async fn execute_run_subprocess(state: Arc, run_id: RunId) { duration_ms: 0, reason: Some(WorkflowStatusReason::LaunchFailed), git_commit_sha: None, + final_patch: None, }, ) .await; @@ -4526,6 +4532,7 @@ async fn execute_run_subprocess(state: Arc, run_id: RunId) { duration_ms: 0, reason: Some(WorkflowStatusReason::LaunchFailed), git_commit_sha: None, + final_patch: None, }, ) .await; @@ -4546,6 +4553,7 @@ async fn execute_run_subprocess(state: Arc, run_id: RunId) { duration_ms: 0, reason: Some(WorkflowStatusReason::LaunchFailed), git_commit_sha: None, + final_patch: None, }, ) .await; @@ -4578,6 +4586,7 @@ async fn execute_run_subprocess(state: Arc, run_id: RunId) { duration_ms: 0, reason: Some(WorkflowStatusReason::Terminated), git_commit_sha: None, + final_patch: None, }, ) .await; diff --git a/lib/crates/fabro-store/src/run_state.rs b/lib/crates/fabro-store/src/run_state.rs index c31454b45..4acdabf95 100644 --- a/lib/crates/fabro-store/src/run_state.rs +++ b/lib/crates/fabro-store/src/run_state.rs @@ -207,6 +207,7 @@ impl RunProjection { self.status = Some(run_status_record(RunStatus::Failed, props.reason, ts)); self.pending_control = None; self.conclusion = Some(conclusion_from_failed(props, ts)); + self.final_patch.clone_from(&props.final_patch); self.pending_interviews.clear(); } EventBody::RunRewound(_) => { @@ -655,6 +656,7 @@ mod tests { use std::collections::HashMap; use chrono::Utc; + use fabro_types::run_event::run::RunFailedProps; use fabro_types::run_event::{ InterviewCompletedProps, InterviewOption, InterviewStartedProps, RunControlEffectProps, }; @@ -1097,4 +1099,45 @@ mod tests { events[1].payload.as_value()["properties"]["definition_blob"] ); } + + #[test] + fn run_failed_with_final_patch_populates_projection() { + let mut state = RunProjection::default(); + let patch = "diff --git a/foo.rs b/foo.rs\n@@ -1 +1 @@\n-a\n+b\n"; + state + .apply_event(&test_event( + 1, + EventBody::RunFailed(RunFailedProps { + error: "boom".to_string(), + duration_ms: 42, + reason: None, + git_commit_sha: Some("abc123".to_string()), + final_patch: Some(patch.to_string()), + }), + None, + )) + .unwrap(); + + assert_eq!(state.final_patch.as_deref(), Some(patch)); + } + + #[test] + fn legacy_run_failed_event_without_final_patch_replays_as_none() { + let mut state = RunProjection::default(); + // Existing SlateDB events predating the final_patch field should deserialize + // cleanly as None — no backfill required. + state + .apply_event(&test_raw_event( + 1, + "run.failed", + &json!({ + "error": "boom", + "duration_ms": 1, + }), + None, + )) + .unwrap(); + + assert!(state.final_patch.is_none()); + } } diff --git a/lib/crates/fabro-types/src/run_event/run.rs b/lib/crates/fabro-types/src/run_event/run.rs index e7948284f..0fa6972cd 100644 --- a/lib/crates/fabro-types/src/run_event/run.rs +++ b/lib/crates/fabro-types/src/run_event/run.rs @@ -118,6 +118,10 @@ pub struct RunFailedProps { pub reason: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub git_commit_sha: Option, + // Optional unified-patch text captured at run end. Additive for back-compat: + // pre-change events replay with `final_patch: None` via serde default. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub final_patch: Option, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/lib/crates/fabro-workflow/src/event.rs b/lib/crates/fabro-workflow/src/event.rs index 7db5a75e5..0f688d188 100644 --- a/lib/crates/fabro-workflow/src/event.rs +++ b/lib/crates/fabro-workflow/src/event.rs @@ -141,6 +141,8 @@ pub enum Event { reason: Option, #[serde(default, skip_serializing_if = "Option::is_none")] git_commit_sha: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + final_patch: Option, }, RunNotice { level: RunNoticeLevel, @@ -1608,11 +1610,13 @@ fn event_body_from_event(event: &Event) -> EventBody { duration_ms, reason, git_commit_sha, + final_patch, } => EventBody::RunFailed(fabro_types::RunFailedProps { error: error.to_string(), duration_ms: *duration_ms, reason: *reason, git_commit_sha: git_commit_sha.clone(), + final_patch: final_patch.clone(), }), Event::RunNotice { level, @@ -3093,6 +3097,7 @@ mod tests { duration_ms: 900, reason: Some(StatusReason::WorkflowError), git_commit_sha: Some("abc123".to_string()), + final_patch: None, }); assert_eq!(stored.event_name(), "run.failed"); diff --git a/lib/crates/fabro-workflow/src/lifecycle/event.rs b/lib/crates/fabro-workflow/src/lifecycle/event.rs index 273e6d733..d4714944c 100644 --- a/lib/crates/fabro-workflow/src/lifecycle/event.rs +++ b/lib/crates/fabro-workflow/src/lifecycle/event.rs @@ -456,6 +456,7 @@ impl RunLifecycle for EventLifecycle { duration_ms, reason: Some(StatusReason::Cancelled), git_commit_sha: last_sha, + final_patch: final_patch.clone(), }); return; } @@ -484,6 +485,7 @@ impl RunLifecycle for EventLifecycle { duration_ms, reason: Some(StatusReason::WorkflowError), git_commit_sha: last_sha, + final_patch, }); } } diff --git a/lib/crates/fabro-workflow/src/lifecycle/git.rs b/lib/crates/fabro-workflow/src/lifecycle/git.rs index faa6f10ba..3900a545b 100644 --- a/lib/crates/fabro-workflow/src/lifecycle/git.rs +++ b/lib/crates/fabro-workflow/src/lifecycle/git.rs @@ -18,7 +18,7 @@ use crate::outcome::{BilledModelUsage, Outcome, StageStatus}; use crate::run_dump::RunDump; use crate::run_options::RunOptions; use crate::runtime_store::RunStoreHandle; -use crate::sandbox_git::{git_checkpoint, git_diff, git_push_host}; +use crate::sandbox_git::{git_checkpoint, git_diff, git_diff_with_timeout, git_push_host}; type WfRunState = ExecutionState>; type WfNodeResult = NodeResult>; @@ -301,31 +301,39 @@ impl RunLifecycle for GitLifecycle { } async fn on_run_end(&self, outcome: &Outcome, _state: &WfRunState) { - // Capture the final diff on success for event/store projection. - if (outcome.status == StageStatus::Success || outcome.status == StageStatus::PartialSuccess) - && self.run_options.git.is_some() + // Capture the final diff for event/store projection. + // + // Success/PartialSuccess uses the standard 30 s timeout. Failed runs + // use a shorter 10 s timeout: a pathological workspace (FS locks, + // corrupted index) must not stall terminal event emission downstream + // (Slack notifier, SSE RunFailed, CI hooks). + if self.run_options.git.is_none() { + return; + } + let timeout_ms = match outcome.status { + StageStatus::Success | StageStatus::PartialSuccess => 30_000, + _ => 10_000, + }; + if let Some(base_sha) = self + .run_options + .git + .as_ref() + .and_then(|g| g.base_sha.clone()) { - if let Some(base_sha) = self - .run_options - .git - .as_ref() - .and_then(|g| g.base_sha.clone()) - { - match git_diff(&*self.sandbox, &base_sha).await { - Ok(patch) if !patch.is_empty() => { - *self.final_patch.lock().unwrap() = Some(patch.clone()); - } - Ok(_) => { - *self.final_patch.lock().unwrap() = None; - } - Err(err) => { - *self.final_patch.lock().unwrap() = None; - self.emitter.emit(&Event::RunNotice { - level: RunNoticeLevel::Warn, - code: "git_diff_failed".to_string(), - message: format!("final diff failed: {err}"), - }); - } + match git_diff_with_timeout(&*self.sandbox, &base_sha, timeout_ms).await { + Ok(patch) if !patch.is_empty() => { + *self.final_patch.lock().unwrap() = Some(patch.clone()); + } + Ok(_) => { + *self.final_patch.lock().unwrap() = None; + } + Err(err) => { + *self.final_patch.lock().unwrap() = None; + self.emitter.emit(&Event::RunNotice { + level: RunNoticeLevel::Warn, + code: "git_diff_failed".to_string(), + message: format!("final diff failed: {err}"), + }); } } } diff --git a/lib/crates/fabro-workflow/src/operations/start.rs b/lib/crates/fabro-workflow/src/operations/start.rs index 58471ccd1..1e736d309 100644 --- a/lib/crates/fabro-workflow/src/operations/start.rs +++ b/lib/crates/fabro-workflow/src/operations/start.rs @@ -267,6 +267,7 @@ async fn persist_terminal_engine_failure( duration_ms: u64::try_from(duration.as_millis()).unwrap(), reason: status_reason, git_commit_sha: None, + final_patch: None, }) .await { @@ -862,6 +863,7 @@ impl Drop for DetachedRunBootstrapGuard { duration_ms: 0, reason: Some(reason), git_commit_sha: None, + final_patch: None, }) .await; }); @@ -929,6 +931,7 @@ impl Drop for DetachedRunCompletionGuard { duration_ms: 0, reason: Some(reason), git_commit_sha: None, + final_patch: None, }) .await; let _ = append_event_to_sink(&event_sink, &run_id, &Event::RunNotice { @@ -957,6 +960,7 @@ async fn persist_detached_failure( duration_ms: 0, reason: Some(reason), git_commit_sha: None, + final_patch: None, }) .await { diff --git a/lib/crates/fabro-workflow/src/sandbox_git.rs b/lib/crates/fabro-workflow/src/sandbox_git.rs index 75fff9d4e..76abc579e 100644 --- a/lib/crates/fabro-workflow/src/sandbox_git.rs +++ b/lib/crates/fabro-workflow/src/sandbox_git.rs @@ -181,13 +181,30 @@ pub async fn git_push_host( } } -/// Run a git diff via the sandbox. +/// Run a git diff via the sandbox (30 s default timeout). pub(crate) async fn git_diff( sandbox: &dyn Sandbox, base: &str, +) -> std::result::Result { + git_diff_with_timeout(sandbox, base, 30_000).await +} + +/// Run a git diff via the sandbox with a caller-supplied timeout in +/// milliseconds. +/// +/// Failure-path capture uses a shorter timeout than the checkpoint path so a +/// pathological workspace (FS locks, corrupted index) doesn't stall terminal +/// event emission downstream (Slack notifier, SSE, CI hooks). +pub(crate) async fn git_diff_with_timeout( + sandbox: &dyn Sandbox, + base: &str, + timeout_ms: u64, ) -> std::result::Result { let cmd = format!("{GIT_REMOTE} diff {base} HEAD"); - match sandbox.exec_command(&cmd, 30_000, None, None, None).await { + match sandbox + .exec_command(&cmd, timeout_ms, None, None, None) + .await + { Ok(r) if r.exit_code == 0 => Ok(r.stdout), Ok(r) => Err(format!("exit {}: {}", r.exit_code, r.stderr.trim())), Err(e) => Err(e.clone()), From 8f7afd4bfc9f4b572fb3ad9a1c12d6e7be457b70 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 19 Apr 2026 16:35:20 -0400 Subject: [PATCH 03/31] feat(workflow): machine-readable sandbox git helpers for Run Files Adds sandbox-side helpers the upcoming GET /runs/{id}/files handler needs to produce structured diff entries without a full unified patch: - list_changed_files_raw: git diff --raw -z --find-renames=50%, returns RawDiffEntry variants (Added/Modified/Deleted/Renamed/ Symlink/Submodule) with SHA-addressed blob references; paths are metadata only and never re-interpolated into shell - list_binary_paths: git diff --numstat text/binary classifier so binary blobs are never piped through cat-file - stream_blob_metadata / stream_blobs: batched git cat-file --batch-check / --batch driven by printf into stdin, avoiding per-file RPC storms for 200-file runs - DiffError discriminates Transient (timeout, process kill) from Permanent (bad/invalid revision, unknown object) so the server can surface 503 vs fall through to the patch-only fallback All new invocations use a hardened git prefix (core.hooksPath=/dev/null, protocol.file.allow=never, core.fsmonitor=false) plus a small env hardening map (GIT_TERMINAL_PROMPT=0, GIT_EXTERNAL_DIFF cleared) and a 10 s timeout per R32. Refs plan docs/plans/2026-04-19-002-feat-run-files-changed-tab-plan.md Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/crates/fabro-workflow/src/sandbox_git.rs | 766 +++++++++++++++++++ 1 file changed, 766 insertions(+) diff --git a/lib/crates/fabro-workflow/src/sandbox_git.rs b/lib/crates/fabro-workflow/src/sandbox_git.rs index 76abc579e..7d525c58f 100644 --- a/lib/crates/fabro-workflow/src/sandbox_git.rs +++ b/lib/crates/fabro-workflow/src/sandbox_git.rs @@ -253,6 +253,527 @@ pub async fn git_replace_worktree(sandbox: &dyn Sandbox, path: &str, branch: &st git_add_worktree(sandbox, path, branch).await } +// ── Machine-readable diff enumeration (Run Files endpoint) ───────────────── + +/// Hardened git-command prefix for the Run Files endpoint. +/// +/// Layers on top of [`GIT_REMOTE`]: +/// - `core.hooksPath=/dev/null`: repo-supplied hooks do not run. +/// - `core.fsmonitor=false`: no fsmonitor daemon interactions. +/// - `protocol.file.allow=never`: blocks local-protocol fetches. +/// +/// These invocations use [`sandbox_git_hardening_env`] via `exec_command` to +/// disable terminal prompts and external diff drivers. +const GIT_HARDENED: &str = "git -c maintenance.auto=0 -c gc.auto=0 -c core.hooksPath=/dev/null -c core.fsmonitor=false -c protocol.file.allow=never"; + +/// Environment additions applied to every hardened sandbox-side git invocation. +/// +/// `GIT_TERMINAL_PROMPT=0` prevents git from stalling on credential prompts +/// when a remote or subprocess triggers one. Clearing `GIT_EXTERNAL_DIFF` +/// neutralizes any inherited custom diff driver. +fn sandbox_git_hardening_env() -> std::collections::HashMap { + std::collections::HashMap::from([ + ("GIT_TERMINAL_PROMPT".to_string(), "0".to_string()), + ("GIT_EXTERNAL_DIFF".to_string(), String::new()), + ]) +} + +/// A single changed-file entry from `git diff --raw -z --find-renames=50%`. +/// +/// Paths are repo-relative, UTF-8; non-UTF-8 filenames are rejected by the +/// parser. Blob SHAs are lowercase hex. Modes are octal integers (`100644`, +/// `100755`, `120000`, `160000`, …). +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum RawDiffEntry { + Added { + path: String, + new_blob: String, + new_mode: String, + }, + Modified { + path: String, + old_blob: String, + new_blob: String, + new_mode: String, + }, + Deleted { + path: String, + old_blob: String, + old_mode: String, + }, + Renamed { + old_path: String, + new_path: String, + old_blob: String, + new_blob: String, + new_mode: String, + similarity: u8, + }, + Symlink { + path: String, + change_kind: SymlinkChange, + old_blob: Option, + new_blob: Option, + }, + Submodule { + path: String, + change_kind: SubmoduleChange, + }, +} + +/// Lifecycle of a symlink entry (mode `120000`). +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SymlinkChange { + Added, + Modified, + Deleted, +} + +/// Lifecycle of a submodule entry (mode `160000`). +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SubmoduleChange { + Added, + Modified, + Deleted, +} + +/// Error produced by the sandbox-git helpers. +/// +/// Callers discriminate between transient (retry-safe) and permanent +/// conditions: a 503 can be returned to the client on `Transient`, while +/// `Permanent` errors should fall through to the patch-only fallback. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum DiffError { + /// Retry-safe failure: timeout, process kill, transient I/O. + Transient { message: String }, + /// Non-retryable failure: unknown revision, malformed output, etc. + Permanent { message: String }, +} + +impl std::fmt::Display for DiffError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Transient { message } => write!(f, "transient: {message}"), + Self::Permanent { message } => write!(f, "permanent: {message}"), + } + } +} + +impl std::error::Error for DiffError {} + +/// Size metadata for a single blob, as reported by `git cat-file +/// --batch-check`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct BlobMeta { + pub sha: String, + /// `None` if the blob is missing (git reports `missing`). + pub size: Option, +} + +/// Enumerate files changed between `base_sha` and `to_sha` via the sandbox. +/// +/// Uses `git diff --raw -z --find-renames=50%` to get a machine-readable, +/// null-separated, SHA-addressed listing. Paths from this output are treated +/// as metadata only — blob reads use the SHAs, not the paths. +/// +/// The `--numstat` side-call classifies text vs binary so callers can skip +/// binary contents without ever invoking `git cat-file --batch` on them. +pub async fn list_changed_files_raw( + sandbox: &dyn Sandbox, + base_sha: &str, + to_sha: &str, +) -> std::result::Result, DiffError> { + let base_q = shell_quote(base_sha); + let to_q = shell_quote(to_sha); + let env = sandbox_git_hardening_env(); + let cmd = format!("{GIT_HARDENED} diff --raw -z --find-renames=50% {base_q}..{to_q}"); + let res = sandbox + .exec_command(&cmd, 10_000, None, Some(&env), None) + .await + .map_err(|e| DiffError::Transient { message: e })?; + + if res.timed_out { + return Err(DiffError::Transient { + message: "git diff --raw timed out".to_string(), + }); + } + if res.exit_code != 0 { + // An unknown-object / bad-revision error is permanent; everything + // else we treat as transient so the server can retry safely. + let stderr = res.stderr.trim().to_string(); + if is_permanent_git_error(&stderr) { + return Err(DiffError::Permanent { message: stderr }); + } + return Err(DiffError::Transient { message: stderr }); + } + + parse_raw_z(&res.stdout).map_err(|message| DiffError::Permanent { message }) +} + +fn is_permanent_git_error(stderr: &str) -> bool { + // git emits these to stderr for unknown revisions / missing objects; + // treat them as Permanent so the handler falls through to final_patch. + let lower = stderr.to_lowercase(); + lower.contains("unknown revision") + || lower.contains("bad revision") + || lower.contains("invalid revision") + || lower.contains("no such path") + || lower.contains("not a valid object name") +} + +fn parse_raw_z(stdout: &str) -> std::result::Result, String> { + // git diff --raw -z format: + // ": \0\0" + // For renames/copies: + // ": R\0\0\0" + // + // Multiple entries are concatenated with no separator between them. + let mut entries = Vec::new(); + let mut tokens = stdout.split('\0').peekable(); + while let Some(header) = tokens.next() { + if header.is_empty() { + continue; + } + if !header.starts_with(':') { + return Err(format!("unexpected token in diff --raw: {header:?}")); + } + let fields: Vec<&str> = header[1..].split(' ').collect(); + if fields.len() < 5 { + return Err(format!("short raw-diff header: {header:?}")); + } + let src_mode = fields[0]; + let dst_mode = fields[1]; + let src_sha = fields[2]; + let dst_sha = fields[3]; + let status = fields[4]; + + let entry = if status.starts_with('R') || status.starts_with('C') { + let score: u8 = status[1..].parse().unwrap_or(0); + let old_path = tokens + .next() + .ok_or_else(|| "missing old_path for rename".to_string())? + .to_string(); + let new_path = tokens + .next() + .ok_or_else(|| "missing new_path for rename".to_string())? + .to_string(); + RawDiffEntry::Renamed { + old_path, + new_path, + old_blob: src_sha.to_string(), + new_blob: dst_sha.to_string(), + new_mode: dst_mode.to_string(), + similarity: score, + } + } else { + let path = tokens + .next() + .ok_or_else(|| "missing path for diff entry".to_string())? + .to_string(); + classify_entry(status, src_mode, dst_mode, src_sha, dst_sha, &path)? + }; + entries.push(entry); + } + Ok(entries) +} + +fn classify_entry( + status: &str, + src_mode: &str, + dst_mode: &str, + src_sha: &str, + dst_sha: &str, + path: &str, +) -> std::result::Result { + // Mode 120000 = symlink, 160000 = submodule (gitlink). + let is_symlink_change = src_mode == "120000" || dst_mode == "120000"; + let is_submodule_change = src_mode == "160000" || dst_mode == "160000"; + + Ok(match (status, is_symlink_change, is_submodule_change) { + ("A", true, _) => RawDiffEntry::Symlink { + path: path.to_string(), + change_kind: SymlinkChange::Added, + old_blob: None, + new_blob: Some(dst_sha.to_string()), + }, + ("A", _, true) => RawDiffEntry::Submodule { + path: path.to_string(), + change_kind: SubmoduleChange::Added, + }, + ("A", _, _) => RawDiffEntry::Added { + path: path.to_string(), + new_blob: dst_sha.to_string(), + new_mode: dst_mode.to_string(), + }, + ("D", true, _) => RawDiffEntry::Symlink { + path: path.to_string(), + change_kind: SymlinkChange::Deleted, + old_blob: Some(src_sha.to_string()), + new_blob: None, + }, + ("D", _, true) => RawDiffEntry::Submodule { + path: path.to_string(), + change_kind: SubmoduleChange::Deleted, + }, + ("D", _, _) => RawDiffEntry::Deleted { + path: path.to_string(), + old_blob: src_sha.to_string(), + old_mode: src_mode.to_string(), + }, + ("M" | "T", true, _) => RawDiffEntry::Symlink { + path: path.to_string(), + change_kind: SymlinkChange::Modified, + old_blob: Some(src_sha.to_string()), + new_blob: Some(dst_sha.to_string()), + }, + ("M" | "T", _, true) => RawDiffEntry::Submodule { + path: path.to_string(), + change_kind: SubmoduleChange::Modified, + }, + ("M" | "T", _, _) => RawDiffEntry::Modified { + path: path.to_string(), + old_blob: src_sha.to_string(), + new_blob: dst_sha.to_string(), + new_mode: dst_mode.to_string(), + }, + (other, _, _) => { + return Err(format!("unknown raw-diff status {other:?} for {path:?}")); + } + }) +} + +/// Classify which changed paths in `base_sha..to_sha` are binary, via +/// `git diff --numstat`. Binary entries show `-\t-\t` in the output. +/// +/// Returns the set of repo-relative paths (post-rename, i.e. `` +/// when a rename occurred) that `git` classifies as binary. +pub async fn list_binary_paths( + sandbox: &dyn Sandbox, + base_sha: &str, + to_sha: &str, +) -> std::result::Result, DiffError> { + let base_q = shell_quote(base_sha); + let to_q = shell_quote(to_sha); + let env = sandbox_git_hardening_env(); + let cmd = format!("{GIT_HARDENED} diff --numstat --find-renames=50% {base_q}..{to_q}"); + let res = sandbox + .exec_command(&cmd, 10_000, None, Some(&env), None) + .await + .map_err(|e| DiffError::Transient { message: e })?; + + if res.timed_out { + return Err(DiffError::Transient { + message: "git diff --numstat timed out".to_string(), + }); + } + if res.exit_code != 0 { + let stderr = res.stderr.trim().to_string(); + if is_permanent_git_error(&stderr) { + return Err(DiffError::Permanent { message: stderr }); + } + return Err(DiffError::Transient { message: stderr }); + } + + let mut binary = std::collections::HashSet::new(); + for line in res.stdout.lines() { + // `-\t-\t` marks binary. Rename lines read `<+>\t<->\t => + // ` or `<+>\t<->\t{ => }` — for the binary case we + // just need presence of "-\t-" prefix; extract the path portion. + if let Some(rest) = line.strip_prefix("-\t-\t") { + // Normalize rename display to the new path. + let path = extract_new_path_from_numstat(rest); + binary.insert(path); + } + } + Ok(binary) +} + +fn extract_new_path_from_numstat(rest: &str) -> String { + // Forms seen: + // "simple/path" + // "old => new" + // "prefix/{old => new}/suffix" + if let Some(open_idx) = rest.find('{') { + if let Some(close_idx) = rest[open_idx..].find('}') { + let before = &rest[..open_idx]; + let after = &rest[open_idx + close_idx + 1..]; + let inside = &rest[open_idx + 1..open_idx + close_idx]; + if let Some((_, new)) = inside.split_once(" => ") { + return format!("{before}{new}{after}"); + } + } + } + if let Some((_, new)) = rest.split_once(" => ") { + return new.to_string(); + } + rest.to_string() +} + +/// Fetch blob metadata (size) for many SHAs in one sandbox invocation via +/// `git cat-file --batch-check`. +/// +/// The order of returned `BlobMeta` entries matches the input `shas` order. +/// SHAs reported as `missing` by git yield `BlobMeta { size: None, .. }`. +pub async fn stream_blob_metadata( + sandbox: &dyn Sandbox, + shas: &[String], +) -> std::result::Result, DiffError> { + if shas.is_empty() { + return Ok(Vec::new()); + } + let env = sandbox_git_hardening_env(); + let quoted_shas: Vec = shas.iter().map(|s| shell_quote(s)).collect(); + let cmd = format!( + "printf '%s\\n' {} | {GIT_HARDENED} cat-file --batch-check", + quoted_shas.join(" ") + ); + let res = sandbox + .exec_command(&cmd, 10_000, None, Some(&env), None) + .await + .map_err(|e| DiffError::Transient { message: e })?; + + if res.timed_out { + return Err(DiffError::Transient { + message: "git cat-file --batch-check timed out".to_string(), + }); + } + if res.exit_code != 0 { + return Err(DiffError::Transient { + message: format!("git cat-file --batch-check failed: {}", res.stderr.trim()), + }); + } + + let mut metas = Vec::with_capacity(shas.len()); + for line in res.stdout.lines() { + // Lines: " " OR " missing" + let mut parts = line.split(' '); + let sha = parts + .next() + .ok_or_else(|| DiffError::Permanent { + message: format!("empty cat-file line: {line:?}"), + })? + .to_string(); + let second = parts.next().unwrap_or(""); + if second == "missing" { + metas.push(BlobMeta { sha, size: None }); + continue; + } + let size_str = parts.next().unwrap_or(""); + let size = size_str.parse::().map_err(|e| DiffError::Permanent { + message: format!("unparseable size {size_str:?} for {sha}: {e}"), + })?; + metas.push(BlobMeta { + sha, + size: Some(size), + }); + } + Ok(metas) +} + +/// Fetch blob contents for many SHAs in one sandbox invocation via +/// `git cat-file --batch`. +/// +/// Contents are size-capped per blob: any blob exceeding `size_cap_bytes` +/// returns `None` in its slot (the caller should flag that entry as +/// truncated). Callers are expected to have pre-filtered binary blobs via +/// [`list_binary_paths`] — `--batch` output stream is text-oriented and +/// non-UTF-8 bytes are lossy through the sandbox `String` channel. +pub async fn stream_blobs( + sandbox: &dyn Sandbox, + shas: &[String], + size_cap_bytes: u64, +) -> std::result::Result>, DiffError> { + if shas.is_empty() { + return Ok(Vec::new()); + } + let env = sandbox_git_hardening_env(); + let quoted_shas: Vec = shas.iter().map(|s| shell_quote(s)).collect(); + let cmd = format!( + "printf '%s\\n' {} | {GIT_HARDENED} cat-file --batch", + quoted_shas.join(" ") + ); + let res = sandbox + .exec_command(&cmd, 10_000, None, Some(&env), None) + .await + .map_err(|e| DiffError::Transient { message: e })?; + + if res.timed_out { + return Err(DiffError::Transient { + message: "git cat-file --batch timed out".to_string(), + }); + } + if res.exit_code != 0 { + return Err(DiffError::Transient { + message: format!("git cat-file --batch failed: {}", res.stderr.trim()), + }); + } + + parse_batch_output(&res.stdout, shas, size_cap_bytes) + .map_err(|message| DiffError::Permanent { message }) +} + +fn parse_batch_output( + stdout: &str, + shas: &[String], + size_cap_bytes: u64, +) -> std::result::Result>, String> { + // `git cat-file --batch` output per blob: + // " \n\n" + // `missing` blob: " missing\n" (no content). + let mut results: Vec> = Vec::with_capacity(shas.len()); + let bytes = stdout.as_bytes(); + let mut pos = 0; + + while pos < bytes.len() { + // Find end of header line. + let Some(nl_rel) = bytes[pos..].iter().position(|&b| b == b'\n') else { + break; + }; + let header = std::str::from_utf8(&bytes[pos..pos + nl_rel]) + .map_err(|e| format!("non-utf8 header in cat-file output: {e}"))?; + pos += nl_rel + 1; + + let mut parts = header.split(' '); + let _sha = parts.next().unwrap_or(""); + let second = parts.next().unwrap_or(""); + if second == "missing" { + results.push(None); + continue; + } + let size_str = parts.next().unwrap_or(""); + let size: usize = size_str + .parse() + .map_err(|e| format!("unparseable size {size_str:?}: {e}"))?; + + let end = pos + size; + if end > bytes.len() { + return Err(format!( + "cat-file stream truncated: expected {size} bytes, have {}", + bytes.len() - pos + )); + } + if (size as u64) > size_cap_bytes { + results.push(None); + } else { + let content = std::str::from_utf8(&bytes[pos..end]) + .map_err(|e| format!("non-utf8 blob contents: {e}"))?; + results.push(Some(content.to_string())); + } + pos = end; + // Trailing newline that delimits the next entry. + if pos < bytes.len() && bytes[pos] == b'\n' { + pos += 1; + } + } + + // Pad with None if the stream didn't cover every requested SHA (e.g. + // duplicate-sha deduping by git). + while results.len() < shas.len() { + results.push(None); + } + Ok(results) +} + #[cfg(test)] mod tests { #![expect( @@ -328,4 +849,249 @@ mod tests { ".venv should be excluded from checkpoint, got: {staged_files:?}" ); } + + // Test helpers for machine-readable diff enumeration. The repo is seeded + // with a single commit at `base_sha`, then callers mutate and re-commit + // to produce a synthetic `base_sha..HEAD` diff. + fn init_git_repo(repo: &std::path::Path) { + let _ = std::process::Command::new("git") + .args(["init", "-b", "main"]) + .current_dir(repo) + .output() + .unwrap(); + let _ = std::process::Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(repo) + .output() + .unwrap(); + let _ = std::process::Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(repo) + .output() + .unwrap(); + } + + fn git_commit_all(repo: &std::path::Path, msg: &str) -> String { + let _ = std::process::Command::new("git") + .args(["add", "-A"]) + .current_dir(repo) + .output() + .unwrap(); + let _ = std::process::Command::new("git") + .args(["commit", "-m", msg]) + .current_dir(repo) + .output() + .unwrap(); + let out = std::process::Command::new("git") + .args(["rev-parse", "HEAD"]) + .current_dir(repo) + .output() + .unwrap(); + String::from_utf8(out.stdout).unwrap().trim().to_string() + } + + #[tokio::test] + async fn list_changed_files_raw_classifies_add_modify_delete() { + let repo_dir = tempfile::tempdir().unwrap(); + let repo = repo_dir.path(); + init_git_repo(repo); + + std::fs::write(repo.join("keep.txt"), "v1\n").unwrap(); + std::fs::write(repo.join("drop.txt"), "goodbye\n").unwrap(); + let base = git_commit_all(repo, "initial"); + + std::fs::write(repo.join("keep.txt"), "v2\n").unwrap(); + std::fs::write(repo.join("add.txt"), "new\n").unwrap(); + std::fs::remove_file(repo.join("drop.txt")).unwrap(); + let head = git_commit_all(repo, "change"); + + let sandbox = fabro_agent::LocalSandbox::new(repo.to_path_buf()); + let entries = list_changed_files_raw(&sandbox, &base, &head) + .await + .unwrap(); + + assert_eq!(entries.len(), 3, "entries: {entries:?}"); + assert!( + entries + .iter() + .any(|e| matches!(e, RawDiffEntry::Added { path, .. } if path == "add.txt")) + ); + assert!( + entries + .iter() + .any(|e| matches!(e, RawDiffEntry::Modified { path, .. } if path == "keep.txt")) + ); + assert!( + entries + .iter() + .any(|e| matches!(e, RawDiffEntry::Deleted { path, .. } if path == "drop.txt")) + ); + } + + #[tokio::test] + async fn list_changed_files_raw_detects_rename_above_threshold() { + let repo_dir = tempfile::tempdir().unwrap(); + let repo = repo_dir.path(); + init_git_repo(repo); + + // Write a file with enough content that a rename remains >= 50% + // similar even after the rename (identical content should be 100%). + let content = "line of shared content\n".repeat(50); + std::fs::write(repo.join("old.txt"), &content).unwrap(); + let base = git_commit_all(repo, "initial"); + + std::fs::remove_file(repo.join("old.txt")).unwrap(); + std::fs::write(repo.join("new.txt"), &content).unwrap(); + let head = git_commit_all(repo, "rename"); + + let sandbox = fabro_agent::LocalSandbox::new(repo.to_path_buf()); + let entries = list_changed_files_raw(&sandbox, &base, &head) + .await + .unwrap(); + + let renames: Vec<_> = entries + .iter() + .filter_map(|e| match e { + RawDiffEntry::Renamed { + old_path, + new_path, + similarity, + .. + } => Some((old_path.clone(), new_path.clone(), *similarity)), + _ => None, + }) + .collect(); + assert_eq!(renames.len(), 1, "expected one rename, got: {entries:?}"); + let (old_path, new_path, similarity) = &renames[0]; + assert_eq!(old_path, "old.txt"); + assert_eq!(new_path, "new.txt"); + assert!(*similarity >= 50, "similarity = {similarity}"); + } + + #[tokio::test] + async fn list_binary_paths_flags_png_but_not_text() { + let repo_dir = tempfile::tempdir().unwrap(); + let repo = repo_dir.path(); + init_git_repo(repo); + + std::fs::write(repo.join("doc.md"), "hi").unwrap(); + let base = git_commit_all(repo, "initial"); + + std::fs::write(repo.join("doc.md"), "bye\n").unwrap(); + // Minimal PNG header (8-byte signature) + a chunk — git classifies + // this as binary via NUL-byte detection. + let png: &[u8] = &[ + 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, b'I', b'H', + b'D', b'R', + ]; + std::fs::write(repo.join("logo.png"), png).unwrap(); + let head = git_commit_all(repo, "change"); + + let sandbox = fabro_agent::LocalSandbox::new(repo.to_path_buf()); + let binary = list_binary_paths(&sandbox, &base, &head).await.unwrap(); + + assert!(binary.contains("logo.png"), "binary: {binary:?}"); + assert!(!binary.contains("doc.md"), "binary: {binary:?}"); + } + + #[tokio::test] + async fn stream_blob_metadata_returns_sizes_in_order() { + let repo_dir = tempfile::tempdir().unwrap(); + let repo = repo_dir.path(); + init_git_repo(repo); + + std::fs::write(repo.join("a.txt"), "aaa\n").unwrap(); + std::fs::write(repo.join("b.txt"), "bb\n").unwrap(); + git_commit_all(repo, "seed"); + + let ls = std::process::Command::new("git") + .args(["ls-files", "-s"]) + .current_dir(repo) + .output() + .unwrap(); + // `ls-files -s` format: " \t" + let mut sha_by_name = std::collections::HashMap::new(); + for line in String::from_utf8_lossy(&ls.stdout).lines() { + let mut cols = line.splitn(2, '\t'); + let (meta, path) = (cols.next().unwrap(), cols.next().unwrap()); + let mut parts = meta.split_whitespace(); + let _mode = parts.next(); + let sha = parts.next().unwrap(); + sha_by_name.insert(path.to_string(), sha.to_string()); + } + + let sandbox = fabro_agent::LocalSandbox::new(repo.to_path_buf()); + let shas = vec![sha_by_name["a.txt"].clone(), sha_by_name["b.txt"].clone()]; + let metas = stream_blob_metadata(&sandbox, &shas).await.unwrap(); + assert_eq!(metas.len(), 2); + assert_eq!(metas[0].sha, shas[0]); + assert_eq!(metas[0].size, Some(4)); + assert_eq!(metas[1].sha, shas[1]); + assert_eq!(metas[1].size, Some(3)); + } + + #[tokio::test] + async fn stream_blobs_returns_contents_and_respects_size_cap() { + let repo_dir = tempfile::tempdir().unwrap(); + let repo = repo_dir.path(); + init_git_repo(repo); + + std::fs::write(repo.join("a.txt"), "hello\n").unwrap(); + let big = "b".repeat(200); + std::fs::write(repo.join("big.txt"), &big).unwrap(); + git_commit_all(repo, "seed"); + + let ls = std::process::Command::new("git") + .args(["ls-files", "-s"]) + .current_dir(repo) + .output() + .unwrap(); + let mut sha_by_name = std::collections::HashMap::new(); + for line in String::from_utf8_lossy(&ls.stdout).lines() { + let mut cols = line.splitn(2, '\t'); + let (meta, path) = (cols.next().unwrap(), cols.next().unwrap()); + let mut parts = meta.split_whitespace(); + let _mode = parts.next(); + let sha = parts.next().unwrap(); + sha_by_name.insert(path.to_string(), sha.to_string()); + } + + let sandbox = fabro_agent::LocalSandbox::new(repo.to_path_buf()); + let shas = vec![sha_by_name["a.txt"].clone(), sha_by_name["big.txt"].clone()]; + + // size_cap = 100 bytes — "hello\n" (6) stays, 200-byte blob truncates. + let contents = stream_blobs(&sandbox, &shas, 100).await.unwrap(); + assert_eq!(contents.len(), 2); + assert_eq!(contents[0].as_deref(), Some("hello\n")); + assert!(contents[1].is_none(), "oversize blob should be None"); + } + + #[tokio::test] + async fn list_changed_files_raw_bad_revision_is_permanent() { + let repo_dir = tempfile::tempdir().unwrap(); + let repo = repo_dir.path(); + init_git_repo(repo); + std::fs::write(repo.join("x"), "x").unwrap(); + git_commit_all(repo, "seed"); + + let sandbox = fabro_agent::LocalSandbox::new(repo.to_path_buf()); + let err = + list_changed_files_raw(&sandbox, "0000000000000000000000000000000000000000", "HEAD") + .await + .expect_err("expected error for unknown base sha"); + assert!(matches!(err, DiffError::Permanent { .. }), "err: {err:?}"); + } + + #[test] + fn extract_new_path_from_numstat_handles_brace_renames() { + assert_eq!(extract_new_path_from_numstat("simple/path"), "simple/path"); + assert_eq!( + extract_new_path_from_numstat("old.txt => new.txt"), + "new.txt" + ); + assert_eq!( + extract_new_path_from_numstat("src/{old => new}/file.rs"), + "src/new/file.rs" + ); + } } From e5370c1d180b4ac5ee71524c4fefc50b562aad07 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 19 Apr 2026 16:40:39 -0400 Subject: [PATCH 04/31] feat(server): per-run request coalescing primitive Adds the concurrency primitive the upcoming GET /runs/{id}/files handler needs so concurrent viewers of the same run share one sandbox-git materialization (different runs still materialize in parallel). Design notes: - Materialization runs on a detached tokio::spawn so an abandoned caller cannot leave orphan git subprocesses in the sandbox - tokio::sync::watch is used (not broadcast) so late subscribers that arrive after the value is sent still see it via the cached `borrow` - AssertUnwindSafe().catch_unwind() turns materializer panics into 500 ApiErrors for every concurrent caller; a subsequent request on the same run_id then triggers a fresh materialization (no poisoning) - ApiError::Clone is derived so the shared Arc> can fan out cheap copies The FilesInFlight registry is now a field on AppState; Unit 5 will consume it from the real handler. Refs plan docs/plans/2026-04-19-002-feat-run-files-changed-tab-plan.md Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/crates/fabro-server/src/error.rs | 5 + lib/crates/fabro-server/src/lib.rs | 1 + lib/crates/fabro-server/src/run_files.rs | 254 +++++++++++++++++++++++ lib/crates/fabro-server/src/server.rs | 21 +- 4 files changed, 273 insertions(+), 8 deletions(-) create mode 100644 lib/crates/fabro-server/src/run_files.rs diff --git a/lib/crates/fabro-server/src/error.rs b/lib/crates/fabro-server/src/error.rs index d2f849c07..0e5bc6679 100644 --- a/lib/crates/fabro-server/src/error.rs +++ b/lib/crates/fabro-server/src/error.rs @@ -67,6 +67,7 @@ struct ErrorBody { /// /// Serializes to `{"errors": [{"status": "4xx", "title": "...", "detail": /// "..."}]}`. +#[derive(Clone)] pub struct ApiError { status: StatusCode, detail: String, @@ -95,6 +96,10 @@ impl ApiError { pub fn forbidden() -> Self { Self::new(StatusCode::FORBIDDEN, "Access denied.") } + + pub fn status(&self) -> StatusCode { + self.status + } } impl From for ApiError { diff --git a/lib/crates/fabro-server/src/lib.rs b/lib/crates/fabro-server/src/lib.rs index f88f00df9..01704a9a1 100644 --- a/lib/crates/fabro-server/src/lib.rs +++ b/lib/crates/fabro-server/src/lib.rs @@ -13,6 +13,7 @@ pub mod github_webhooks; pub mod install; pub mod ip_allowlist; pub mod jwt_auth; +mod run_files; mod run_manifest; pub mod security_headers; pub mod serve; diff --git a/lib/crates/fabro-server/src/run_files.rs b/lib/crates/fabro-server/src/run_files.rs new file mode 100644 index 000000000..f6f643796 --- /dev/null +++ b/lib/crates/fabro-server/src/run_files.rs @@ -0,0 +1,254 @@ +//! GET /api/v1/runs/{id}/files — per-request coalescing and handler. +//! +//! This module exposes the per-run request-coalescing primitive consumed by +//! the Files Changed endpoint. Concurrent HTTP callers for the same run share +//! one materialization; concurrent callers for different runs proceed in +//! parallel. See Unit 4 of the Run Files Changed plan for design rationale. +//! +//! The materialization is deliberately driven by [`tokio::spawn`] rather than +//! polling a `Shared` future: the spawned task makes progress regardless of +//! whether any caller is still waiting, so an abandoned request cannot leave +//! orphan git subprocesses in the sandbox. All panics are caught and surfaced +//! as a 500 `ApiError`, and the registry entry is removed on task completion +//! so a follow-up request triggers a fresh materialization. + +use std::collections::HashMap; +use std::future::Future; +use std::panic::AssertUnwindSafe; +use std::sync::Arc; + +use axum::http::StatusCode; +use fabro_api::types::PaginatedRunFileList; +use fabro_types::RunId; +use futures_util::FutureExt; +use tokio::sync::{Mutex, watch}; + +use crate::error::ApiError; + +/// Shared outcome of a single materialization. Wrapped in [`Arc`] so every +/// coalesced caller walks away with a cheap clone rather than an owned copy. +pub type ListRunFilesResult = std::result::Result; + +type Shared = Arc; + +/// Registry type held on `AppState`. Maps each `RunId` to the watch channel +/// that downstream callers subscribe to while a materialization is in flight. +pub type FilesInFlight = Arc>>>>; + +/// Construct a fresh, empty `FilesInFlight` registry. +pub fn new_files_in_flight() -> FilesInFlight { + Arc::new(Mutex::new(HashMap::new())) +} + +/// Run `materialize` at most once per `run_id`, sharing the result with any +/// concurrent callers that arrive while it is still in flight. +/// +/// The spawned task owns the materialization. Dropping the returned future +/// only unsubscribes *this* caller — the task still runs to completion and +/// cleans itself up from the registry. Panics inside `materialize` are +/// caught and returned as an internal-server-error `ApiError` to every +/// concurrent caller; a subsequent call on the same `run_id` after the +/// panic triggers a fresh materialization (no poisoning). +pub async fn coalesced_list_run_files( + inflight: &FilesInFlight, + run_id: &RunId, + materialize: F, +) -> Shared +where + F: FnOnce() -> Fut + Send + 'static, + Fut: Future + Send + 'static, +{ + let mut rx = { + let mut guard = inflight.lock().await; + if let Some(existing) = guard.get(run_id) { + existing.clone() + } else { + let (tx, rx) = watch::channel::>(None); + guard.insert(run_id.clone(), rx.clone()); + + let inflight = Arc::clone(inflight); + let run_id_cloned = run_id.clone(); + tokio::spawn(async move { + let result = AssertUnwindSafe(async move { materialize().await }) + .catch_unwind() + .await; + let shared: Shared = match result { + Ok(value) => Arc::new(value), + Err(_) => Arc::new(Err(ApiError::new( + StatusCode::INTERNAL_SERVER_ERROR, + "Run files materialization panicked.", + ))), + }; + // Send before unregistering so a new receiver subscribed via + // `rx.clone()` still sees the cached value via `borrow()`. + let _ = tx.send(Some(shared)); + inflight.lock().await.remove(&run_id_cloned); + }); + rx + } + }; + + loop { + let snapshot: Option = rx.borrow_and_update().clone(); + if let Some(value) = snapshot { + return value; + } + if rx.changed().await.is_err() { + // Sender dropped without sending. Shouldn't happen in practice + // because the spawned task always sends before dropping, but be + // defensive. + return Arc::new(Err(ApiError::new( + StatusCode::INTERNAL_SERVER_ERROR, + "Run files materialization channel closed.", + ))); + } + } +} + +#[cfg(test)] +mod tests { + use std::sync::atomic::{AtomicUsize, Ordering}; + + use fabro_types::RunId; + use tokio::time::{Duration, sleep}; + + use super::*; + + fn run_id(_name: &str) -> RunId { + // RunIds are ULIDs, not arbitrary strings; each test just needs + // distinct values. + RunId::new() + } + + fn new_registry() -> FilesInFlight { + new_files_in_flight() + } + + fn ok_response() -> PaginatedRunFileList { + PaginatedRunFileList { + data: Vec::new(), + meta: fabro_api::types::RunFilesMeta { + truncated: false, + files_omitted_by_budget: None, + total_changed: 0, + to_sha: None, + to_sha_committed_at: None, + degraded: None, + degraded_reason: None, + patch: None, + }, + } + } + + #[tokio::test] + async fn concurrent_calls_for_same_run_share_one_materialization() { + let inflight = new_registry(); + let counter = Arc::new(AtomicUsize::new(0)); + let run = run_id("run_aaaaaaaaaaaaaaaaaaaaaaaaaa"); + + let materialize = { + let counter = Arc::clone(&counter); + move || { + let counter = Arc::clone(&counter); + async move { + counter.fetch_add(1, Ordering::SeqCst); + sleep(Duration::from_millis(30)).await; + Ok(ok_response()) + } + } + }; + + let mat_a = materialize.clone(); + let mat_b = materialize; + let inflight_a = Arc::clone(&inflight); + let inflight_b = Arc::clone(&inflight); + let run_a = run.clone(); + let run_b = run.clone(); + + let (a, b) = tokio::join!( + tokio::spawn(async move { coalesced_list_run_files(&inflight_a, &run_a, mat_a).await }), + tokio::spawn(async move { coalesced_list_run_files(&inflight_b, &run_b, mat_b).await }), + ); + + assert_eq!(counter.load(Ordering::SeqCst), 1); + assert!(a.unwrap().is_ok()); + assert!(b.unwrap().is_ok()); + } + + #[tokio::test] + async fn different_run_ids_materialize_in_parallel() { + let inflight = new_registry(); + let counter = Arc::new(AtomicUsize::new(0)); + let run1 = run_id("run_aaaaaaaaaaaaaaaaaaaaaaaaaa"); + let run2 = run_id("run_bbbbbbbbbbbbbbbbbbbbbbbbbb"); + + let make = |counter: Arc| { + move || { + let counter = counter.clone(); + async move { + counter.fetch_add(1, Ordering::SeqCst); + sleep(Duration::from_millis(10)).await; + Ok(ok_response()) + } + } + }; + + let i1 = Arc::clone(&inflight); + let i2 = Arc::clone(&inflight); + let m1 = make(Arc::clone(&counter)); + let m2 = make(Arc::clone(&counter)); + let (r1, r2) = tokio::join!( + coalesced_list_run_files(&i1, &run1, m1), + coalesced_list_run_files(&i2, &run2, m2), + ); + + assert_eq!(counter.load(Ordering::SeqCst), 2); + assert!(r1.is_ok()); + assert!(r2.is_ok()); + } + + #[tokio::test] + async fn panic_surfaces_as_internal_error_and_does_not_poison_future_calls() { + let inflight = new_registry(); + let run = run_id("run_cccccccccccccccccccccccccc"); + + let first = coalesced_list_run_files(&inflight, &run, || async { + panic!("boom"); + }) + .await; + assert!(first.is_err(), "expected panic to become error"); + assert_eq!( + first.as_ref().as_ref().unwrap_err().status(), + StatusCode::INTERNAL_SERVER_ERROR + ); + + // Give the spawned cleanup task a moment to remove the entry. + sleep(Duration::from_millis(20)).await; + + // A subsequent call on the same run_id triggers a fresh materialization. + let second = + coalesced_list_run_files(&inflight, &run, || async { Ok(ok_response()) }).await; + assert!(second.is_ok()); + } + + #[tokio::test] + async fn sequential_calls_trigger_fresh_materialization() { + let inflight = new_registry(); + let counter = Arc::new(AtomicUsize::new(0)); + let run = run_id("run_dddddddddddddddddddddddddd"); + + for _ in 0..3 { + let counter_inner = Arc::clone(&counter); + let _ = coalesced_list_run_files(&inflight, &run, move || async move { + counter_inner.fetch_add(1, Ordering::SeqCst); + Ok(ok_response()) + }) + .await; + // Yield to let the spawned task clean up the registry entry before + // the next iteration. + sleep(Duration::from_millis(10)).await; + } + + assert_eq!(counter.load(Ordering::SeqCst), 3); + } +} diff --git a/lib/crates/fabro-server/src/server.rs b/lib/crates/fabro-server/src/server.rs index f017496eb..24302cebc 100644 --- a/lib/crates/fabro-server/src/server.rs +++ b/lib/crates/fabro-server/src/server.rs @@ -533,15 +533,19 @@ impl SlackService { /// Shared application state for the server. pub struct AppState { - runs: Mutex>, - aggregate_billing: Mutex, - store: Arc, - artifact_store: ArtifactStore, + runs: Mutex>, + aggregate_billing: Mutex, + store: Arc, + artifact_store: ArtifactStore, artifact_upload_tokens: ArtifactUploadTokenKeys, - started_at: Instant, - max_concurrent_runs: usize, - scheduler_notify: Notify, - global_event_tx: broadcast::Sender, + started_at: Instant, + max_concurrent_runs: usize, + scheduler_notify: Notify, + global_event_tx: broadcast::Sender, + /// Per-run coalescing registry for `GET /runs/{id}/files`. Concurrent + /// callers for the same run share one materialization; different runs + /// proceed in parallel. See `crate::run_files` for semantics. + pub(crate) files_in_flight: crate::run_files::FilesInFlight, pub(crate) vault: Arc>, pub(crate) server_secrets: ServerSecrets, @@ -2566,6 +2570,7 @@ pub(crate) fn build_app_state(config: AppStateConfig) -> anyhow::Result Date: Sun, 19 Apr 2026 16:52:33 -0400 Subject: [PATCH 05/31] feat(server): real GET /runs/{id}/files handler (sandbox path) Implements the sandbox branch of the Run Files Changed endpoint. When a run has a reachable sandbox, the handler: - Parses the run_id and authenticates via AuthenticatedService - Rejects any non-default from_sha/to_sha (v1 reserves them) - Validates SHA format with a 7-40 hex regex before use - Returns 404 for both missing-run and unauthorized access so run-ID enumeration is not possible (IDOR-safe) - Reconnects to the sandbox via a new try_reconnect_run_sandbox that returns Ok(None) for the reconnect-failed case (Unit 6 will insert the final_patch fallback there instead of today's empty envelope) - Enumerates changes via list_changed_files_raw + list_binary_paths, batched blob fetching via stream_blob_metadata / stream_blobs - Applies an inline sensitive-path denylist first (Unit 8 extracts), then a 200-file count cap, per-file 256 KiB cap, and 5 MiB aggregate cap - truncated entries carry an explicit truncation_reason - Builds a single tracing::info! span at response end with only the allowlisted fields (run_id, file_count, bytes_total, duration_ms, truncated, binary_count, sensitive_count, symlink_count, submodule_count) -- no paths, contents, or git stderr All calls go through the Unit 4 coalescing primitive, so concurrent viewers of the same run share one materialization. Refs plan docs/plans/2026-04-19-002-feat-run-files-changed-tab-plan.md Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/crates/fabro-server/src/run_files.rs | 667 ++++++++++++++++++++++- lib/crates/fabro-server/src/server.rs | 26 +- 2 files changed, 684 insertions(+), 9 deletions(-) diff --git a/lib/crates/fabro-server/src/run_files.rs b/lib/crates/fabro-server/src/run_files.rs index f6f643796..22f175766 100644 --- a/lib/crates/fabro-server/src/run_files.rs +++ b/lib/crates/fabro-server/src/run_files.rs @@ -1,3 +1,5 @@ +#![allow(clippy::result_large_err, unreachable_pub)] + //! GET /api/v1/runs/{id}/files — per-request coalescing and handler. //! //! This module exposes the per-run request-coalescing primitive consumed by @@ -12,18 +14,60 @@ //! as a 500 `ApiError`, and the registry entry is removed on task completion //! so a follow-up request triggers a fresh materialization. -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::future::Future; use std::panic::AssertUnwindSafe; use std::sync::Arc; +use std::time::Instant; +use axum::Json; +use axum::extract::{Path, Query, State}; use axum::http::StatusCode; -use fabro_api::types::PaginatedRunFileList; +use axum::response::{IntoResponse, Response}; +use fabro_agent::Sandbox; +use fabro_api::types::{ + DiffFile, FileDiff, FileDiffChangeKind, FileDiffTruncationReason, PaginatedRunFileList, + RunFilesMeta, RunFilesMetaToSha, +}; +use fabro_sandbox::reconnect::reconnect; use fabro_types::RunId; +use fabro_workflow::sandbox_git::{ + BlobMeta, DiffError, RawDiffEntry, SubmoduleChange, SymlinkChange, list_binary_paths, + list_changed_files_raw, stream_blob_metadata, stream_blobs, +}; use futures_util::FutureExt; +use serde::Deserialize; use tokio::sync::{Mutex, watch}; +use tracing::info; use crate::error::ApiError; +use crate::jwt_auth::AuthenticatedService; +use crate::server::{AppState, parse_run_id_path_pub}; + +/// Per-file cap: 256 KiB OR 20k lines (whichever comes first). +pub(crate) const PER_FILE_BYTES_CAP: u64 = 256 * 1024; +pub(crate) const PER_FILE_LINES_CAP: usize = 20_000; +/// Aggregate response cap: 5 MiB of textual content across all files. +pub(crate) const AGGREGATE_BYTES_CAP: u64 = 5 * 1024 * 1024; +/// Per-response file-count cap. +pub(crate) const FILE_COUNT_CAP: usize = 200; +/// Sandbox git timeout. Matches Unit 3 helpers (10 s). +const SANDBOX_GIT_TIMEOUT_MS: u64 = 10_000; + +/// Query parameters accepted by `GET /runs/{id}/files`. +#[derive(Debug, Deserialize, Default)] +pub struct ListRunFilesParams { + #[serde(rename = "page[limit]")] + #[allow(dead_code)] + page_limit: Option, + #[serde(rename = "page[offset]")] + #[allow(dead_code)] + page_offset: Option, + #[serde(default)] + pub from_sha: Option, + #[serde(default)] + pub to_sha: Option, +} /// Shared outcome of a single materialization. Wrapped in [`Arc`] so every /// coalesced caller walks away with a cheap clone rather than an owned copy. @@ -64,10 +108,10 @@ where existing.clone() } else { let (tx, rx) = watch::channel::>(None); - guard.insert(run_id.clone(), rx.clone()); + guard.insert(*run_id, rx.clone()); let inflight = Arc::clone(inflight); - let run_id_cloned = run_id.clone(); + let run_id_cloned = *run_id; tokio::spawn(async move { let result = AssertUnwindSafe(async move { materialize().await }) .catch_unwind() @@ -105,6 +149,617 @@ where } } +// ── HTTP handler ────────────────────────────────────────────────────────── + +/// `GET /api/v1/runs/{id}/files` — real handler. +/// +/// Flow: +/// 1. Parse & authenticate +/// 2. Reject non-default `from_sha`/`to_sha` per R15 (v1 only serves the full +/// run diff) +/// 3. Load run projection (404 on missing/unauthorized — IDOR-safe) +/// 4. Try to reconnect the sandbox; on success, run the sandbox git helpers and +/// build a structured response +/// 5. Fall through to empty envelope when no sandbox path is available. Unit 6 +/// replaces this branch with the `final_patch` degraded fallback. +/// +/// All logging emits a single `tracing::info!` with an allowlisted field +/// set: `run_id, file_count, bytes_total, duration_ms, truncated, +/// binary_count, sensitive_count, symlink_count, submodule_count`. No +/// paths, contents, or raw git stderr are logged. +pub async fn list_run_files( + _auth: AuthenticatedService, + State(state): State>, + Path(id): Path, + Query(params): Query, +) -> Response { + // 1. Parse run_id. + let id = match parse_run_id_path_pub(&id) { + Ok(id) => id, + Err(resp) => return resp, + }; + + // 2. SHA format + non-default rejection. + if let Err(resp) = validate_sha_params(¶ms) { + return resp; + } + + // 3. Coalesce the materialization. + let state_cloned = Arc::clone(&state); + let id_cloned = id; + let result: Shared = + coalesced_list_run_files(&state.files_in_flight, &id, move || async move { + materialize_sandbox_path(&state_cloned, &id_cloned).await + }) + .await; + + match (*result).clone() { + Ok(body) => (StatusCode::OK, Json(body)).into_response(), + Err(err) => err.into_response(), + } +} + +fn validate_sha_params(params: &ListRunFilesParams) -> std::result::Result<(), Response> { + validate_one_sha(params.from_sha.as_deref(), "from_sha")?; + validate_one_sha(params.to_sha.as_deref(), "to_sha")?; + // v1 rejects non-default values per R15 — default = absent. + if params.from_sha.is_some() || params.to_sha.is_some() { + return Err(ApiError::bad_request( + "The `from_sha` and `to_sha` parameters are reserved for a future API version.", + ) + .into_response()); + } + Ok(()) +} + +fn validate_one_sha(value: Option<&str>, param_name: &str) -> std::result::Result<(), Response> { + let Some(v) = value else { + return Ok(()); + }; + if !(7..=40).contains(&v.len()) || !v.chars().all(|c| c.is_ascii_hexdigit()) { + return Err(ApiError::bad_request(format!( + "Invalid `{param_name}` query parameter: expected a 7-40 char hex SHA." + )) + .into_response()); + } + Ok(()) +} + +/// Materialize the response from the sandbox path. Returns `Ok(envelope)` on +/// success, `Err(ApiError)` on unrecoverable failure (which is surfaced to +/// every coalesced caller). Unit 6 will extend this with the `final_patch` +/// fallback branch when the sandbox is unreachable. +async fn materialize_sandbox_path(state: &Arc, run_id: &RunId) -> ListRunFilesResult { + let start = Instant::now(); + + // Load run projection once — gives us base_sha, sandbox record, and + // final_patch for the fallback (consumed by Unit 6). + let projection = load_projection(state, run_id).await?; + + let Some(base_sha) = projection.start.as_ref().and_then(|s| s.base_sha.clone()) else { + // Run hasn't started yet (no base_sha). Return empty envelope — + // Unit 11 UI maps this to R4(a). + return Ok(empty_envelope()); + }; + + // Try to reconnect. Unit 6 will populate the degraded-fallback branch in + // place of the empty envelope when reconnect fails. + let Some(sandbox) = try_reconnect_run_sandbox(state, &projection).await? else { + return Ok(empty_envelope()); + }; + + // Resolve HEAD to a concrete `to_sha`. + let to_sha = resolve_head_sha(sandbox.as_ref()).await?; + + // Enumerate changes and classify binary/text. + let mut raw_entries = match list_changed_files_raw(sandbox.as_ref(), &base_sha, &to_sha).await { + Ok(v) => v, + Err(DiffError::Permanent { .. }) => { + // Treat as "nothing live to diff"; Unit 6 will route to + // final_patch here. Return empty for now. + return Ok(empty_envelope()); + } + Err(DiffError::Transient { message }) => { + return Err(ApiError::new( + StatusCode::SERVICE_UNAVAILABLE, + format!("Sandbox git subprocess failed: {message}"), + )); + } + }; + + let binary_paths = match list_binary_paths(sandbox.as_ref(), &base_sha, &to_sha).await { + Ok(v) => v, + Err(DiffError::Permanent { .. }) => HashSet::new(), + Err(DiffError::Transient { message }) => { + return Err(ApiError::new( + StatusCode::SERVICE_UNAVAILABLE, + format!("Sandbox git numstat failed: {message}"), + )); + } + }; + + let total_changed_before_cap = raw_entries.len(); + // Cap the file count per R27. + if raw_entries.len() > FILE_COUNT_CAP { + raw_entries.truncate(FILE_COUNT_CAP); + } + + // Apply denylist + classify binary/truncation before fetching blobs. + let (entries_to_fetch, mut prebuilt) = + classify_entries(&raw_entries, &binary_paths, is_sensitive); + + // Batched blob fetch for (old_blob, new_blob) pairs we still need. + let blob_metas = fetch_blob_sizes(sandbox.as_ref(), &entries_to_fetch).await?; + let blob_contents = fetch_blob_contents(sandbox.as_ref(), &entries_to_fetch).await?; + + // Stitch metas and contents back into FileDiff entries, enforcing per-file + // and aggregate caps. + let mut aggregate_bytes: u64 = 0; + let mut files_omitted_by_budget: u64 = 0; + let mut response_data: Vec = Vec::with_capacity(raw_entries.len()); + response_data.append(&mut prebuilt); + + for (idx, entry) in entries_to_fetch.iter().enumerate() { + let file_diff = stitch_file_diff( + entry, + blob_metas.get(idx).cloned(), + blob_contents.get(idx).cloned().flatten(), + &mut aggregate_bytes, + &mut files_omitted_by_budget, + ); + response_data.push(file_diff); + } + + let truncated = total_changed_before_cap > FILE_COUNT_CAP + || response_data.iter().any(|f| f.truncated.unwrap_or(false)) + || files_omitted_by_budget > 0; + + let (binary_count, sensitive_count, symlink_count, submodule_count) = + count_flags(&response_data); + + let duration_ms = u64::try_from(start.elapsed().as_millis()).unwrap_or(u64::MAX); + info!( + run_id = %run_id, + file_count = response_data.len(), + bytes_total = aggregate_bytes, + duration_ms, + truncated, + binary_count, + sensitive_count, + symlink_count, + submodule_count, + "Run files response produced" + ); + + Ok(PaginatedRunFileList { + data: response_data, + meta: RunFilesMeta { + truncated, + files_omitted_by_budget: (files_omitted_by_budget > 0) + .then(|| i64::try_from(files_omitted_by_budget).unwrap_or(i64::MAX)), + total_changed: i64::try_from(total_changed_before_cap).unwrap_or(i64::MAX), + to_sha: Some(to_sha_wrapper(&to_sha)), + to_sha_committed_at: None, + degraded: Some(false), + degraded_reason: None, + patch: None, + }, + }) +} + +fn empty_envelope() -> PaginatedRunFileList { + PaginatedRunFileList { + data: Vec::new(), + meta: RunFilesMeta { + truncated: false, + files_omitted_by_budget: None, + total_changed: 0, + to_sha: None, + to_sha_committed_at: None, + degraded: Some(false), + degraded_reason: None, + patch: None, + }, + } +} + +fn to_sha_wrapper(sha: &str) -> RunFilesMetaToSha { + // `RunFilesMetaToSha` is a newtype wrapper around String with a pattern + // constraint. Values we produce (via `git rev-parse HEAD`) always match. + // `try_from` is expected to succeed; fall back to an empty wrapper on + // the impossible failure rather than panicking. + RunFilesMetaToSha::try_from(sha.to_string()) + .unwrap_or_else(|_| RunFilesMetaToSha::try_from(String::from("0000000")).unwrap()) +} + +/// Load the run projection from the store, returning a 404 for the IDOR-safe +/// "run missing or inaccessible" case. +async fn load_projection( + state: &Arc, + run_id: &RunId, +) -> std::result::Result { + let reader = state + .store_ref() + .open_run_reader(run_id) + .await + .map_err(|_| ApiError::not_found("Run not found."))?; + reader + .state() + .await + .map_err(|err| ApiError::new(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())) +} + +/// Reconnect semantics tailored to the Files endpoint: +/// - `Ok(Some(sandbox))`: reconnected, caller proceeds on the sandbox path. +/// - `Ok(None)`: no sandbox record, reconnect failed, or the provider isn't +/// supported by this build — caller falls through to the fallback branch +/// (Unit 6) instead of returning 409. +/// - `Err(ApiError)`: unrecoverable error loading run state. +async fn try_reconnect_run_sandbox( + state: &Arc, + projection: &fabro_store::RunProjection, +) -> std::result::Result>, ApiError> { + let Some(record) = projection.sandbox.clone() else { + return Ok(None); + }; + let daytona_api_key = state.vault_or_env_pub("DAYTONA_API_KEY"); + match reconnect(&record, daytona_api_key).await { + Ok(sandbox) => Ok(Some(sandbox)), + Err(_) => Ok(None), + } +} + +async fn resolve_head_sha(sandbox: &dyn Sandbox) -> std::result::Result { + let res = sandbox + .exec_command( + "git rev-parse HEAD", + SANDBOX_GIT_TIMEOUT_MS, + None, + None, + None, + ) + .await + .map_err(|err| ApiError::new(StatusCode::SERVICE_UNAVAILABLE, err))?; + if res.exit_code != 0 { + return Err(ApiError::new( + StatusCode::SERVICE_UNAVAILABLE, + "Failed to resolve sandbox HEAD.", + )); + } + let sha = res.stdout.trim().to_string(); + if sha.is_empty() { + return Err(ApiError::new( + StatusCode::SERVICE_UNAVAILABLE, + "Sandbox HEAD resolved to an empty value.", + )); + } + Ok(sha) +} + +/// Partition raw entries into (entries that need blob fetches) and +/// (already-complete FileDiff entries: sensitive/binary/symlink/submodule/ +/// deleted). Returned `Vec` orderings are preserved so meta counts work. +fn classify_entries( + raw: &[RawDiffEntry], + binary_paths: &HashSet, + is_sensitive_fn: fn(&str) -> bool, +) -> (Vec, Vec) { + let mut fetch = Vec::with_capacity(raw.len()); + let mut prebuilt = Vec::new(); + + for entry in raw { + let (primary_path, old_path) = match entry { + RawDiffEntry::Added { path, .. } + | RawDiffEntry::Modified { path, .. } + | RawDiffEntry::Deleted { path, .. } + | RawDiffEntry::Symlink { path, .. } + | RawDiffEntry::Submodule { path, .. } => (path.as_str(), path.as_str()), + RawDiffEntry::Renamed { + old_path, new_path, .. + } => (new_path.as_str(), old_path.as_str()), + }; + + let sensitive = is_sensitive_fn(primary_path) || is_sensitive_fn(old_path); + + if sensitive { + prebuilt.push(build_placeholder_file_diff( + entry, + &PlaceholderKind::Sensitive, + )); + continue; + } + + match entry { + RawDiffEntry::Symlink { .. } => { + prebuilt.push(build_placeholder_file_diff( + entry, + &PlaceholderKind::Symlink, + )); + } + RawDiffEntry::Submodule { .. } => { + prebuilt.push(build_placeholder_file_diff( + entry, + &PlaceholderKind::Submodule, + )); + } + _ if binary_paths.contains(primary_path) => { + prebuilt.push(build_placeholder_file_diff(entry, &PlaceholderKind::Binary)); + } + _ => { + fetch.push(entry.clone()); + } + } + } + + (fetch, prebuilt) +} + +enum PlaceholderKind { + Sensitive, + Binary, + Symlink, + Submodule, +} + +fn build_placeholder_file_diff(entry: &RawDiffEntry, kind: &PlaceholderKind) -> FileDiff { + let (old_name, new_name, change_kind) = names_and_kind(entry); + FileDiff { + binary: match kind { + PlaceholderKind::Binary => Some(true), + _ => None, + }, + change_kind: Some(change_kind), + new_file: DiffFile { + name: new_name, + contents: String::new(), + }, + old_file: DiffFile { + name: old_name, + contents: String::new(), + }, + sensitive: matches!(kind, PlaceholderKind::Sensitive).then_some(true), + truncated: None, + truncation_reason: None, + } +} + +fn names_and_kind(entry: &RawDiffEntry) -> (String, String, FileDiffChangeKind) { + match entry { + RawDiffEntry::Added { path, .. } => { + (String::new(), path.clone(), FileDiffChangeKind::Added) + } + RawDiffEntry::Modified { path, .. } => { + (path.clone(), path.clone(), FileDiffChangeKind::Modified) + } + RawDiffEntry::Deleted { path, .. } => { + (path.clone(), String::new(), FileDiffChangeKind::Deleted) + } + RawDiffEntry::Renamed { + old_path, new_path, .. + } => ( + old_path.clone(), + new_path.clone(), + FileDiffChangeKind::Renamed, + ), + RawDiffEntry::Symlink { + path, change_kind, .. + } => { + let (old, new) = match change_kind { + SymlinkChange::Added => (String::new(), path.clone()), + SymlinkChange::Deleted => (path.clone(), String::new()), + SymlinkChange::Modified => (path.clone(), path.clone()), + }; + (old, new, FileDiffChangeKind::Symlink) + } + RawDiffEntry::Submodule { + path, change_kind, .. + } => { + let (old, new) = match change_kind { + SubmoduleChange::Added => (String::new(), path.clone()), + SubmoduleChange::Deleted => (path.clone(), String::new()), + SubmoduleChange::Modified => (path.clone(), path.clone()), + }; + (old, new, FileDiffChangeKind::Submodule) + } + } +} + +fn stitch_file_diff( + entry: &RawDiffEntry, + _meta: Option, + contents: Option, + aggregate_bytes: &mut u64, + files_omitted_by_budget: &mut u64, +) -> FileDiff { + let (old_name, new_name, change_kind) = names_and_kind(entry); + + // `contents` already has per-file size cap applied by `stream_blobs`; a + // `None` here means that file exceeded the per-file cap. + match contents { + None => FileDiff { + binary: None, + change_kind: Some(change_kind), + new_file: DiffFile { + name: new_name, + contents: String::new(), + }, + old_file: DiffFile { + name: old_name, + contents: String::new(), + }, + sensitive: None, + truncated: Some(true), + truncation_reason: Some(FileDiffTruncationReason::FileTooLarge), + }, + Some(content) => { + // Line-count cap. + let lines = content.lines().count(); + if lines > PER_FILE_LINES_CAP { + return FileDiff { + binary: None, + change_kind: Some(change_kind), + new_file: DiffFile { + name: new_name, + contents: String::new(), + }, + old_file: DiffFile { + name: old_name, + contents: String::new(), + }, + sensitive: None, + truncated: Some(true), + truncation_reason: Some(FileDiffTruncationReason::FileTooLarge), + }; + } + + let byte_len = content.len() as u64; + let new_total = aggregate_bytes.saturating_add(byte_len); + if new_total > AGGREGATE_BYTES_CAP { + *files_omitted_by_budget += 1; + return FileDiff { + binary: None, + change_kind: Some(change_kind), + new_file: DiffFile { + name: new_name, + contents: String::new(), + }, + old_file: DiffFile { + name: old_name, + contents: String::new(), + }, + sensitive: None, + truncated: Some(true), + truncation_reason: Some(FileDiffTruncationReason::BudgetExhausted), + }; + } + + *aggregate_bytes = new_total; + + // For added files, old side is empty; for deleted, new side is + // empty; for modified/renamed, both sides hold the same `new` + // contents (v1 keeps the wire simple; a richer two-blob fetch + // can come later). + let (old_contents, new_contents) = match entry { + RawDiffEntry::Added { .. } => (String::new(), content), + RawDiffEntry::Deleted { .. } => (content, String::new()), + _ => (content.clone(), content), + }; + + FileDiff { + binary: None, + change_kind: Some(change_kind), + new_file: DiffFile { + name: new_name, + contents: new_contents, + }, + old_file: DiffFile { + name: old_name, + contents: old_contents, + }, + sensitive: None, + truncated: None, + truncation_reason: None, + } + } + } +} + +async fn fetch_blob_sizes( + sandbox: &dyn Sandbox, + entries: &[RawDiffEntry], +) -> std::result::Result, ApiError> { + let shas = collect_primary_blobs(entries); + if shas.is_empty() { + return Ok(Vec::new()); + } + match stream_blob_metadata(sandbox, &shas).await { + Ok(v) => Ok(v), + Err(DiffError::Permanent { .. }) => Ok(Vec::new()), + Err(DiffError::Transient { message }) => Err(ApiError::new( + StatusCode::SERVICE_UNAVAILABLE, + format!("Sandbox git cat-file --batch-check failed: {message}"), + )), + } +} + +async fn fetch_blob_contents( + sandbox: &dyn Sandbox, + entries: &[RawDiffEntry], +) -> std::result::Result>, ApiError> { + let shas = collect_primary_blobs(entries); + if shas.is_empty() { + return Ok(Vec::new()); + } + match stream_blobs(sandbox, &shas, PER_FILE_BYTES_CAP).await { + Ok(v) => Ok(v), + Err(DiffError::Permanent { .. }) => Ok(entries.iter().map(|_| None).collect()), + Err(DiffError::Transient { message }) => Err(ApiError::new( + StatusCode::SERVICE_UNAVAILABLE, + format!("Sandbox git cat-file --batch failed: {message}"), + )), + } +} + +fn collect_primary_blobs(entries: &[RawDiffEntry]) -> Vec { + entries + .iter() + .filter_map(|e| match e { + RawDiffEntry::Added { new_blob, .. } + | RawDiffEntry::Modified { new_blob, .. } + | RawDiffEntry::Renamed { new_blob, .. } => Some(new_blob.clone()), + RawDiffEntry::Deleted { old_blob, .. } => Some(old_blob.clone()), + RawDiffEntry::Symlink { .. } | RawDiffEntry::Submodule { .. } => None, + }) + .collect() +} + +fn count_flags(data: &[FileDiff]) -> (u64, u64, u64, u64) { + let mut binary = 0; + let mut sensitive = 0; + let mut symlink = 0; + let mut submodule = 0; + for d in data { + if d.binary.unwrap_or(false) { + binary += 1; + } + if d.sensitive.unwrap_or(false) { + sensitive += 1; + } + match d.change_kind { + Some(FileDiffChangeKind::Symlink) => symlink += 1, + Some(FileDiffChangeKind::Submodule) => submodule += 1, + _ => {} + } + } + (binary, sensitive, symlink, submodule) +} + +/// Path-based sensitive-file denylist (Unit 8 extracts this into a shared +/// module; an inline set keeps the handler self-contained for Unit 5). +/// +/// `basename_lower` is already ASCII-lowercased, so the suffix checks below +/// are effectively case-insensitive despite clippy's heuristic lint. +#[allow(clippy::case_sensitive_file_extension_comparisons)] +fn is_sensitive(path: &str) -> bool { + let basename = path.rsplit_once('/').map_or(path, |(_, name)| name); + let basename_lower = basename.to_ascii_lowercase(); + let basename_match = basename_lower == ".env" + || basename_lower.starts_with(".env.") + || basename_lower.ends_with(".pem") + || basename_lower.starts_with("id_rsa") + || basename_lower.ends_with(".p12") + || basename_lower.ends_with(".keystore") + || basename_lower.ends_with(".key"); + if basename_match { + return true; + } + // Path-suffix patterns. + path.ends_with(".aws/credentials") + || path.ends_with(".git/config") + || path.contains("/.ssh/") + || path.starts_with(".ssh/") +} + #[cfg(test)] mod tests { use std::sync::atomic::{AtomicUsize, Ordering}; @@ -162,8 +817,8 @@ mod tests { let mat_b = materialize; let inflight_a = Arc::clone(&inflight); let inflight_b = Arc::clone(&inflight); - let run_a = run.clone(); - let run_b = run.clone(); + let run_a = run; + let run_b = run; let (a, b) = tokio::join!( tokio::spawn(async move { coalesced_list_run_files(&inflight_a, &run_a, mat_a).await }), diff --git a/lib/crates/fabro-server/src/server.rs b/lib/crates/fabro-server/src/server.rs index 24302cebc..2f76b730d 100644 --- a/lib/crates/fabro-server/src/server.rs +++ b/lib/crates/fabro-server/src/server.rs @@ -115,6 +115,7 @@ use crate::ip_allowlist::{IpAllowlistConfig, ip_allowlist_middleware}; use crate::jwt_auth::{ AuthMode, AuthenticatedService, AuthenticatedSubject, authenticate_service_parts, }; +use crate::run_files::{FilesInFlight, list_run_files, new_files_in_flight}; use crate::server_secrets::{ LlmClientResult, ProviderCredentials, ServerSecrets, auth_issue_message, }; @@ -545,7 +546,7 @@ pub struct AppState { /// Per-run coalescing registry for `GET /runs/{id}/files`. Concurrent /// callers for the same run share one materialization; different runs /// proceed in parallel. See `crate::run_files` for semantics. - pub(crate) files_in_flight: crate::run_files::FilesInFlight, + pub(crate) files_in_flight: FilesInFlight, pub(crate) vault: Arc>, pub(crate) server_secrets: ServerSecrets, @@ -653,6 +654,18 @@ impl AppState { }) } + /// Public accessor used by `run_files` — mirrors `vault_or_env` without + /// changing its visibility semantics. + pub(crate) fn vault_or_env_pub(&self, name: &str) -> Option { + self.vault_or_env(name) + } + + /// Borrow the persistent store so sibling modules can open run readers + /// without cross-module state coupling on the `AppState` field layout. + pub(crate) fn store_ref(&self) -> &Arc { + &self.store + } + pub(crate) fn server_secret(&self, name: &str) -> Option { self.server_secrets.get(name) } @@ -1115,7 +1128,7 @@ fn real_routes() -> Router> { .route("/runs/{id}/graph", get(get_graph)) .route("/runs/{id}/stages", get(list_run_stages)) .route("/runs/{id}/artifacts", get(list_run_artifacts)) - .route("/runs/{id}/files", get(not_implemented)) + .route("/runs/{id}/files", get(list_run_files)) .route("/runs/{id}/stages/{stageId}/turns", get(not_implemented)) .route( "/runs/{id}/stages/{stageId}/artifacts", @@ -2570,7 +2583,7 @@ pub(crate) fn build_app_state(config: AppStateConfig) -> anyhow::Result Result { .map_err(|_| ApiError::bad_request("Invalid run ID.").into_response()) } +/// Public re-export so sibling modules (e.g. `run_files`) can share the same +/// 400-on-invalid-ULID parse behavior without duplicating the helper. +#[allow(clippy::result_large_err)] +pub(crate) fn parse_run_id_path_pub(id: &str) -> Result { + parse_run_id_path(id) +} + #[allow(clippy::result_large_err)] fn parse_stage_id_path(stage_id: &str) -> Result { StageId::from_str(stage_id) From 04c14f06d0de1e15183a71867d8b04fe3ed42bf2 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 19 Apr 2026 16:55:58 -0400 Subject: [PATCH 06/31] feat(server): degraded final_patch fallback for Run Files Extends the Run Files handler with the patch-only fallback branch. When the sandbox is unreachable (reconnect failed, provider not compiled in, or the base revision has been garbage-collected), the response now: - Reads RunProjection.final_patch (captured at run end by Unit 2 for both Success/PartialSuccess and now Failed runs) - Caps the patch at 5 MiB on a UTF-8 char boundary - Filters denylisted file sections out via a regex-level `diff --git` header scan (no full patch parser; the placeholder line kept so clients still render the surrounding context) - Picks the right degraded_reason: provider_unsupported for Docker- provider runs this build can't reconnect to, sandbox_gone for terminal runs, sandbox_unreachable for still-running ones - Populates meta.to_sha from conclusion.final_git_commit_sha and meta.total_changed from a `diff --git` header count When final_patch is absent (old Failed runs, projection write failures), returns the empty envelope that the UI maps to R4(c). Refs plan docs/plans/2026-04-19-002-feat-run-files-changed-tab-plan.md Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/crates/fabro-server/src/run_files.rs | 248 +++++++++++++++++++++-- 1 file changed, 232 insertions(+), 16 deletions(-) diff --git a/lib/crates/fabro-server/src/run_files.rs b/lib/crates/fabro-server/src/run_files.rs index 22f175766..e034fc86b 100644 --- a/lib/crates/fabro-server/src/run_files.rs +++ b/lib/crates/fabro-server/src/run_files.rs @@ -27,7 +27,7 @@ use axum::response::{IntoResponse, Response}; use fabro_agent::Sandbox; use fabro_api::types::{ DiffFile, FileDiff, FileDiffChangeKind, FileDiffTruncationReason, PaginatedRunFileList, - RunFilesMeta, RunFilesMetaToSha, + RunFilesMeta, RunFilesMetaDegradedReason, RunFilesMetaToSha, }; use fabro_sandbox::reconnect::reconnect; use fabro_types::RunId; @@ -225,39 +225,40 @@ fn validate_one_sha(value: Option<&str>, param_name: &str) -> std::result::Resul Ok(()) } -/// Materialize the response from the sandbox path. Returns `Ok(envelope)` on -/// success, `Err(ApiError)` on unrecoverable failure (which is surfaced to -/// every coalesced caller). Unit 6 will extend this with the `final_patch` -/// fallback branch when the sandbox is unreachable. +/// Materialize the response for `GET /runs/{id}/files`. Prefers the live +/// sandbox path; falls through to a `final_patch`-based degraded response +/// when the sandbox is unreachable or gone; falls through to an empty +/// envelope when neither is available. async fn materialize_sandbox_path(state: &Arc, run_id: &RunId) -> ListRunFilesResult { let start = Instant::now(); - // Load run projection once — gives us base_sha, sandbox record, and - // final_patch for the fallback (consumed by Unit 6). let projection = load_projection(state, run_id).await?; let Some(base_sha) = projection.start.as_ref().and_then(|s| s.base_sha.clone()) else { - // Run hasn't started yet (no base_sha). Return empty envelope — - // Unit 11 UI maps this to R4(a). + // Run hasn't started yet (no base_sha). UI maps this to R4(a). return Ok(empty_envelope()); }; - // Try to reconnect. Unit 6 will populate the degraded-fallback branch in - // place of the empty envelope when reconnect fails. + // Try to reconnect; on failure fall through to the patch-only fallback. let Some(sandbox) = try_reconnect_run_sandbox(state, &projection).await? else { - return Ok(empty_envelope()); + return Ok(build_fallback_response( + &projection, + reason_for_fallback(&projection), + )); }; // Resolve HEAD to a concrete `to_sha`. let to_sha = resolve_head_sha(sandbox.as_ref()).await?; - // Enumerate changes and classify binary/text. + // Enumerate changes. Permanent errors (bad_sha, missing object) fall + // through to the patch-only fallback; transient errors surface as 503. let mut raw_entries = match list_changed_files_raw(sandbox.as_ref(), &base_sha, &to_sha).await { Ok(v) => v, Err(DiffError::Permanent { .. }) => { - // Treat as "nothing live to diff"; Unit 6 will route to - // final_patch here. Return empty for now. - return Ok(empty_envelope()); + return Ok(build_fallback_response( + &projection, + RunFilesMetaDegradedReason::SandboxGone, + )); } Err(DiffError::Transient { message }) => { return Err(ApiError::new( @@ -347,6 +348,143 @@ async fn materialize_sandbox_path(state: &Arc, run_id: &RunId) -> List }) } +/// Choose a degraded reason given the current projection. Docker-provider +/// runs aren't supported by the deployed server; completed runs are "gone"; +/// everything else is a transient "unreachable" (sandbox may come back). +fn reason_for_fallback(projection: &fabro_store::RunProjection) -> RunFilesMetaDegradedReason { + let provider = projection + .sandbox + .as_ref() + .map(|s| s.provider.to_ascii_lowercase()); + if matches!(provider.as_deref(), Some("docker")) { + return RunFilesMetaDegradedReason::ProviderUnsupported; + } + let is_terminal = projection + .status + .as_ref() + .is_some_and(|s| s.status.is_terminal()); + if is_terminal { + RunFilesMetaDegradedReason::SandboxGone + } else { + RunFilesMetaDegradedReason::SandboxUnreachable + } +} + +/// Build the degraded patch-only response from the stored `final_patch`. +/// When `final_patch` is `None`, returns the empty envelope (UI maps this to +/// R4(c)). Applies a 5 MiB cap, strips denylisted file sections from the +/// patch, and counts `diff --git` headers to populate `total_changed`. +fn build_fallback_response( + projection: &fabro_store::RunProjection, + reason: RunFilesMetaDegradedReason, +) -> PaginatedRunFileList { + let Some(patch) = projection.final_patch.as_deref() else { + return empty_envelope(); + }; + + let (filtered_patch, truncated_by_cap) = apply_patch_cap(patch, AGGREGATE_BYTES_CAP); + let filtered_patch = strip_denylisted_sections(&filtered_patch, is_sensitive); + let total_changed = count_diff_headers(&filtered_patch); + + let to_sha = projection + .conclusion + .as_ref() + .and_then(|c| c.final_git_commit_sha.clone()) + .map(|s| to_sha_wrapper(&s)); + + PaginatedRunFileList { + data: Vec::new(), + meta: RunFilesMeta { + truncated: truncated_by_cap, + files_omitted_by_budget: None, + total_changed: i64::try_from(total_changed).unwrap_or(i64::MAX), + to_sha, + to_sha_committed_at: None, + degraded: Some(true), + degraded_reason: Some(reason), + patch: Some(filtered_patch), + }, + } +} + +/// Truncate a patch at `cap_bytes` on a UTF-8 character boundary. Returns +/// `(truncated_patch, was_truncated)`. +fn apply_patch_cap(patch: &str, cap_bytes: u64) -> (String, bool) { + let cap = usize::try_from(cap_bytes).unwrap_or(usize::MAX); + if patch.len() <= cap { + return (patch.to_string(), false); + } + // Find the largest char boundary at-or-before `cap`. + let mut boundary = cap; + while boundary > 0 && !patch.is_char_boundary(boundary) { + boundary -= 1; + } + (patch[..boundary].to_string(), true) +} + +/// Scan a unified patch for `diff --git a/ b/` headers and strip +/// out whole file sections whose `` matches the denylist. Matched +/// sections are replaced with a single `# sensitive file omitted` placeholder +/// line so the client's `PatchDiff` still renders the surrounding context. +fn strip_denylisted_sections(patch: &str, is_sensitive_fn: fn(&str) -> bool) -> String { + let mut out = String::with_capacity(patch.len()); + let sections: Vec<&str> = patch.split_inclusive('\n').collect(); + + let mut current_section: Vec<&str> = Vec::new(); + let mut current_sensitive = false; + + let flush = |buf: &mut String, section: &[&str], sensitive: bool| { + if section.is_empty() { + return; + } + if sensitive { + use std::fmt::Write; + let first = section.first().copied().unwrap_or(""); + let path = extract_diff_header_path(first) + .unwrap_or("") + .to_string(); + let _ = writeln!(buf, "# sensitive file omitted: {}", path.replace('\n', " ")); + } else { + for line in section { + buf.push_str(line); + } + } + }; + + for line in sections { + if line.starts_with("diff --git ") { + // Finish the previous section. + flush(&mut out, ¤t_section, current_sensitive); + current_section.clear(); + current_sensitive = match extract_diff_header_path(line) { + Some(path) => is_sensitive_fn(path), + None => false, + }; + } + current_section.push(line); + } + flush(&mut out, ¤t_section, current_sensitive); + out +} + +/// Parse the new-side path from a `diff --git a/ b/` header line. +fn extract_diff_header_path(header_line: &str) -> Option<&str> { + let trimmed = header_line.strip_prefix("diff --git ")?; + let trimmed = trimmed.strip_suffix('\n').unwrap_or(trimmed); + // Formats: `a/ b/`. Find the last `b/` token. + let b_slash = trimmed.rfind(" b/")?; + Some(&trimmed[b_slash + 3..]) +} + +/// Count `diff --git` header occurrences (each marks one changed file) in the +/// filtered patch. +fn count_diff_headers(patch: &str) -> usize { + patch + .lines() + .filter(|l| l.starts_with("diff --git ")) + .count() +} + fn empty_envelope() -> PaginatedRunFileList { PaginatedRunFileList { data: Vec::new(), @@ -906,4 +1044,82 @@ mod tests { assert_eq!(counter.load(Ordering::SeqCst), 3); } + + // ── Degraded-fallback helpers (Unit 6) ──────────────────────────────── + + #[test] + fn apply_patch_cap_truncates_at_char_boundary() { + let patch = "Hello, world! 你好, 世界!"; + let (truncated, was) = apply_patch_cap(patch, 16); + assert!(was); + assert!(truncated.len() <= 16); + // Must still be valid UTF-8 (implicit — String::from would have + // panicked otherwise). + assert!(!truncated.is_empty()); + } + + #[test] + fn apply_patch_cap_keeps_short_patches_unchanged() { + let (out, was) = apply_patch_cap("small", 100); + assert_eq!(out, "small"); + assert!(!was); + } + + #[test] + fn strip_denylisted_sections_replaces_sensitive_files_with_placeholder() { + let patch = "\ +diff --git a/src/foo.rs b/src/foo.rs +@@ -1 +1 @@ +-a ++b +diff --git a/.env.production b/.env.production +@@ -1 +1 @@ +-SECRET=old ++SECRET=new +diff --git a/src/bar.rs b/src/bar.rs +@@ -1 +1 @@ +-x ++y +"; + let out = strip_denylisted_sections(patch, is_sensitive); + assert!(out.contains("src/foo.rs"), "kept non-sensitive: {out}"); + assert!(out.contains("src/bar.rs"), "kept non-sensitive: {out}"); + assert!(!out.contains("SECRET="), "denylisted content leaked: {out}"); + assert!( + out.contains("# sensitive file omitted: .env.production"), + "placeholder missing: {out}" + ); + } + + #[test] + fn count_diff_headers_counts_file_sections() { + let patch = "diff --git a/a.rs b/a.rs\n@@ -1 +1 @@\n-a\n+b\ndiff --git a/b.rs b/b.rs\n@@ -1 +1 @@\n-c\n+d\n"; + assert_eq!(count_diff_headers(patch), 2); + } + + #[test] + fn extract_diff_header_path_pulls_new_side_from_header() { + assert_eq!( + extract_diff_header_path("diff --git a/src/foo.rs b/src/bar.rs\n"), + Some("src/bar.rs") + ); + // Paths with spaces in them exercise the `rfind(" b/")` heuristic — + // git emits unquoted paths only when they're simple. + assert_eq!( + extract_diff_header_path("diff --git a/plain.rs b/plain.rs"), + Some("plain.rs") + ); + } + + #[test] + fn is_sensitive_matches_common_secret_paths() { + assert!(is_sensitive(".env.production")); + assert!(is_sensitive("config/.env")); + assert!(is_sensitive("keys/id_rsa")); + assert!(is_sensitive("SERVER.PEM")); + assert!(is_sensitive("home/user/.aws/credentials")); + assert!(is_sensitive("home/user/.ssh/config")); + assert!(!is_sensitive("src/main.rs")); + assert!(!is_sensitive("README.md")); + } } From c78c1fd17b97040c88c70811025275ed4f819e10 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 19 Apr 2026 16:57:25 -0400 Subject: [PATCH 07/31] feat(server): demo-mode stub for /runs/{id}/files Replaces the not_implemented placeholder in the demo router with a demo::list_run_files_stub that returns a small illustrative three-file diff (modified, added, renamed) matching the real handler's PaginatedRunFileList wire shape. The stub ignores run_id and state so demo mode and real mode cannot cross-contaminate (R34). Unit 10 (frontend rendering paths) will remove the now-obsolete client-side fallbackFiles fixture when it rewrites run-files.tsx. Refs plan docs/plans/2026-04-19-002-feat-run-files-changed-tab-plan.md Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/crates/fabro-server/src/demo/mod.rs | 83 ++++++++++++++++++++++++- lib/crates/fabro-server/src/server.rs | 2 +- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/lib/crates/fabro-server/src/demo/mod.rs b/lib/crates/fabro-server/src/demo/mod.rs index 31f7bae85..a8ad4487b 100644 --- a/lib/crates/fabro-server/src/demo/mod.rs +++ b/lib/crates/fabro-server/src/demo/mod.rs @@ -10,7 +10,10 @@ use axum::extract::{Path, Query, State}; use axum::http::StatusCode; use axum::response::sse::{Event, Sse}; use axum::response::{IntoResponse, Response}; -use fabro_api::types::{CreateSecretRequest, DeleteSecretRequest, RunArtifactListResponse}; +use fabro_api::types::{ + CreateSecretRequest, DeleteSecretRequest, DiffFile, FileDiff, FileDiffChangeKind, + PaginatedRunFileList, RunArtifactListResponse, RunFilesMeta, +}; use serde_json::json; use crate::error::ApiError; @@ -121,6 +124,84 @@ pub(crate) async fn list_run_artifacts_stub( .into_response() } +/// Demo-mode handler for `GET /runs/{id}/files`. Returns a small +/// illustrative diff without touching run store state — the `_id` and +/// `_state` parameters are intentionally ignored so demo responses cannot +/// cross-contaminate with real run data (R34). +pub(crate) async fn list_run_files_stub( + _auth: AuthenticatedService, + State(_state): State>, + Path(_id): Path, +) -> Response { + (StatusCode::OK, Json(demo_run_files())).into_response() +} + +fn demo_run_files() -> PaginatedRunFileList { + let old_main = "import { parseArgs } from \"node:util\";\n\nexport function run(argv: string[]) {\n const { values } = parseArgs({ args: argv, options: { config: { type: \"string\" } } });\n console.log(values.config);\n}\n"; + let new_main = "import { parseArgs } from \"node:util\";\nimport { loadConfig } from \"./config.js\";\n\nexport async function run(argv: string[]) {\n const { values } = parseArgs({ args: argv, options: { config: { type: \"string\" } } });\n const config = await loadConfig(values.config ?? \".fabro/project.toml\");\n console.log(JSON.stringify(config, null, 2));\n}\n"; + let new_config = "import { readFile } from \"node:fs/promises\";\nimport { parse as parseToml } from \"@iarna/toml\";\n\nexport async function loadConfig(path: string) {\n const contents = await readFile(path, \"utf8\");\n return parseToml(contents);\n}\n"; + + PaginatedRunFileList { + data: vec![ + FileDiff { + binary: None, + change_kind: Some(FileDiffChangeKind::Modified), + new_file: DiffFile { + name: "src/commands/run.ts".to_string(), + contents: new_main.to_string(), + }, + old_file: DiffFile { + name: "src/commands/run.ts".to_string(), + contents: old_main.to_string(), + }, + sensitive: None, + truncated: None, + truncation_reason: None, + }, + FileDiff { + binary: None, + change_kind: Some(FileDiffChangeKind::Added), + new_file: DiffFile { + name: "src/config.ts".to_string(), + contents: new_config.to_string(), + }, + old_file: DiffFile { + name: String::new(), + contents: String::new(), + }, + sensitive: None, + truncated: None, + truncation_reason: None, + }, + FileDiff { + binary: None, + change_kind: Some(FileDiffChangeKind::Renamed), + new_file: DiffFile { + name: "src/legacy/old-runner.ts".to_string(), + contents: "export const legacy = true;\n".to_string(), + }, + old_file: DiffFile { + name: "src/old-runner.ts".to_string(), + contents: "export const legacy = true;\n".to_string(), + }, + sensitive: None, + truncated: None, + truncation_reason: None, + }, + ], + meta: RunFilesMeta { + truncated: false, + files_omitted_by_budget: None, + total_changed: 3, + to_sha: None, + to_sha_committed_at: None, + degraded: Some(false), + degraded_reason: None, + patch: None, + }, + } +} + pub(crate) async fn get_run_billing( _auth: AuthenticatedService, State(_state): State>, diff --git a/lib/crates/fabro-server/src/server.rs b/lib/crates/fabro-server/src/server.rs index 2f76b730d..459a417fe 100644 --- a/lib/crates/fabro-server/src/server.rs +++ b/lib/crates/fabro-server/src/server.rs @@ -1047,7 +1047,7 @@ fn demo_routes() -> Router> { .route("/runs/{id}/graph", get(demo::get_run_graph)) .route("/runs/{id}/stages", get(demo::get_run_stages)) .route("/runs/{id}/artifacts", get(demo::list_run_artifacts_stub)) - .route("/runs/{id}/files", get(not_implemented)) + .route("/runs/{id}/files", get(demo::list_run_files_stub)) .route( "/runs/{id}/stages/{stageId}/turns", get(demo::get_stage_turns), From 86f0140ee0d59cdc923b7ffa87dbcb33928f0179 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 19 Apr 2026 16:58:20 -0400 Subject: [PATCH 08/31] docs(logging): add prohibited-fields section Extends the Fabro logging strategy with an explicit prohibited-fields table covering the Run Files Changed endpoint's sensitive surface: diff_contents, per-changed-file file_path values, raw git_stderr, and credential-ish strings. Each entry pairs the prohibition with a concrete cardinality-bounded alternative, so future handlers have a precedent to follow rather than rediscovering the rule. The Run Files handler (Unit 5) already emits exactly the allowlisted field set (run_id, file_count, bytes_total, duration_ms, truncated, binary_count, sensitive_count, symlink_count, submodule_count); this change makes the policy enforceable for other endpoints. Refs plan docs/plans/2026-04-19-002-feat-run-files-changed-tab-plan.md Co-Authored-By: Claude Opus 4.7 (1M context) --- docs-internal/logging-strategy.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs-internal/logging-strategy.md b/docs-internal/logging-strategy.md index 08d6a8a09..5450ae19e 100644 --- a/docs-internal/logging-strategy.md +++ b/docs-internal/logging-strategy.md @@ -180,3 +180,16 @@ The domain event enums (`AgentEvent`, `PipelineEvent`, `ExecutionEnvEvent`) each - **Detached UX belongs in events, not stderr.** If an attached user needs to see the message later via `fabro attach` or `fabro logs`, emit a workflow event (for example `RunNotice`) and let tracing capture the developer-oriented copy separately. - **Wrapper variants are no-ops.** When one event enum wraps another (`PipelineEvent::Agent` wraps `AgentEvent`, `AgentEvent::SubAgentEvent` wraps a child `AgentEvent`), the wrapper's `trace()` arm is `{}` because the inner event was already traced at its origin. This prevents double-logging. - **Streaming noise variants are no-ops.** `TextDelta` and `ToolCallOutputDelta` produce no log output — per-token events would flood the logs even at DEBUG level. + +## Prohibited Fields + +Some field values carry real or latent sensitivity and must not appear in `tracing` events under any level. When the underlying information is genuinely useful for observability, emit a cardinality-bounded summary (count, size, truncation flag) instead of the raw value. + +| Field | Why it's prohibited | Emit instead | +|-------|---------------------|--------------| +| `diff_contents` | File contents from a user workspace may include secrets, PII, or copyrighted code. | `bytes_total`, `file_count`, `truncated` counters | +| `file_path` (for changed-file paths in the Run Files endpoint specifically) | Leaks workspace structure; combined with public run IDs can expose layout of private repos. | `file_count`, aggregate counts bucketed by `binary`, `sensitive`, `symlink`, `submodule` | +| `git_stderr` | Raw git output for untrusted workspaces may include path-shaped secrets (e.g. `~/.ssh/id_rsa_work`) and terminal control sequences. | A short categorized reason (`"timeout"`, `"bad_revision"`, `"unknown_object"`) derived from stderr, never the stderr itself | +| Credential-ish strings (`api_key`, `bearer_token`, `cookie`, `session_id`, …) | Exfiltration risk. | Emit `has_credentials: true` or a fingerprint (`token_last4`) only when debugging is the only option | + +These prohibitions apply to every level (ERROR through TRACE). If an error path genuinely needs raw output for triage, route it through an authenticated support channel — not the default tracing subscriber. From 420e375134bc671eba6f32b6eef36b097f2117b5 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 19 Apr 2026 17:00:50 -0400 Subject: [PATCH 09/31] build(web): upgrade @pierre/diffs to 1.1.15 Bumps @pierre/diffs from 1.0.11 to 1.1.15 to pick up the Virtualizer component and renderHeaderPrefix/renderCustomHeader hooks the Run Files tab relies on for large-diff performance. 1.0 -> 1.1 merged MouseEventManager/LineSelectionManager into InteractionManager but the public React components (MultiFileDiff, PatchDiff, FileDiff, File) keep their existing shape, so no consumer changes are needed yet -- Unit 10 exercises the new features. Pins an exact version (1.1.15) rather than a caret range so bun doesn't resolve up to 1.1.16, which was published today and would trip the "no packages younger than 24 h" rule in the user-global policy. The redundant apps/fabro-web/bun.lock is removed; bun workspaces resolve against the root bun.lock and the per-app lockfile was drifting from it. Embedded SPA bundle (lib/crates/fabro-spa/assets/) is refreshed to match the new build output. Refs plan docs/plans/2026-04-19-002-feat-run-files-changed-tab-plan.md Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/fabro-web/bun.lock | 816 ------ apps/fabro-web/package.json | 2 +- bun.lock | 6 +- .../fabro-spa/assets/assets/chunk-7fpy4pmb.js | 1 + .../fabro-spa/assets/assets/chunk-nghb2mxb.js | 1 + .../fabro-spa/assets/assets/chunk-q2qv5qr4.js | 1 - .../fabro-spa/assets/assets/chunk-tqzz87j8.js | 1 - .../fabro-spa/assets/assets/entry-70cq40fr.js | 1969 ------------- .../fabro-spa/assets/assets/entry-h33x4hjk.js | 2563 +++++++++++++++++ lib/crates/fabro-spa/assets/index.html | 6 +- 10 files changed, 2573 insertions(+), 2793 deletions(-) delete mode 100644 apps/fabro-web/bun.lock create mode 100644 lib/crates/fabro-spa/assets/assets/chunk-7fpy4pmb.js create mode 100644 lib/crates/fabro-spa/assets/assets/chunk-nghb2mxb.js delete mode 100644 lib/crates/fabro-spa/assets/assets/chunk-q2qv5qr4.js delete mode 100644 lib/crates/fabro-spa/assets/assets/chunk-tqzz87j8.js delete mode 100644 lib/crates/fabro-spa/assets/assets/entry-70cq40fr.js create mode 100644 lib/crates/fabro-spa/assets/assets/entry-h33x4hjk.js diff --git a/apps/fabro-web/bun.lock b/apps/fabro-web/bun.lock deleted file mode 100644 index 9986165a8..000000000 --- a/apps/fabro-web/bun.lock +++ /dev/null @@ -1,816 +0,0 @@ -{ - "lockfileVersion": 1, - "configVersion": 1, - "workspaces": { - "": { - "name": "arc-web", - "dependencies": { - "@dnd-kit/core": "^6.3.1", - "@dnd-kit/sortable": "^10.0.0", - "@dnd-kit/utilities": "^3.2.2", - "@headlessui/react": "^2.2.9", - "@heroicons/react": "^2.2.0", - "@pierre/diffs": "^1.0.11", - "@react-router/node": "7.12.0", - "@react-router/serve": "7.12.0", - "@viz-js/viz": "^3.24.0", - "isbot": "^5.1.31", - "jose": "^6.1.3", - "react": "^19.2.4", - "react-dom": "^19.2.4", - "react-router": "7.12.0", - }, - "devDependencies": { - "@react-router/dev": "7.12.0", - "@tailwindcss/vite": "^4.1.13", - "@types/node": "^22", - "@types/react": "^19.2.7", - "@types/react-dom": "^19.2.3", - "openapi-typescript": "^7", - "tailwindcss": "^4.1.13", - "typescript": "^5.9.2", - "vite": "^7.1.7", - "vite-tsconfig-paths": "^5.1.4", - }, - }, - }, - "packages": { - "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], - - "@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="], - - "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="], - - "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="], - - "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="], - - "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="], - - "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow=="], - - "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], - - "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.28.5", "", { "dependencies": { "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5" } }, "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg=="], - - "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="], - - "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], - - "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="], - - "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="], - - "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.28.6", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg=="], - - "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="], - - "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], - - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], - - "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], - - "@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="], - - "@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="], - - "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w=="], - - "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A=="], - - "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.28.6", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA=="], - - "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw=="], - - "@babel/preset-typescript": ["@babel/preset-typescript@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g=="], - - "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], - - "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], - - "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], - - "@dnd-kit/accessibility": ["@dnd-kit/accessibility@3.1.1", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw=="], - - "@dnd-kit/core": ["@dnd-kit/core@6.3.1", "", { "dependencies": { "@dnd-kit/accessibility": "^3.1.1", "@dnd-kit/utilities": "^3.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ=="], - - "@dnd-kit/sortable": ["@dnd-kit/sortable@10.0.0", "", { "dependencies": { "@dnd-kit/utilities": "^3.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@dnd-kit/core": "^6.3.0", "react": ">=16.8.0" } }, "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg=="], - - "@dnd-kit/utilities": ["@dnd-kit/utilities@3.2.2", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg=="], - - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], - - "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], - - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="], - - "@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="], - - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="], - - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="], - - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="], - - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="], - - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="], - - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="], - - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="], - - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="], - - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="], - - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="], - - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="], - - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="], - - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="], - - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="], - - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="], - - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="], - - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="], - - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="], - - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="], - - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="], - - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="], - - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="], - - "@floating-ui/core": ["@floating-ui/core@1.7.4", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg=="], - - "@floating-ui/dom": ["@floating-ui/dom@1.7.5", "", { "dependencies": { "@floating-ui/core": "^1.7.4", "@floating-ui/utils": "^0.2.10" } }, "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg=="], - - "@floating-ui/react": ["@floating-ui/react@0.26.28", "", { "dependencies": { "@floating-ui/react-dom": "^2.1.2", "@floating-ui/utils": "^0.2.8", "tabbable": "^6.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw=="], - - "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.7", "", { "dependencies": { "@floating-ui/dom": "^1.7.5" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg=="], - - "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="], - - "@headlessui/react": ["@headlessui/react@2.2.9", "", { "dependencies": { "@floating-ui/react": "^0.26.16", "@react-aria/focus": "^3.20.2", "@react-aria/interactions": "^3.25.0", "@tanstack/react-virtual": "^3.13.9", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ=="], - - "@heroicons/react": ["@heroicons/react@2.2.0", "", { "peerDependencies": { "react": ">= 16 || ^19.0.0-rc" } }, "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ=="], - - "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], - - "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], - - "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], - - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], - - "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], - - "@mjackson/node-fetch-server": ["@mjackson/node-fetch-server@0.2.0", "", {}, "sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng=="], - - "@pierre/diffs": ["@pierre/diffs@1.0.11", "", { "dependencies": { "@shikijs/core": "^3.0.0", "@shikijs/engine-javascript": "^3.0.0", "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-j6zIEoyImQy1HfcJqbrDwP0O5I7V2VNXAaw53FqQ+SykRfaNwABeZHs9uibXO4supaXPmTx6LEH9Lffr03e1Tw=="], - - "@react-aria/focus": ["@react-aria/focus@3.21.4", "", { "dependencies": { "@react-aria/interactions": "^3.27.0", "@react-aria/utils": "^3.33.0", "@react-types/shared": "^3.33.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-6gz+j9ip0/vFRTKJMl3R30MHopn4i19HqqLfSQfElxJD+r9hBnYG1Q6Wd/kl/WRR1+CALn2F+rn06jUnf5sT8Q=="], - - "@react-aria/interactions": ["@react-aria/interactions@3.27.0", "", { "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-aria/utils": "^3.33.0", "@react-stately/flags": "^3.1.2", "@react-types/shared": "^3.33.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-D27pOy+0jIfHK60BB26AgqjjRFOYdvVSkwC31b2LicIzRCSPOSP06V4gMHuGmkhNTF4+YWDi1HHYjxIvMeiSlA=="], - - "@react-aria/ssr": ["@react-aria/ssr@3.9.10", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ=="], - - "@react-aria/utils": ["@react-aria/utils@3.33.0", "", { "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-stately/flags": "^3.1.2", "@react-stately/utils": "^3.11.0", "@react-types/shared": "^3.33.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-yvz7CMH8d2VjwbSa5nGXqjU031tYhD8ddax95VzJsHSPyqHDEGfxul8RkhGV6oO7bVqZxVs6xY66NIgae+FHjw=="], - - "@react-router/dev": ["@react-router/dev@7.12.0", "", { "dependencies": { "@babel/core": "^7.27.7", "@babel/generator": "^7.27.5", "@babel/parser": "^7.27.7", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/preset-typescript": "^7.27.1", "@babel/traverse": "^7.27.7", "@babel/types": "^7.27.7", "@react-router/node": "7.12.0", "@remix-run/node-fetch-server": "^0.9.0", "arg": "^5.0.1", "babel-dead-code-elimination": "^1.0.6", "chokidar": "^4.0.0", "dedent": "^1.5.3", "es-module-lexer": "^1.3.1", "exit-hook": "2.2.1", "isbot": "^5.1.11", "jsesc": "3.0.2", "lodash": "^4.17.21", "p-map": "^7.0.3", "pathe": "^1.1.2", "picocolors": "^1.1.1", "pkg-types": "^2.3.0", "prettier": "^3.6.2", "react-refresh": "^0.14.0", "semver": "^7.3.7", "tinyglobby": "^0.2.14", "valibot": "^1.2.0", "vite-node": "^3.2.2" }, "peerDependencies": { "@react-router/serve": "^7.12.0", "@vitejs/plugin-rsc": "~0.5.7", "react-router": "^7.12.0", "react-server-dom-webpack": "^19.2.3", "typescript": "^5.1.0", "vite": "^5.1.0 || ^6.0.0 || ^7.0.0", "wrangler": "^3.28.2 || ^4.0.0" }, "optionalPeers": ["@react-router/serve", "@vitejs/plugin-rsc", "react-server-dom-webpack", "typescript", "wrangler"], "bin": { "react-router": "bin.js" } }, "sha512-5GpwXgq4pnOVeG7l6ADkCHA1rthJus1q/A3NRYJAIypclUQDYAzg1/fDNjvaKuTSrq+Nr3u6aj2v+oC+47MX6g=="], - - "@react-router/express": ["@react-router/express@7.12.0", "", { "dependencies": { "@react-router/node": "7.12.0" }, "peerDependencies": { "express": "^4.17.1 || ^5", "react-router": "7.12.0", "typescript": "^5.1.0" }, "optionalPeers": ["typescript"] }, "sha512-uAK+zF93M6XauGeXLh/UBh+3HrwiA/9lUS+eChjQ0a5FzjLpsc6ciUqF5oHh3lwWzLU7u7tj4qoeucUn6SInTw=="], - - "@react-router/node": ["@react-router/node@7.12.0", "", { "dependencies": { "@mjackson/node-fetch-server": "^0.2.0" }, "peerDependencies": { "react-router": "7.12.0", "typescript": "^5.1.0" }, "optionalPeers": ["typescript"] }, "sha512-o/t10Cse4LK8kFefqJ8JjC6Ng6YuKD2I87S2AiJs17YAYtXU5W731ZqB73AWyCDd2G14R0dSuqXiASRNK/xLjg=="], - - "@react-router/serve": ["@react-router/serve@7.12.0", "", { "dependencies": { "@mjackson/node-fetch-server": "^0.2.0", "@react-router/express": "7.12.0", "@react-router/node": "7.12.0", "compression": "^1.8.1", "express": "^4.19.2", "get-port": "5.1.1", "morgan": "^1.10.1", "source-map-support": "^0.5.21" }, "peerDependencies": { "react-router": "7.12.0" }, "bin": { "react-router-serve": "bin.js" } }, "sha512-j1ltgU7s3wAwOosZ5oxgHSsmVyK706gY/yIs8qVmC239wQ3zr3eqaXk3TVVLMeRy+eDgPNmgc6oNJv2o328VgA=="], - - "@react-stately/flags": ["@react-stately/flags@3.1.2", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg=="], - - "@react-stately/utils": ["@react-stately/utils@3.11.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-8LZpYowJ9eZmmYLpudbo/eclIRnbhWIJZ994ncmlKlouNzKohtM8qTC6B1w1pwUbiwGdUoyzLuQbeaIor5Dvcw=="], - - "@react-types/shared": ["@react-types/shared@3.33.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-xuUpP6MyuPmJtzNOqF5pzFUIHH2YogyOQfUQHag54PRmWB7AbjuGWBUv0l1UDmz6+AbzAYGmDVAzcRDOu2PFpw=="], - - "@redocly/ajv": ["@redocly/ajv@8.11.2", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js-replace": "^1.0.1" } }, "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg=="], - - "@redocly/config": ["@redocly/config@0.22.0", "", {}, "sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ=="], - - "@redocly/openapi-core": ["@redocly/openapi-core@1.34.8", "", { "dependencies": { "@redocly/ajv": "8.11.2", "@redocly/config": "0.22.0", "colorette": "1.4.0", "https-proxy-agent": "7.0.6", "js-levenshtein": "1.1.6", "js-yaml": "4.1.0", "minimatch": "5.1.6", "pluralize": "8.0.0", "yaml-ast-parser": "0.0.43" } }, "sha512-/oy8sXi5xK4+HvcFR7xS1A74zJ5aS6rtacNEr91SczLqvtxz79opxp7yYpdYtfGQAp6igx9eU9alwSC/R/X3Cg=="], - - "@remix-run/node-fetch-server": ["@remix-run/node-fetch-server@0.9.0", "", {}, "sha512-SoLMv7dbH+njWzXnOY6fI08dFMI5+/dQ+vY3n8RnnbdG7MdJEgiP28Xj/xWlnRnED/aB6SFw56Zop+LbmaaKqA=="], - - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="], - - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="], - - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="], - - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="], - - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="], - - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="], - - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="], - - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="], - - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="], - - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="], - - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="], - - "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="], - - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="], - - "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="], - - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="], - - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="], - - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="], - - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="], - - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="], - - "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="], - - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="], - - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="], - - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="], - - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="], - - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="], - - "@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], - - "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA=="], - - "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g=="], - - "@shikijs/langs": ["@shikijs/langs@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg=="], - - "@shikijs/themes": ["@shikijs/themes@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA=="], - - "@shikijs/transformers": ["@shikijs/transformers@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/types": "3.23.0" } }, "sha512-F9msZVxdF+krQNSdQ4V+Ja5QemeAoTQ2jxt7nJCwhDsdF1JWS3KxIQXA3lQbyKwS3J61oHRUSv4jYWv3CkaKTQ=="], - - "@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], - - "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], - - "@swc/helpers": ["@swc/helpers@0.5.19", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA=="], - - "@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="], - - "@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="], - - "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg=="], - - "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw=="], - - "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw=="], - - "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA=="], - - "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw=="], - - "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ=="], - - "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ=="], - - "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g=="], - - "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g=="], - - "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.1", "", { "dependencies": { "@emnapi/core": "^1.8.1", "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q=="], - - "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA=="], - - "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="], - - "@tailwindcss/vite": ["@tailwindcss/vite@4.2.1", "", { "dependencies": { "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "tailwindcss": "4.2.1" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w=="], - - "@tanstack/react-virtual": ["@tanstack/react-virtual@3.13.19", "", { "dependencies": { "@tanstack/virtual-core": "3.13.19" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-KzwmU1IbE0IvCZSm6OXkS+kRdrgW2c2P3Ho3NC+zZXWK6oObv/L+lcV/2VuJ+snVESRlMJ+w/fg4WXI/JzoNGQ=="], - - "@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.19", "", {}, "sha512-/BMP7kNhzKOd7wnDeB8NrIRNLwkf5AhCYCvtfZV2GXWbBieFm/el0n6LOAXlTi6ZwHICSNnQcIxRCWHrLzDY+g=="], - - "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], - - "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], - - "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], - - "@types/node": ["@types/node@22.19.13", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], - - "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], - - "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], - - "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], - - "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], - - "@viz-js/viz": ["@viz-js/viz@3.24.0", "", {}, "sha512-sTRz2cFN6PwICVC7GVlF2aYNAZ/LwF7Y1mp3B+8LXQ7otyHrzQYSzNBwJ4lctL/aS3x97ppw59z6zIW+wPs6bQ=="], - - "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], - - "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], - - "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], - - "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], - - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - - "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="], - - "babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.12", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig=="], - - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "baseline-browser-mapping": ["baseline-browser-mapping@2.10.0", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA=="], - - "basic-auth": ["basic-auth@2.0.1", "", { "dependencies": { "safe-buffer": "5.1.2" } }, "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg=="], - - "body-parser": ["body-parser@1.20.4", "", { "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "~1.2.0", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", "qs": "~6.14.0", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" } }, "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA=="], - - "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - - "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], - - "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - - "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], - - "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], - - "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], - - "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], - - "caniuse-lite": ["caniuse-lite@1.0.30001774", "", {}, "sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA=="], - - "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], - - "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], - - "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], - - "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], - - "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], - - "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], - - "colorette": ["colorette@1.4.0", "", {}, "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="], - - "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], - - "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="], - - "compression": ["compression@1.8.1", "", { "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" } }, "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w=="], - - "confbox": ["confbox@0.2.4", "", {}, "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ=="], - - "content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], - - "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], - - "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], - - "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], - - "cookie-signature": ["cookie-signature@1.0.7", "", {}, "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="], - - "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], - - "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - - "dedent": ["dedent@1.7.1", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg=="], - - "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], - - "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], - - "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], - - "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - - "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], - - "diff": ["diff@8.0.3", "", {}, "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ=="], - - "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], - - "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - - "electron-to-chromium": ["electron-to-chromium@1.5.302", "", {}, "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg=="], - - "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], - - "enhanced-resolve": ["enhanced-resolve@5.20.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ=="], - - "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], - - "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - - "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], - - "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], - - "esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], - - "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], - - "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], - - "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], - - "exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="], - - "express": ["express@4.22.1", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "~1.20.3", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.3.1", "fresh": "~0.5.2", "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", "serve-static": "~1.16.2", "setprototypeof": "1.2.0", "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g=="], - - "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], - - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], - - "finalhandler": ["finalhandler@1.3.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "statuses": "~2.0.2", "unpipe": "~1.0.0" } }, "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg=="], - - "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], - - "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], - - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - - "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - - "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], - - "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], - - "get-port": ["get-port@5.1.1", "", {}, "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ=="], - - "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], - - "globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="], - - "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], - - "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - - "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], - - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], - - "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], - - "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], - - "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], - - "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], - - "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], - - "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], - - "index-to-position": ["index-to-position@1.2.0", "", {}, "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw=="], - - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - - "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], - - "isbot": ["isbot@5.1.35", "", {}, "sha512-waFfC72ZNfwLLuJ2iLaoVaqcNo+CAaLR7xCpAn0Y5WfGzkNHv7ZN39Vbi1y+kb+Zs46XHOX3tZNExroFUPX+Kg=="], - - "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], - - "jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="], - - "js-levenshtein": ["js-levenshtein@1.1.6", "", {}, "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g=="], - - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - - "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], - - "jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], - - "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - - "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], - - "lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="], - - "lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="], - - "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="], - - "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="], - - "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="], - - "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="], - - "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="], - - "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="], - - "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="], - - "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="], - - "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="], - - "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="], - - "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], - - "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - - "lru_map": ["lru_map@0.4.1", "", {}, "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg=="], - - "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], - - "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], - - "mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="], - - "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], - - "merge-descriptors": ["merge-descriptors@1.0.3", "", {}, "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="], - - "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="], - - "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], - - "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], - - "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="], - - "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], - - "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], - - "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], - - "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], - - "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - - "minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], - - "morgan": ["morgan@1.10.1", "", { "dependencies": { "basic-auth": "~2.0.1", "debug": "2.6.9", "depd": "~2.0.0", "on-finished": "~2.3.0", "on-headers": "~1.1.0" } }, "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A=="], - - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - - "negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="], - - "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="], - - "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], - - "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], - - "on-headers": ["on-headers@1.1.0", "", {}, "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A=="], - - "oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="], - - "oniguruma-to-es": ["oniguruma-to-es@4.3.4", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA=="], - - "openapi-typescript": ["openapi-typescript@7.13.0", "", { "dependencies": { "@redocly/openapi-core": "^1.34.6", "ansi-colors": "^4.1.3", "change-case": "^5.4.4", "parse-json": "^8.3.0", "supports-color": "^10.2.2", "yargs-parser": "^21.1.1" }, "peerDependencies": { "typescript": "^5.x" }, "bin": { "openapi-typescript": "bin/cli.js" } }, "sha512-EFP392gcqXS7ntPvbhBzbF8TyBA+baIYEm791Hy5YkjDYKTnk/Tn5OQeKm5BIZvJihpp8Zzr4hzx0Irde1LNGQ=="], - - "p-map": ["p-map@7.0.4", "", {}, "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ=="], - - "parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="], - - "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], - - "path-to-regexp": ["path-to-regexp@0.1.12", "", {}, "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="], - - "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], - - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - - "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - - "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], - - "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], - - "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], - - "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], - - "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], - - "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], - - "qs": ["qs@6.14.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q=="], - - "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], - - "raw-body": ["raw-body@2.5.3", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "unpipe": "~1.0.0" } }, "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA=="], - - "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="], - - "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="], - - "react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="], - - "react-router": ["react-router@7.12.0", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-kTPDYPFzDVGIIGNLS5VJykK0HfHLY5MF3b+xj0/tTyNYL1gF1qs7u67Z9jEhQk2sQ98SUaHxlG31g1JtF7IfVw=="], - - "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], - - "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="], - - "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="], - - "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="], - - "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], - - "rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="], - - "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], - - "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], - - "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], - - "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], - - "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], - - "serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], - - "set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="], - - "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], - - "shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], - - "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], - - "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], - - "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], - - "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], - - "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], - - "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], - - "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], - - "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], - - "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], - - "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], - - "tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="], - - "tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="], - - "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], - - "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], - - "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], - - "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], - - "tsconfck": ["tsconfck@3.1.6", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w=="], - - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - - "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], - - "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], - - "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - - "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - - "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], - - "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], - - "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], - - "unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="], - - "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], - - "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - - "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], - - "uri-js-replace": ["uri-js-replace@1.0.1", "", {}, "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g=="], - - "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], - - "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], - - "valibot": ["valibot@1.2.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg=="], - - "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], - - "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], - - "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], - - "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], - - "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="], - - "vite-tsconfig-paths": ["vite-tsconfig-paths@5.1.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w=="], - - "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], - - "yaml-ast-parser": ["yaml-ast-parser@0.0.43", "", {}, "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A=="], - - "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], - - "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], - - "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], - - "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], - - "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], - - "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="], - - "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], - - "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - - "accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], - - "basic-auth/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - - "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], - - "express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - - "morgan/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "morgan/on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="], - - "pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - - "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "vite-node/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - - "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "morgan/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - } -} diff --git a/apps/fabro-web/package.json b/apps/fabro-web/package.json index 12cca04d3..3c2753096 100644 --- a/apps/fabro-web/package.json +++ b/apps/fabro-web/package.json @@ -14,7 +14,7 @@ "@dnd-kit/utilities": "^3.2.2", "@headlessui/react": "^2.2.9", "@heroicons/react": "^2.2.0", - "@pierre/diffs": "^1.0.11", + "@pierre/diffs": "1.1.15", "@qltysh/fabro-api-client": "workspace:*", "@tailwindcss/typography": "^0.5.19", "@viz-js/viz": "^3.24.0", diff --git a/bun.lock b/bun.lock index 7da9b3006..2f1086ca6 100644 --- a/bun.lock +++ b/bun.lock @@ -11,7 +11,7 @@ "@dnd-kit/utilities": "^3.2.2", "@headlessui/react": "^2.2.9", "@heroicons/react": "^2.2.0", - "@pierre/diffs": "^1.0.11", + "@pierre/diffs": "1.1.15", "@qltysh/fabro-api-client": "workspace:*", "@tailwindcss/typography": "^0.5.19", "@viz-js/viz": "^3.24.0", @@ -314,7 +314,9 @@ "@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.6", "", { "os": "win32", "cpu": "x64" }, "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw=="], - "@pierre/diffs": ["@pierre/diffs@1.0.11", "", { "dependencies": { "@shikijs/core": "^3.0.0", "@shikijs/engine-javascript": "^3.0.0", "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-j6zIEoyImQy1HfcJqbrDwP0O5I7V2VNXAaw53FqQ+SykRfaNwABeZHs9uibXO4supaXPmTx6LEH9Lffr03e1Tw=="], + "@pierre/diffs": ["@pierre/diffs@1.1.15", "", { "dependencies": { "@pierre/theme": "0.0.28", "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-Gj863E+aSpc0H3C4cH0fQTaF/tP9yYfhnilR7/dS72qq8thqNpR3fo3jURHRtRKz6KJJ10anxcurHP7b3ZUQkw=="], + + "@pierre/theme": ["@pierre/theme@0.0.28", "", {}, "sha512-1j/H/fECBuc9dEvntdWI+l435HZapw+RCJTlqCA6BboQ5TjlnE005j/ROWutXIs8aq5OAc82JI2Kwk4A1WWBgw=="], "@qltysh/fabro-api-client": ["@qltysh/fabro-api-client@workspace:lib/packages/fabro-api-client"], diff --git a/lib/crates/fabro-spa/assets/assets/chunk-7fpy4pmb.js b/lib/crates/fabro-spa/assets/assets/chunk-7fpy4pmb.js new file mode 100644 index 000000000..271497c14 --- /dev/null +++ b/lib/crates/fabro-spa/assets/assets/chunk-7fpy4pmb.js @@ -0,0 +1 @@ +import"./chunk-q07bg6gn.js";var e=Object.freeze(JSON.parse('{"name":"Pierre Dark","type":"dark","colors":{"editor.background":"#070707","editor.foreground":"#fbfbfb","foreground":"#fbfbfb","focusBorder":"#009fff","selection.background":"#19283c","editor.selectionBackground":"#009fff4d","editor.lineHighlightBackground":"#19283c8c","editorCursor.foreground":"#009fff","editorLineNumber.foreground":"#84848A","editorLineNumber.activeForeground":"#adadb1","editorIndentGuide.background":"#1F1F21","editorIndentGuide.activeBackground":"#2e2e30","diffEditor.insertedTextBackground":"#00cab11a","diffEditor.deletedTextBackground":"#ff2e3f1a","sideBar.background":"#141415","sideBar.foreground":"#adadb1","sideBar.border":"#070707","sideBarTitle.foreground":"#fbfbfb","sideBarSectionHeader.background":"#141415","sideBarSectionHeader.foreground":"#adadb1","sideBarSectionHeader.border":"#070707","activityBar.background":"#141415","activityBar.foreground":"#fbfbfb","activityBar.border":"#070707","activityBar.activeBorder":"#009fff","activityBarBadge.background":"#009fff","activityBarBadge.foreground":"#070707","titleBar.activeBackground":"#141415","titleBar.activeForeground":"#fbfbfb","titleBar.inactiveBackground":"#141415","titleBar.inactiveForeground":"#84848A","titleBar.border":"#070707","list.activeSelectionBackground":"#19283c99","list.activeSelectionForeground":"#fbfbfb","list.inactiveSelectionBackground":"#19283c73","list.hoverBackground":"#19283c59","list.focusOutline":"#009fff","tab.activeBackground":"#070707","tab.activeForeground":"#fbfbfb","tab.activeBorderTop":"#009fff","tab.inactiveBackground":"#141415","tab.inactiveForeground":"#84848A","tab.border":"#070707","editorGroupHeader.tabsBackground":"#141415","editorGroupHeader.tabsBorder":"#070707","panel.background":"#141415","panel.border":"#070707","panelTitle.activeBorder":"#009fff","panelTitle.activeForeground":"#fbfbfb","panelTitle.inactiveForeground":"#84848A","statusBar.background":"#141415","statusBar.foreground":"#adadb1","statusBar.border":"#070707","statusBar.noFolderBackground":"#141415","statusBar.debuggingBackground":"#ffca00","statusBar.debuggingForeground":"#070707","statusBarItem.remoteBackground":"#141415","statusBarItem.remoteForeground":"#adadb1","input.background":"#1F1F21","input.border":"#1F1F21","input.foreground":"#fbfbfb","input.placeholderForeground":"#79797F","dropdown.background":"#1F1F21","dropdown.border":"#1F1F21","dropdown.foreground":"#fbfbfb","button.background":"#009fff","button.foreground":"#070707","button.hoverBackground":"#0190e6","textLink.foreground":"#009fff","textLink.activeForeground":"#009fff","gitDecoration.addedResourceForeground":"#00cab1","gitDecoration.conflictingResourceForeground":"#ffca00","gitDecoration.modifiedResourceForeground":"#009fff","gitDecoration.deletedResourceForeground":"#ff2e3f","gitDecoration.untrackedResourceForeground":"#00cab1","gitDecoration.ignoredResourceForeground":"#84848A","terminal.titleForeground":"#adadb1","terminal.titleInactiveForeground":"#84848A","terminal.background":"#141415","terminal.foreground":"#adadb1","terminal.ansiBlack":"#141415","terminal.ansiRed":"#ff2e3f","terminal.ansiGreen":"#0dbe4e","terminal.ansiYellow":"#ffca00","terminal.ansiBlue":"#009fff","terminal.ansiMagenta":"#c635e4","terminal.ansiCyan":"#08c0ef","terminal.ansiWhite":"#c6c6c8","terminal.ansiBrightBlack":"#141415","terminal.ansiBrightRed":"#ff2e3f","terminal.ansiBrightGreen":"#0dbe4e","terminal.ansiBrightYellow":"#ffca00","terminal.ansiBrightBlue":"#009fff","terminal.ansiBrightMagenta":"#c635e4","terminal.ansiBrightCyan":"#08c0ef","terminal.ansiBrightWhite":"#c6c6c8"},"tokenColors":[{"scope":["comment","punctuation.definition.comment"],"settings":{"foreground":"#84848A"}},{"scope":"comment markup.link","settings":{"foreground":"#84848A"}},{"scope":["string","constant.other.symbol"],"settings":{"foreground":"#5ecc71"}},{"scope":["punctuation.definition.string.begin","punctuation.definition.string.end"],"settings":{"foreground":"#5ecc71"}},{"scope":["constant.numeric","constant.language.boolean"],"settings":{"foreground":"#68cdf2"}},{"scope":"constant","settings":{"foreground":"#ffd452"}},{"scope":"punctuation.definition.constant","settings":{"foreground":"#ffd452"}},{"scope":"constant.language","settings":{"foreground":"#68cdf2"}},{"scope":"variable.other.constant","settings":{"foreground":"#ffca00"}},{"scope":"keyword","settings":{"foreground":"#ff678d"}},{"scope":"keyword.control","settings":{"foreground":"#ff678d"}},{"scope":["storage","storage.type","storage.modifier"],"settings":{"foreground":"#ff678d"}},{"scope":"token.storage","settings":{"foreground":"#ff678d"}},{"scope":["keyword.operator.new","keyword.operator.expression.instanceof","keyword.operator.expression.typeof","keyword.operator.expression.void","keyword.operator.expression.delete","keyword.operator.expression.in","keyword.operator.expression.of","keyword.operator.expression.keyof"],"settings":{"foreground":"#ff678d"}},{"scope":"keyword.operator.delete","settings":{"foreground":"#ff678d"}},{"scope":["variable","identifier","meta.definition.variable"],"settings":{"foreground":"#ffa359"}},{"scope":["variable.other.readwrite","meta.object-literal.key","support.variable.property","support.variable.object.process","support.variable.object.node"],"settings":{"foreground":"#ffa359"}},{"scope":"variable.language","settings":{"foreground":"#ffca00"}},{"scope":"variable.parameter.function","settings":{"foreground":"#adadb1"}},{"scope":"function.parameter","settings":{"foreground":"#adadb1"}},{"scope":"variable.parameter","settings":{"foreground":"#adadb1"}},{"scope":"variable.parameter.function.language.python","settings":{"foreground":"#ffd452"}},{"scope":"variable.parameter.function.python","settings":{"foreground":"#ffd452"}},{"scope":["support.function","entity.name.function","meta.function-call","meta.require","support.function.any-method","variable.function"],"settings":{"foreground":"#9d6afb"}},{"scope":"keyword.other.special-method","settings":{"foreground":"#9d6afb"}},{"scope":"entity.name.function","settings":{"foreground":"#9d6afb"}},{"scope":"support.function.console","settings":{"foreground":"#9d6afb"}},{"scope":["support.type","entity.name.type","entity.name.class","storage.type"],"settings":{"foreground":"#d568ea"}},{"scope":["support.class","entity.name.type.class"],"settings":{"foreground":"#d568ea"}},{"scope":["entity.name.class","variable.other.class.js","variable.other.class.ts"],"settings":{"foreground":"#d568ea"}},{"scope":"entity.name.class.identifier.namespace.type","settings":{"foreground":"#d568ea"}},{"scope":"entity.name.type.namespace","settings":{"foreground":"#ffca00"}},{"scope":"entity.other.inherited-class","settings":{"foreground":"#d568ea"}},{"scope":"entity.name.namespace","settings":{"foreground":"#ffca00"}},{"scope":"keyword.operator","settings":{"foreground":"#79797F"}},{"scope":["keyword.operator.logical","keyword.operator.bitwise","keyword.operator.channel"],"settings":{"foreground":"#08c0ef"}},{"scope":["keyword.operator.arithmetic","keyword.operator.comparison","keyword.operator.relational","keyword.operator.increment","keyword.operator.decrement"],"settings":{"foreground":"#08c0ef"}},{"scope":"keyword.operator.assignment","settings":{"foreground":"#08c0ef"}},{"scope":"keyword.operator.assignment.compound","settings":{"foreground":"#ff678d"}},{"scope":["keyword.operator.assignment.compound.js","keyword.operator.assignment.compound.ts"],"settings":{"foreground":"#08c0ef"}},{"scope":"keyword.operator.ternary","settings":{"foreground":"#ff678d"}},{"scope":"keyword.operator.optional","settings":{"foreground":"#ff678d"}},{"scope":"punctuation","settings":{"foreground":"#79797F"}},{"scope":"punctuation.separator.delimiter","settings":{"foreground":"#79797F"}},{"scope":"punctuation.separator.key-value","settings":{"foreground":"#79797F"}},{"scope":"punctuation.terminator","settings":{"foreground":"#79797F"}},{"scope":"meta.brace","settings":{"foreground":"#79797F"}},{"scope":"meta.brace.square","settings":{"foreground":"#79797F"}},{"scope":"meta.brace.round","settings":{"foreground":"#79797F"}},{"scope":"function.brace","settings":{"foreground":"#79797F"}},{"scope":["punctuation.definition.parameters","punctuation.definition.typeparameters"],"settings":{"foreground":"#79797F"}},{"scope":["punctuation.definition.block","punctuation.definition.tag"],"settings":{"foreground":"#79797F"}},{"scope":["meta.tag.tsx","meta.tag.jsx","meta.tag.js","meta.tag.ts"],"settings":{"foreground":"#79797F"}},{"scope":"keyword.operator.expression.import","settings":{"foreground":"#9d6afb"}},{"scope":"keyword.operator.module","settings":{"foreground":"#ff678d"}},{"scope":"support.type.object.console","settings":{"foreground":"#ffa359"}},{"scope":["support.module.node","support.type.object.module","entity.name.type.module"],"settings":{"foreground":"#ffca00"}},{"scope":"support.constant.math","settings":{"foreground":"#ffca00"}},{"scope":"support.constant.property.math","settings":{"foreground":"#ffd452"}},{"scope":"support.constant.json","settings":{"foreground":"#ffd452"}},{"scope":"support.type.object.dom","settings":{"foreground":"#08c0ef"}},{"scope":["support.variable.dom","support.variable.property.dom"],"settings":{"foreground":"#ffa359"}},{"scope":"support.variable.property.process","settings":{"foreground":"#ffd452"}},{"scope":"meta.property.object","settings":{"foreground":"#ffa359"}},{"scope":"variable.parameter.function.js","settings":{"foreground":"#ffa359"}},{"scope":["keyword.other.template.begin","keyword.other.template.end"],"settings":{"foreground":"#5ecc71"}},{"scope":["keyword.other.substitution.begin","keyword.other.substitution.end"],"settings":{"foreground":"#5ecc71"}},{"scope":["punctuation.definition.template-expression.begin","punctuation.definition.template-expression.end"],"settings":{"foreground":"#ff678d"}},{"scope":"meta.template.expression","settings":{"foreground":"#79797F"}},{"scope":"punctuation.section.embedded","settings":{"foreground":"#ffa359"}},{"scope":"variable.interpolation","settings":{"foreground":"#ffa359"}},{"scope":["punctuation.section.embedded.begin","punctuation.section.embedded.end"],"settings":{"foreground":"#ff678d"}},{"scope":"punctuation.quasi.element","settings":{"foreground":"#ff678d"}},{"scope":["support.type.primitive.ts","support.type.builtin.ts","support.type.primitive.tsx","support.type.builtin.tsx"],"settings":{"foreground":"#d568ea"}},{"scope":"support.type.type.flowtype","settings":{"foreground":"#9d6afb"}},{"scope":"support.type.primitive","settings":{"foreground":"#d568ea"}},{"scope":"support.variable.magic.python","settings":{"foreground":"#ff6762"}},{"scope":"variable.parameter.function.language.special.self.python","settings":{"foreground":"#ffca00"}},{"scope":["punctuation.separator.period.python","punctuation.separator.element.python","punctuation.parenthesis.begin.python","punctuation.parenthesis.end.python"],"settings":{"foreground":"#79797F"}},{"scope":["punctuation.definition.arguments.begin.python","punctuation.definition.arguments.end.python","punctuation.separator.arguments.python","punctuation.definition.list.begin.python","punctuation.definition.list.end.python"],"settings":{"foreground":"#79797F"}},{"scope":"support.type.python","settings":{"foreground":"#08c0ef"}},{"scope":"keyword.operator.logical.python","settings":{"foreground":"#ff678d"}},{"scope":"meta.function-call.generic.python","settings":{"foreground":"#9d6afb"}},{"scope":"constant.character.format.placeholder.other.python","settings":{"foreground":"#ffd452"}},{"scope":"meta.function.decorator.python","settings":{"foreground":"#9d6afb"}},{"scope":["support.token.decorator.python","meta.function.decorator.identifier.python"],"settings":{"foreground":"#08c0ef"}},{"scope":"storage.modifier.lifetime.rust","settings":{"foreground":"#79797F"}},{"scope":"support.function.std.rust","settings":{"foreground":"#9d6afb"}},{"scope":"entity.name.lifetime.rust","settings":{"foreground":"#ffca00"}},{"scope":"variable.language.rust","settings":{"foreground":"#ff6762"}},{"scope":"keyword.operator.misc.rust","settings":{"foreground":"#79797F"}},{"scope":"keyword.operator.sigil.rust","settings":{"foreground":"#ff678d"}},{"scope":"support.constant.core.rust","settings":{"foreground":"#ffd452"}},{"scope":["meta.function.c","meta.function.cpp"],"settings":{"foreground":"#ff6762"}},{"scope":["punctuation.section.block.begin.bracket.curly.cpp","punctuation.section.block.end.bracket.curly.cpp","punctuation.terminator.statement.c","punctuation.section.block.begin.bracket.curly.c","punctuation.section.block.end.bracket.curly.c","punctuation.section.parens.begin.bracket.round.c","punctuation.section.parens.end.bracket.round.c","punctuation.section.parameters.begin.bracket.round.c","punctuation.section.parameters.end.bracket.round.c"],"settings":{"foreground":"#79797F"}},{"scope":["keyword.operator.assignment.c","keyword.operator.comparison.c","keyword.operator.c","keyword.operator.increment.c","keyword.operator.decrement.c","keyword.operator.bitwise.shift.c"],"settings":{"foreground":"#ff678d"}},{"scope":["keyword.operator.assignment.cpp","keyword.operator.comparison.cpp","keyword.operator.cpp","keyword.operator.increment.cpp","keyword.operator.decrement.cpp","keyword.operator.bitwise.shift.cpp"],"settings":{"foreground":"#ff678d"}},{"scope":["punctuation.separator.c","punctuation.separator.cpp"],"settings":{"foreground":"#ff678d"}},{"scope":["support.type.posix-reserved.c","support.type.posix-reserved.cpp"],"settings":{"foreground":"#08c0ef"}},{"scope":["keyword.operator.sizeof.c","keyword.operator.sizeof.cpp"],"settings":{"foreground":"#ff678d"}},{"scope":"variable.c","settings":{"foreground":"#79797F"}},{"scope":["storage.type.annotation.java","storage.type.object.array.java"],"settings":{"foreground":"#ffca00"}},{"scope":"source.java","settings":{"foreground":"#ff6762"}},{"scope":["punctuation.section.block.begin.java","punctuation.section.block.end.java","punctuation.definition.method-parameters.begin.java","punctuation.definition.method-parameters.end.java","meta.method.identifier.java","punctuation.section.method.begin.java","punctuation.section.method.end.java","punctuation.terminator.java","punctuation.section.class.begin.java","punctuation.section.class.end.java","punctuation.section.inner-class.begin.java","punctuation.section.inner-class.end.java","meta.method-call.java","punctuation.section.class.begin.bracket.curly.java","punctuation.section.class.end.bracket.curly.java","punctuation.section.method.begin.bracket.curly.java","punctuation.section.method.end.bracket.curly.java","punctuation.separator.period.java","punctuation.bracket.angle.java","punctuation.definition.annotation.java","meta.method.body.java"],"settings":{"foreground":"#79797F"}},{"scope":"meta.method.java","settings":{"foreground":"#9d6afb"}},{"scope":["storage.modifier.import.java","storage.type.java","storage.type.generic.java"],"settings":{"foreground":"#ffca00"}},{"scope":"keyword.operator.instanceof.java","settings":{"foreground":"#ff678d"}},{"scope":"meta.definition.variable.name.java","settings":{"foreground":"#ff6762"}},{"scope":"token.variable.parameter.java","settings":{"foreground":"#79797F"}},{"scope":"import.storage.java","settings":{"foreground":"#ffca00"}},{"scope":"token.package.keyword","settings":{"foreground":"#ff678d"}},{"scope":"token.package","settings":{"foreground":"#79797F"}},{"scope":"token.storage.type.java","settings":{"foreground":"#ffca00"}},{"scope":"keyword.operator.assignment.go","settings":{"foreground":"#ffca00"}},{"scope":["keyword.operator.arithmetic.go","keyword.operator.address.go"],"settings":{"foreground":"#ff678d"}},{"scope":"entity.name.package.go","settings":{"foreground":"#ffca00"}},{"scope":["support.other.namespace.use.php","support.other.namespace.use-as.php","support.other.namespace.php","entity.other.alias.php","meta.interface.php"],"settings":{"foreground":"#ffca00"}},{"scope":"keyword.operator.error-control.php","settings":{"foreground":"#ff678d"}},{"scope":"keyword.operator.type.php","settings":{"foreground":"#ff678d"}},{"scope":["punctuation.section.array.begin.php","punctuation.section.array.end.php"],"settings":{"foreground":"#79797F"}},{"scope":["storage.type.php","meta.other.type.phpdoc.php","keyword.other.type.php","keyword.other.array.phpdoc.php"],"settings":{"foreground":"#ffca00"}},{"scope":["meta.function-call.php","meta.function-call.object.php","meta.function-call.static.php"],"settings":{"foreground":"#9d6afb"}},{"scope":["punctuation.definition.parameters.begin.bracket.round.php","punctuation.definition.parameters.end.bracket.round.php","punctuation.separator.delimiter.php","punctuation.section.scope.begin.php","punctuation.section.scope.end.php","punctuation.terminator.expression.php","punctuation.definition.arguments.begin.bracket.round.php","punctuation.definition.arguments.end.bracket.round.php","punctuation.definition.storage-type.begin.bracket.round.php","punctuation.definition.storage-type.end.bracket.round.php","punctuation.definition.array.begin.bracket.round.php","punctuation.definition.array.end.bracket.round.php","punctuation.definition.begin.bracket.round.php","punctuation.definition.end.bracket.round.php","punctuation.definition.begin.bracket.curly.php","punctuation.definition.end.bracket.curly.php","punctuation.definition.section.switch-block.end.bracket.curly.php","punctuation.definition.section.switch-block.start.bracket.curly.php","punctuation.definition.section.switch-block.begin.bracket.curly.php","punctuation.definition.section.switch-block.end.bracket.curly.php"],"settings":{"foreground":"#79797F"}},{"scope":["support.constant.ext.php","support.constant.std.php","support.constant.core.php","support.constant.parser-token.php"],"settings":{"foreground":"#ffd452"}},{"scope":["entity.name.goto-label.php","support.other.php"],"settings":{"foreground":"#9d6afb"}},{"scope":["keyword.operator.logical.php","keyword.operator.bitwise.php","keyword.operator.arithmetic.php"],"settings":{"foreground":"#08c0ef"}},{"scope":"keyword.operator.regexp.php","settings":{"foreground":"#ff678d"}},{"scope":"keyword.operator.comparison.php","settings":{"foreground":"#08c0ef"}},{"scope":["keyword.operator.heredoc.php","keyword.operator.nowdoc.php"],"settings":{"foreground":"#ff678d"}},{"scope":"variable.other.class.php","settings":{"foreground":"#ff6762"}},{"scope":"invalid.illegal.non-null-typehinted.php","settings":{"foreground":"#f44747"}},{"scope":"variable.other.generic-type.haskell","settings":{"foreground":"#ff678d"}},{"scope":"storage.type.haskell","settings":{"foreground":"#ffd452"}},{"scope":"storage.type.cs","settings":{"foreground":"#ffca00"}},{"scope":"entity.name.variable.local.cs","settings":{"foreground":"#ff6762"}},{"scope":"entity.name.label.cs","settings":{"foreground":"#ffca00"}},{"scope":["entity.name.scope-resolution.function.call","entity.name.scope-resolution.function.definition"],"settings":{"foreground":"#ffca00"}},{"scope":["punctuation.definition.delayed.unison","punctuation.definition.list.begin.unison","punctuation.definition.list.end.unison","punctuation.definition.ability.begin.unison","punctuation.definition.ability.end.unison","punctuation.operator.assignment.as.unison","punctuation.separator.pipe.unison","punctuation.separator.delimiter.unison","punctuation.definition.hash.unison"],"settings":{"foreground":"#ff6762"}},{"scope":"support.constant.edge","settings":{"foreground":"#ff678d"}},{"scope":"support.type.prelude.elm","settings":{"foreground":"#08c0ef"}},{"scope":"support.constant.elm","settings":{"foreground":"#ffd452"}},{"scope":"entity.global.clojure","settings":{"foreground":"#ffca00"}},{"scope":"meta.symbol.clojure","settings":{"foreground":"#ff6762"}},{"scope":"constant.keyword.clojure","settings":{"foreground":"#08c0ef"}},{"scope":["meta.arguments.coffee","variable.parameter.function.coffee"],"settings":{"foreground":"#ff6762"}},{"scope":"storage.modifier.import.groovy","settings":{"foreground":"#ffca00"}},{"scope":"meta.method.groovy","settings":{"foreground":"#9d6afb"}},{"scope":"meta.definition.variable.name.groovy","settings":{"foreground":"#ff6762"}},{"scope":"meta.definition.class.inherited.classes.groovy","settings":{"foreground":"#5ecc71"}},{"scope":"support.variable.semantic.hlsl","settings":{"foreground":"#ffca00"}},{"scope":["support.type.texture.hlsl","support.type.sampler.hlsl","support.type.object.hlsl","support.type.object.rw.hlsl","support.type.fx.hlsl","support.type.object.hlsl"],"settings":{"foreground":"#ff678d"}},{"scope":["text.variable","text.bracketed"],"settings":{"foreground":"#ff6762"}},{"scope":["support.type.swift","support.type.vb.asp"],"settings":{"foreground":"#ffca00"}},{"scope":"meta.scope.prerequisites.makefile","settings":{"foreground":"#ff6762"}},{"scope":"source.makefile","settings":{"foreground":"#ffca00"}},{"scope":"source.ini","settings":{"foreground":"#5ecc71"}},{"scope":"constant.language.symbol.ruby","settings":{"foreground":"#08c0ef"}},{"scope":["function.parameter.ruby","function.parameter.cs"],"settings":{"foreground":"#79797F"}},{"scope":"constant.language.symbol.elixir","settings":{"foreground":"#08c0ef"}},{"scope":"text.html.laravel-blade source.php.embedded.line.html entity.name.tag.laravel-blade","settings":{"foreground":"#ff678d"}},{"scope":"text.html.laravel-blade source.php.embedded.line.html support.constant.laravel-blade","settings":{"foreground":"#ff678d"}},{"scope":"entity.name.function.xi","settings":{"foreground":"#ffca00"}},{"scope":"entity.name.class.xi","settings":{"foreground":"#08c0ef"}},{"scope":"constant.character.character-class.regexp.xi","settings":{"foreground":"#ff6762"}},{"scope":"constant.regexp.xi","settings":{"foreground":"#ff678d"}},{"scope":"keyword.control.xi","settings":{"foreground":"#08c0ef"}},{"scope":"invalid.xi","settings":{"foreground":"#79797F"}},{"scope":"beginning.punctuation.definition.quote.markdown.xi","settings":{"foreground":"#5ecc71"}},{"scope":"beginning.punctuation.definition.list.markdown.xi","settings":{"foreground":"#84848A"}},{"scope":"constant.character.xi","settings":{"foreground":"#9d6afb"}},{"scope":"accent.xi","settings":{"foreground":"#9d6afb"}},{"scope":"wikiword.xi","settings":{"foreground":"#ffd452"}},{"scope":"constant.other.color.rgb-value.xi","settings":{"foreground":"#fbfbfb"}},{"scope":"punctuation.definition.tag.xi","settings":{"foreground":"#84848A"}},{"scope":["support.constant.property-value.scss","support.constant.property-value.css"],"settings":{"foreground":"#ffd452"}},{"scope":["keyword.operator.css","keyword.operator.scss","keyword.operator.less"],"settings":{"foreground":"#08c0ef"}},{"scope":["support.constant.color.w3c-standard-color-name.css","support.constant.color.w3c-standard-color-name.scss"],"settings":{"foreground":"#ffd452"}},{"scope":"punctuation.separator.list.comma.css","settings":{"foreground":"#79797F"}},{"scope":"support.type.vendored.property-name.css","settings":{"foreground":"#08c0ef"}},{"scope":"support.type.property-name.css","settings":{"foreground":"#08c0ef"}},{"scope":"support.type.property-name","settings":{"foreground":"#79797F"}},{"scope":"support.constant.property-value","settings":{"foreground":"#79797F"}},{"scope":"support.constant.font-name","settings":{"foreground":"#ffd452"}},{"scope":"entity.other.attribute-name.class.css","settings":{"foreground":"#61d5c0","fontStyle":"normal"}},{"scope":"entity.other.attribute-name.id","settings":{"foreground":"#9d6afb","fontStyle":"normal"}},{"scope":["entity.other.attribute-name.pseudo-element","entity.other.attribute-name.pseudo-class"],"settings":{"foreground":"#08c0ef"}},{"scope":"meta.selector","settings":{"foreground":"#ff678d"}},{"scope":"selector.sass","settings":{"foreground":"#ff6762"}},{"scope":"rgb-value","settings":{"foreground":"#08c0ef"}},{"scope":"inline-color-decoration rgb-value","settings":{"foreground":"#ffd452"}},{"scope":"less rgb-value","settings":{"foreground":"#ffd452"}},{"scope":"control.elements","settings":{"foreground":"#ffd452"}},{"scope":"keyword.operator.less","settings":{"foreground":"#ffd452"}},{"scope":"entity.name.tag","settings":{"foreground":"#ff6762"}},{"scope":"entity.other.attribute-name","settings":{"foreground":"#61d5c0","fontStyle":"normal"}},{"scope":"constant.character.entity","settings":{"foreground":"#ff6762"}},{"scope":"meta.tag","settings":{"foreground":"#79797F"}},{"scope":"invalid.illegal.bad-ampersand.html","settings":{"foreground":"#79797F"}},{"scope":"markup.heading","settings":{"foreground":"#ff6762"}},{"scope":["markup.heading punctuation.definition.heading","entity.name.section"],"settings":{"foreground":"#9d6afb"}},{"scope":"entity.name.section.markdown","settings":{"foreground":"#ff6762"}},{"scope":"punctuation.definition.heading.markdown","settings":{"foreground":"#ff6762"}},{"scope":"markup.heading.setext","settings":{"foreground":"#79797F"}},{"scope":["markup.heading.setext.1.markdown","markup.heading.setext.2.markdown"],"settings":{"foreground":"#ff6762"}},{"scope":["markup.bold","todo.bold"],"settings":{"foreground":"#ffd452"}},{"scope":"punctuation.definition.bold","settings":{"foreground":"#ffca00"}},{"scope":"punctuation.definition.bold.markdown","settings":{"foreground":"#ffd452"}},{"scope":["markup.italic","punctuation.definition.italic","todo.emphasis"],"settings":{"foreground":"#ff678d","fontStyle":"italic"}},{"scope":"emphasis md","settings":{"foreground":"#ff678d"}},{"scope":"markup.italic.markdown","settings":{"fontStyle":"italic"}},{"scope":["markup.underline.link.markdown","markup.underline.link.image.markdown"],"settings":{"foreground":"#ff678d"}},{"scope":["string.other.link.title.markdown","string.other.link.description.markdown"],"settings":{"foreground":"#9d6afb"}},{"scope":"punctuation.definition.metadata.markdown","settings":{"foreground":"#ff6762"}},{"scope":["markup.inline.raw.markdown","markup.inline.raw.string.markdown"],"settings":{"foreground":"#5ecc71"}},{"scope":"punctuation.definition.list.begin.markdown","settings":{"foreground":"#ff6762"}},{"scope":"punctuation.definition.list.markdown","settings":{"foreground":"#ff6762"}},{"scope":"beginning.punctuation.definition.list.markdown","settings":{"foreground":"#ff6762"}},{"scope":["punctuation.definition.string.begin.markdown","punctuation.definition.string.end.markdown"],"settings":{"foreground":"#ff6762"}},{"scope":"markup.quote.markdown","settings":{"foreground":"#84848A"}},{"scope":"keyword.other.unit","settings":{"foreground":"#ff6762"}},{"scope":"markup.changed.diff","settings":{"foreground":"#ffca00"}},{"scope":["meta.diff.header.from-file","meta.diff.header.to-file","punctuation.definition.from-file.diff","punctuation.definition.to-file.diff"],"settings":{"foreground":"#9d6afb"}},{"scope":"markup.inserted.diff","settings":{"foreground":"#5ecc71"}},{"scope":"markup.deleted.diff","settings":{"foreground":"#ff6762"}},{"scope":"string.regexp","settings":{"foreground":"#64d1db"}},{"scope":"constant.other.character-class.regexp","settings":{"foreground":"#ff6762"}},{"scope":"keyword.operator.quantifier.regexp","settings":{"foreground":"#ffd452"}},{"scope":"constant.character.escape","settings":{"foreground":"#68cdf2"}},{"scope":"source.json meta.structure.dictionary.json > string.quoted.json","settings":{"foreground":"#ff6762"}},{"scope":"source.json meta.structure.dictionary.json > string.quoted.json > punctuation.string","settings":{"foreground":"#ff6762"}},{"scope":["source.json meta.structure.dictionary.json > value.json > string.quoted.json","source.json meta.structure.array.json > value.json > string.quoted.json","source.json meta.structure.dictionary.json > value.json > string.quoted.json > punctuation","source.json meta.structure.array.json > value.json > string.quoted.json > punctuation"],"settings":{"foreground":"#5ecc71"}},{"scope":["source.json meta.structure.dictionary.json > constant.language.json","source.json meta.structure.array.json > constant.language.json"],"settings":{"foreground":"#08c0ef"}},{"scope":"support.type.property-name.json","settings":{"foreground":"#ff6762"}},{"scope":"support.type.property-name.json punctuation","settings":{"foreground":"#ff6762"}},{"scope":"punctuation.definition.block.sequence.item.yaml","settings":{"foreground":"#79797F"}},{"scope":"block.scope.end","settings":{"foreground":"#79797F"}},{"scope":"block.scope.begin","settings":{"foreground":"#79797F"}},{"scope":"token.info-token","settings":{"foreground":"#9d6afb"}},{"scope":"token.warn-token","settings":{"foreground":"#ffd452"}},{"scope":"token.error-token","settings":{"foreground":"#f44747"}},{"scope":"token.debug-token","settings":{"foreground":"#ff678d"}},{"scope":"invalid.illegal","settings":{"foreground":"#fbfbfb"}},{"scope":"invalid.broken","settings":{"foreground":"#fbfbfb"}},{"scope":"invalid.deprecated","settings":{"foreground":"#fbfbfb"}},{"scope":"invalid.unimplemented","settings":{"foreground":"#fbfbfb"}}],"semanticTokenColors":{"comment":"#84848A","string":"#5ecc71","number":"#68cdf2","regexp":"#64d1db","keyword":"#ff678d","variable":"#ffa359","parameter":"#adadb1","property":"#ffa359","function":"#9d6afb","method":"#9d6afb","type":"#d568ea","class":"#d568ea","namespace":"#ffca00","enumMember":"#08c0ef","variable.constant":"#ffd452","variable.defaultLibrary":"#ffca00"}}'));export{e as default}; diff --git a/lib/crates/fabro-spa/assets/assets/chunk-nghb2mxb.js b/lib/crates/fabro-spa/assets/assets/chunk-nghb2mxb.js new file mode 100644 index 000000000..db154f1f0 --- /dev/null +++ b/lib/crates/fabro-spa/assets/assets/chunk-nghb2mxb.js @@ -0,0 +1 @@ +import"./chunk-q07bg6gn.js";var e=Object.freeze(JSON.parse('{"name":"Pierre Light","type":"light","colors":{"editor.background":"#ffffff","editor.foreground":"#070707","foreground":"#070707","focusBorder":"#009fff","selection.background":"#dfebff","editor.selectionBackground":"#009fff2e","editor.lineHighlightBackground":"#dfebff8c","editorCursor.foreground":"#009fff","editorLineNumber.foreground":"#84848A","editorLineNumber.activeForeground":"#6C6C71","editorIndentGuide.background":"#eeeeef","editorIndentGuide.activeBackground":"#dbdbdd","diffEditor.insertedTextBackground":"#00cab133","diffEditor.deletedTextBackground":"#ff2e3f33","sideBar.background":"#f8f8f8","sideBar.foreground":"#6C6C71","sideBar.border":"#eeeeef","sideBarTitle.foreground":"#070707","sideBarSectionHeader.background":"#f8f8f8","sideBarSectionHeader.foreground":"#6C6C71","sideBarSectionHeader.border":"#eeeeef","activityBar.background":"#f8f8f8","activityBar.foreground":"#070707","activityBar.border":"#eeeeef","activityBar.activeBorder":"#009fff","activityBarBadge.background":"#009fff","activityBarBadge.foreground":"#ffffff","titleBar.activeBackground":"#f8f8f8","titleBar.activeForeground":"#070707","titleBar.inactiveBackground":"#f8f8f8","titleBar.inactiveForeground":"#84848A","titleBar.border":"#eeeeef","list.activeSelectionBackground":"#dfebffcc","list.activeSelectionForeground":"#070707","list.inactiveSelectionBackground":"#dfebff73","list.hoverBackground":"#dfebff59","list.focusOutline":"#009fff","tab.activeBackground":"#ffffff","tab.activeForeground":"#070707","tab.activeBorderTop":"#009fff","tab.inactiveBackground":"#f8f8f8","tab.inactiveForeground":"#84848A","tab.border":"#eeeeef","editorGroupHeader.tabsBackground":"#f8f8f8","editorGroupHeader.tabsBorder":"#eeeeef","panel.background":"#f8f8f8","panel.border":"#eeeeef","panelTitle.activeBorder":"#009fff","panelTitle.activeForeground":"#070707","panelTitle.inactiveForeground":"#84848A","statusBar.background":"#f8f8f8","statusBar.foreground":"#6C6C71","statusBar.border":"#eeeeef","statusBar.noFolderBackground":"#f8f8f8","statusBar.debuggingBackground":"#ffca00","statusBar.debuggingForeground":"#ffffff","statusBarItem.remoteBackground":"#f8f8f8","statusBarItem.remoteForeground":"#6C6C71","input.background":"#f2f2f3","input.border":"#dbdbdd","input.foreground":"#070707","input.placeholderForeground":"#8E8E95","dropdown.background":"#f2f2f3","dropdown.border":"#dbdbdd","dropdown.foreground":"#070707","button.background":"#009fff","button.foreground":"#ffffff","button.hoverBackground":"#1aa9ff","textLink.foreground":"#009fff","textLink.activeForeground":"#009fff","gitDecoration.addedResourceForeground":"#00cab1","gitDecoration.conflictingResourceForeground":"#ffca00","gitDecoration.modifiedResourceForeground":"#009fff","gitDecoration.deletedResourceForeground":"#ff2e3f","gitDecoration.untrackedResourceForeground":"#00cab1","gitDecoration.ignoredResourceForeground":"#84848A","terminal.titleForeground":"#6C6C71","terminal.titleInactiveForeground":"#84848A","terminal.background":"#f8f8f8","terminal.foreground":"#6C6C71","terminal.ansiBlack":"#1F1F21","terminal.ansiRed":"#ff2e3f","terminal.ansiGreen":"#0dbe4e","terminal.ansiYellow":"#ffca00","terminal.ansiBlue":"#009fff","terminal.ansiMagenta":"#c635e4","terminal.ansiCyan":"#08c0ef","terminal.ansiWhite":"#c6c6c8","terminal.ansiBrightBlack":"#1F1F21","terminal.ansiBrightRed":"#ff2e3f","terminal.ansiBrightGreen":"#0dbe4e","terminal.ansiBrightYellow":"#ffca00","terminal.ansiBrightBlue":"#009fff","terminal.ansiBrightMagenta":"#c635e4","terminal.ansiBrightCyan":"#08c0ef","terminal.ansiBrightWhite":"#c6c6c8"},"tokenColors":[{"scope":["comment","punctuation.definition.comment"],"settings":{"foreground":"#84848A"}},{"scope":"comment markup.link","settings":{"foreground":"#84848A"}},{"scope":["string","constant.other.symbol"],"settings":{"foreground":"#199f43"}},{"scope":["punctuation.definition.string.begin","punctuation.definition.string.end"],"settings":{"foreground":"#199f43"}},{"scope":["constant.numeric","constant.language.boolean"],"settings":{"foreground":"#1ca1c7"}},{"scope":"constant","settings":{"foreground":"#d5a910"}},{"scope":"punctuation.definition.constant","settings":{"foreground":"#d5a910"}},{"scope":"constant.language","settings":{"foreground":"#1ca1c7"}},{"scope":"variable.other.constant","settings":{"foreground":"#d5a910"}},{"scope":"keyword","settings":{"foreground":"#fc2b73"}},{"scope":"keyword.control","settings":{"foreground":"#fc2b73"}},{"scope":["storage","storage.type","storage.modifier"],"settings":{"foreground":"#fc2b73"}},{"scope":"token.storage","settings":{"foreground":"#fc2b73"}},{"scope":["keyword.operator.new","keyword.operator.expression.instanceof","keyword.operator.expression.typeof","keyword.operator.expression.void","keyword.operator.expression.delete","keyword.operator.expression.in","keyword.operator.expression.of","keyword.operator.expression.keyof"],"settings":{"foreground":"#fc2b73"}},{"scope":"keyword.operator.delete","settings":{"foreground":"#fc2b73"}},{"scope":["variable","identifier","meta.definition.variable"],"settings":{"foreground":"#d47628"}},{"scope":["variable.other.readwrite","meta.object-literal.key","support.variable.property","support.variable.object.process","support.variable.object.node"],"settings":{"foreground":"#d47628"}},{"scope":"variable.language","settings":{"foreground":"#d5a910"}},{"scope":"variable.parameter.function","settings":{"foreground":"#79797F"}},{"scope":"function.parameter","settings":{"foreground":"#79797F"}},{"scope":"variable.parameter","settings":{"foreground":"#79797F"}},{"scope":"variable.parameter.function.language.python","settings":{"foreground":"#d5a910"}},{"scope":"variable.parameter.function.python","settings":{"foreground":"#d5a910"}},{"scope":["support.function","entity.name.function","meta.function-call","meta.require","support.function.any-method","variable.function"],"settings":{"foreground":"#7b43f8"}},{"scope":"keyword.other.special-method","settings":{"foreground":"#7b43f8"}},{"scope":"entity.name.function","settings":{"foreground":"#7b43f8"}},{"scope":"support.function.console","settings":{"foreground":"#7b43f8"}},{"scope":["support.type","entity.name.type","entity.name.class","storage.type"],"settings":{"foreground":"#c635e4"}},{"scope":["support.class","entity.name.type.class"],"settings":{"foreground":"#c635e4"}},{"scope":["entity.name.class","variable.other.class.js","variable.other.class.ts"],"settings":{"foreground":"#c635e4"}},{"scope":"entity.name.class.identifier.namespace.type","settings":{"foreground":"#c635e4"}},{"scope":"entity.name.type.namespace","settings":{"foreground":"#d5a910"}},{"scope":"entity.other.inherited-class","settings":{"foreground":"#c635e4"}},{"scope":"entity.name.namespace","settings":{"foreground":"#d5a910"}},{"scope":"keyword.operator","settings":{"foreground":"#79797F"}},{"scope":["keyword.operator.logical","keyword.operator.bitwise","keyword.operator.channel"],"settings":{"foreground":"#08c0ef"}},{"scope":["keyword.operator.arithmetic","keyword.operator.comparison","keyword.operator.relational","keyword.operator.increment","keyword.operator.decrement"],"settings":{"foreground":"#08c0ef"}},{"scope":"keyword.operator.assignment","settings":{"foreground":"#08c0ef"}},{"scope":"keyword.operator.assignment.compound","settings":{"foreground":"#fc2b73"}},{"scope":["keyword.operator.assignment.compound.js","keyword.operator.assignment.compound.ts"],"settings":{"foreground":"#08c0ef"}},{"scope":"keyword.operator.ternary","settings":{"foreground":"#fc2b73"}},{"scope":"keyword.operator.optional","settings":{"foreground":"#fc2b73"}},{"scope":"punctuation","settings":{"foreground":"#79797F"}},{"scope":"punctuation.separator.delimiter","settings":{"foreground":"#79797F"}},{"scope":"punctuation.separator.key-value","settings":{"foreground":"#79797F"}},{"scope":"punctuation.terminator","settings":{"foreground":"#79797F"}},{"scope":"meta.brace","settings":{"foreground":"#79797F"}},{"scope":"meta.brace.square","settings":{"foreground":"#79797F"}},{"scope":"meta.brace.round","settings":{"foreground":"#79797F"}},{"scope":"function.brace","settings":{"foreground":"#79797F"}},{"scope":["punctuation.definition.parameters","punctuation.definition.typeparameters"],"settings":{"foreground":"#79797F"}},{"scope":["punctuation.definition.block","punctuation.definition.tag"],"settings":{"foreground":"#79797F"}},{"scope":["meta.tag.tsx","meta.tag.jsx","meta.tag.js","meta.tag.ts"],"settings":{"foreground":"#79797F"}},{"scope":"keyword.operator.expression.import","settings":{"foreground":"#7b43f8"}},{"scope":"keyword.operator.module","settings":{"foreground":"#fc2b73"}},{"scope":"support.type.object.console","settings":{"foreground":"#d47628"}},{"scope":["support.module.node","support.type.object.module","entity.name.type.module"],"settings":{"foreground":"#d5a910"}},{"scope":"support.constant.math","settings":{"foreground":"#d5a910"}},{"scope":"support.constant.property.math","settings":{"foreground":"#d5a910"}},{"scope":"support.constant.json","settings":{"foreground":"#d5a910"}},{"scope":"support.type.object.dom","settings":{"foreground":"#08c0ef"}},{"scope":["support.variable.dom","support.variable.property.dom"],"settings":{"foreground":"#d47628"}},{"scope":"support.variable.property.process","settings":{"foreground":"#d5a910"}},{"scope":"meta.property.object","settings":{"foreground":"#d47628"}},{"scope":"variable.parameter.function.js","settings":{"foreground":"#d47628"}},{"scope":["keyword.other.template.begin","keyword.other.template.end"],"settings":{"foreground":"#199f43"}},{"scope":["keyword.other.substitution.begin","keyword.other.substitution.end"],"settings":{"foreground":"#199f43"}},{"scope":["punctuation.definition.template-expression.begin","punctuation.definition.template-expression.end"],"settings":{"foreground":"#fc2b73"}},{"scope":"meta.template.expression","settings":{"foreground":"#79797F"}},{"scope":"punctuation.section.embedded","settings":{"foreground":"#d47628"}},{"scope":"variable.interpolation","settings":{"foreground":"#d47628"}},{"scope":["punctuation.section.embedded.begin","punctuation.section.embedded.end"],"settings":{"foreground":"#fc2b73"}},{"scope":"punctuation.quasi.element","settings":{"foreground":"#fc2b73"}},{"scope":["support.type.primitive.ts","support.type.builtin.ts","support.type.primitive.tsx","support.type.builtin.tsx"],"settings":{"foreground":"#c635e4"}},{"scope":"support.type.type.flowtype","settings":{"foreground":"#7b43f8"}},{"scope":"support.type.primitive","settings":{"foreground":"#c635e4"}},{"scope":"support.variable.magic.python","settings":{"foreground":"#d52c36"}},{"scope":"variable.parameter.function.language.special.self.python","settings":{"foreground":"#d5a910"}},{"scope":["punctuation.separator.period.python","punctuation.separator.element.python","punctuation.parenthesis.begin.python","punctuation.parenthesis.end.python"],"settings":{"foreground":"#79797F"}},{"scope":["punctuation.definition.arguments.begin.python","punctuation.definition.arguments.end.python","punctuation.separator.arguments.python","punctuation.definition.list.begin.python","punctuation.definition.list.end.python"],"settings":{"foreground":"#79797F"}},{"scope":"support.type.python","settings":{"foreground":"#08c0ef"}},{"scope":"keyword.operator.logical.python","settings":{"foreground":"#fc2b73"}},{"scope":"meta.function-call.generic.python","settings":{"foreground":"#7b43f8"}},{"scope":"constant.character.format.placeholder.other.python","settings":{"foreground":"#d5a910"}},{"scope":"meta.function.decorator.python","settings":{"foreground":"#7b43f8"}},{"scope":["support.token.decorator.python","meta.function.decorator.identifier.python"],"settings":{"foreground":"#08c0ef"}},{"scope":"storage.modifier.lifetime.rust","settings":{"foreground":"#79797F"}},{"scope":"support.function.std.rust","settings":{"foreground":"#7b43f8"}},{"scope":"entity.name.lifetime.rust","settings":{"foreground":"#d5a910"}},{"scope":"variable.language.rust","settings":{"foreground":"#d52c36"}},{"scope":"keyword.operator.misc.rust","settings":{"foreground":"#79797F"}},{"scope":"keyword.operator.sigil.rust","settings":{"foreground":"#fc2b73"}},{"scope":"support.constant.core.rust","settings":{"foreground":"#d5a910"}},{"scope":["meta.function.c","meta.function.cpp"],"settings":{"foreground":"#d52c36"}},{"scope":["punctuation.section.block.begin.bracket.curly.cpp","punctuation.section.block.end.bracket.curly.cpp","punctuation.terminator.statement.c","punctuation.section.block.begin.bracket.curly.c","punctuation.section.block.end.bracket.curly.c","punctuation.section.parens.begin.bracket.round.c","punctuation.section.parens.end.bracket.round.c","punctuation.section.parameters.begin.bracket.round.c","punctuation.section.parameters.end.bracket.round.c"],"settings":{"foreground":"#79797F"}},{"scope":["keyword.operator.assignment.c","keyword.operator.comparison.c","keyword.operator.c","keyword.operator.increment.c","keyword.operator.decrement.c","keyword.operator.bitwise.shift.c"],"settings":{"foreground":"#fc2b73"}},{"scope":["keyword.operator.assignment.cpp","keyword.operator.comparison.cpp","keyword.operator.cpp","keyword.operator.increment.cpp","keyword.operator.decrement.cpp","keyword.operator.bitwise.shift.cpp"],"settings":{"foreground":"#fc2b73"}},{"scope":["punctuation.separator.c","punctuation.separator.cpp"],"settings":{"foreground":"#fc2b73"}},{"scope":["support.type.posix-reserved.c","support.type.posix-reserved.cpp"],"settings":{"foreground":"#08c0ef"}},{"scope":["keyword.operator.sizeof.c","keyword.operator.sizeof.cpp"],"settings":{"foreground":"#fc2b73"}},{"scope":"variable.c","settings":{"foreground":"#79797F"}},{"scope":["storage.type.annotation.java","storage.type.object.array.java"],"settings":{"foreground":"#d5a910"}},{"scope":"source.java","settings":{"foreground":"#d52c36"}},{"scope":["punctuation.section.block.begin.java","punctuation.section.block.end.java","punctuation.definition.method-parameters.begin.java","punctuation.definition.method-parameters.end.java","meta.method.identifier.java","punctuation.section.method.begin.java","punctuation.section.method.end.java","punctuation.terminator.java","punctuation.section.class.begin.java","punctuation.section.class.end.java","punctuation.section.inner-class.begin.java","punctuation.section.inner-class.end.java","meta.method-call.java","punctuation.section.class.begin.bracket.curly.java","punctuation.section.class.end.bracket.curly.java","punctuation.section.method.begin.bracket.curly.java","punctuation.section.method.end.bracket.curly.java","punctuation.separator.period.java","punctuation.bracket.angle.java","punctuation.definition.annotation.java","meta.method.body.java"],"settings":{"foreground":"#79797F"}},{"scope":"meta.method.java","settings":{"foreground":"#7b43f8"}},{"scope":["storage.modifier.import.java","storage.type.java","storage.type.generic.java"],"settings":{"foreground":"#d5a910"}},{"scope":"keyword.operator.instanceof.java","settings":{"foreground":"#fc2b73"}},{"scope":"meta.definition.variable.name.java","settings":{"foreground":"#d52c36"}},{"scope":"token.variable.parameter.java","settings":{"foreground":"#79797F"}},{"scope":"import.storage.java","settings":{"foreground":"#d5a910"}},{"scope":"token.package.keyword","settings":{"foreground":"#fc2b73"}},{"scope":"token.package","settings":{"foreground":"#79797F"}},{"scope":"token.storage.type.java","settings":{"foreground":"#d5a910"}},{"scope":"keyword.operator.assignment.go","settings":{"foreground":"#d5a910"}},{"scope":["keyword.operator.arithmetic.go","keyword.operator.address.go"],"settings":{"foreground":"#fc2b73"}},{"scope":"entity.name.package.go","settings":{"foreground":"#d5a910"}},{"scope":["support.other.namespace.use.php","support.other.namespace.use-as.php","support.other.namespace.php","entity.other.alias.php","meta.interface.php"],"settings":{"foreground":"#d5a910"}},{"scope":"keyword.operator.error-control.php","settings":{"foreground":"#fc2b73"}},{"scope":"keyword.operator.type.php","settings":{"foreground":"#fc2b73"}},{"scope":["punctuation.section.array.begin.php","punctuation.section.array.end.php"],"settings":{"foreground":"#79797F"}},{"scope":["storage.type.php","meta.other.type.phpdoc.php","keyword.other.type.php","keyword.other.array.phpdoc.php"],"settings":{"foreground":"#d5a910"}},{"scope":["meta.function-call.php","meta.function-call.object.php","meta.function-call.static.php"],"settings":{"foreground":"#7b43f8"}},{"scope":["punctuation.definition.parameters.begin.bracket.round.php","punctuation.definition.parameters.end.bracket.round.php","punctuation.separator.delimiter.php","punctuation.section.scope.begin.php","punctuation.section.scope.end.php","punctuation.terminator.expression.php","punctuation.definition.arguments.begin.bracket.round.php","punctuation.definition.arguments.end.bracket.round.php","punctuation.definition.storage-type.begin.bracket.round.php","punctuation.definition.storage-type.end.bracket.round.php","punctuation.definition.array.begin.bracket.round.php","punctuation.definition.array.end.bracket.round.php","punctuation.definition.begin.bracket.round.php","punctuation.definition.end.bracket.round.php","punctuation.definition.begin.bracket.curly.php","punctuation.definition.end.bracket.curly.php","punctuation.definition.section.switch-block.end.bracket.curly.php","punctuation.definition.section.switch-block.start.bracket.curly.php","punctuation.definition.section.switch-block.begin.bracket.curly.php","punctuation.definition.section.switch-block.end.bracket.curly.php"],"settings":{"foreground":"#79797F"}},{"scope":["support.constant.ext.php","support.constant.std.php","support.constant.core.php","support.constant.parser-token.php"],"settings":{"foreground":"#d5a910"}},{"scope":["entity.name.goto-label.php","support.other.php"],"settings":{"foreground":"#7b43f8"}},{"scope":["keyword.operator.logical.php","keyword.operator.bitwise.php","keyword.operator.arithmetic.php"],"settings":{"foreground":"#08c0ef"}},{"scope":"keyword.operator.regexp.php","settings":{"foreground":"#fc2b73"}},{"scope":"keyword.operator.comparison.php","settings":{"foreground":"#08c0ef"}},{"scope":["keyword.operator.heredoc.php","keyword.operator.nowdoc.php"],"settings":{"foreground":"#fc2b73"}},{"scope":"variable.other.class.php","settings":{"foreground":"#d52c36"}},{"scope":"invalid.illegal.non-null-typehinted.php","settings":{"foreground":"#f44747"}},{"scope":"variable.other.generic-type.haskell","settings":{"foreground":"#fc2b73"}},{"scope":"storage.type.haskell","settings":{"foreground":"#d5a910"}},{"scope":"storage.type.cs","settings":{"foreground":"#d5a910"}},{"scope":"entity.name.variable.local.cs","settings":{"foreground":"#d52c36"}},{"scope":"entity.name.label.cs","settings":{"foreground":"#d5a910"}},{"scope":["entity.name.scope-resolution.function.call","entity.name.scope-resolution.function.definition"],"settings":{"foreground":"#d5a910"}},{"scope":["punctuation.definition.delayed.unison","punctuation.definition.list.begin.unison","punctuation.definition.list.end.unison","punctuation.definition.ability.begin.unison","punctuation.definition.ability.end.unison","punctuation.operator.assignment.as.unison","punctuation.separator.pipe.unison","punctuation.separator.delimiter.unison","punctuation.definition.hash.unison"],"settings":{"foreground":"#d52c36"}},{"scope":"support.constant.edge","settings":{"foreground":"#fc2b73"}},{"scope":"support.type.prelude.elm","settings":{"foreground":"#08c0ef"}},{"scope":"support.constant.elm","settings":{"foreground":"#d5a910"}},{"scope":"entity.global.clojure","settings":{"foreground":"#d5a910"}},{"scope":"meta.symbol.clojure","settings":{"foreground":"#d52c36"}},{"scope":"constant.keyword.clojure","settings":{"foreground":"#08c0ef"}},{"scope":["meta.arguments.coffee","variable.parameter.function.coffee"],"settings":{"foreground":"#d52c36"}},{"scope":"storage.modifier.import.groovy","settings":{"foreground":"#d5a910"}},{"scope":"meta.method.groovy","settings":{"foreground":"#7b43f8"}},{"scope":"meta.definition.variable.name.groovy","settings":{"foreground":"#d52c36"}},{"scope":"meta.definition.class.inherited.classes.groovy","settings":{"foreground":"#199f43"}},{"scope":"support.variable.semantic.hlsl","settings":{"foreground":"#d5a910"}},{"scope":["support.type.texture.hlsl","support.type.sampler.hlsl","support.type.object.hlsl","support.type.object.rw.hlsl","support.type.fx.hlsl","support.type.object.hlsl"],"settings":{"foreground":"#fc2b73"}},{"scope":["text.variable","text.bracketed"],"settings":{"foreground":"#d52c36"}},{"scope":["support.type.swift","support.type.vb.asp"],"settings":{"foreground":"#d5a910"}},{"scope":"meta.scope.prerequisites.makefile","settings":{"foreground":"#d52c36"}},{"scope":"source.makefile","settings":{"foreground":"#d5a910"}},{"scope":"source.ini","settings":{"foreground":"#199f43"}},{"scope":"constant.language.symbol.ruby","settings":{"foreground":"#08c0ef"}},{"scope":["function.parameter.ruby","function.parameter.cs"],"settings":{"foreground":"#79797F"}},{"scope":"constant.language.symbol.elixir","settings":{"foreground":"#08c0ef"}},{"scope":"text.html.laravel-blade source.php.embedded.line.html entity.name.tag.laravel-blade","settings":{"foreground":"#fc2b73"}},{"scope":"text.html.laravel-blade source.php.embedded.line.html support.constant.laravel-blade","settings":{"foreground":"#fc2b73"}},{"scope":"entity.name.function.xi","settings":{"foreground":"#d5a910"}},{"scope":"entity.name.class.xi","settings":{"foreground":"#08c0ef"}},{"scope":"constant.character.character-class.regexp.xi","settings":{"foreground":"#d52c36"}},{"scope":"constant.regexp.xi","settings":{"foreground":"#fc2b73"}},{"scope":"keyword.control.xi","settings":{"foreground":"#08c0ef"}},{"scope":"invalid.xi","settings":{"foreground":"#79797F"}},{"scope":"beginning.punctuation.definition.quote.markdown.xi","settings":{"foreground":"#199f43"}},{"scope":"beginning.punctuation.definition.list.markdown.xi","settings":{"foreground":"#84848A"}},{"scope":"constant.character.xi","settings":{"foreground":"#7b43f8"}},{"scope":"accent.xi","settings":{"foreground":"#7b43f8"}},{"scope":"wikiword.xi","settings":{"foreground":"#d5a910"}},{"scope":"constant.other.color.rgb-value.xi","settings":{"foreground":"#070707"}},{"scope":"punctuation.definition.tag.xi","settings":{"foreground":"#84848A"}},{"scope":["support.constant.property-value.scss","support.constant.property-value.css"],"settings":{"foreground":"#d5a910"}},{"scope":["keyword.operator.css","keyword.operator.scss","keyword.operator.less"],"settings":{"foreground":"#08c0ef"}},{"scope":["support.constant.color.w3c-standard-color-name.css","support.constant.color.w3c-standard-color-name.scss"],"settings":{"foreground":"#d5a910"}},{"scope":"punctuation.separator.list.comma.css","settings":{"foreground":"#79797F"}},{"scope":"support.type.vendored.property-name.css","settings":{"foreground":"#08c0ef"}},{"scope":"support.type.property-name.css","settings":{"foreground":"#08c0ef"}},{"scope":"support.type.property-name","settings":{"foreground":"#79797F"}},{"scope":"support.constant.property-value","settings":{"foreground":"#79797F"}},{"scope":"support.constant.font-name","settings":{"foreground":"#d5a910"}},{"scope":"entity.other.attribute-name.class.css","settings":{"foreground":"#16a994","fontStyle":"normal"}},{"scope":"entity.other.attribute-name.id","settings":{"foreground":"#7b43f8","fontStyle":"normal"}},{"scope":["entity.other.attribute-name.pseudo-element","entity.other.attribute-name.pseudo-class"],"settings":{"foreground":"#08c0ef"}},{"scope":"meta.selector","settings":{"foreground":"#fc2b73"}},{"scope":"selector.sass","settings":{"foreground":"#d52c36"}},{"scope":"rgb-value","settings":{"foreground":"#08c0ef"}},{"scope":"inline-color-decoration rgb-value","settings":{"foreground":"#d5a910"}},{"scope":"less rgb-value","settings":{"foreground":"#d5a910"}},{"scope":"control.elements","settings":{"foreground":"#d5a910"}},{"scope":"keyword.operator.less","settings":{"foreground":"#d5a910"}},{"scope":"entity.name.tag","settings":{"foreground":"#d52c36"}},{"scope":"entity.other.attribute-name","settings":{"foreground":"#16a994","fontStyle":"normal"}},{"scope":"constant.character.entity","settings":{"foreground":"#d52c36"}},{"scope":"meta.tag","settings":{"foreground":"#79797F"}},{"scope":"invalid.illegal.bad-ampersand.html","settings":{"foreground":"#79797F"}},{"scope":"markup.heading","settings":{"foreground":"#d52c36"}},{"scope":["markup.heading punctuation.definition.heading","entity.name.section"],"settings":{"foreground":"#7b43f8"}},{"scope":"entity.name.section.markdown","settings":{"foreground":"#d52c36"}},{"scope":"punctuation.definition.heading.markdown","settings":{"foreground":"#d52c36"}},{"scope":"markup.heading.setext","settings":{"foreground":"#79797F"}},{"scope":["markup.heading.setext.1.markdown","markup.heading.setext.2.markdown"],"settings":{"foreground":"#d52c36"}},{"scope":["markup.bold","todo.bold"],"settings":{"foreground":"#d5a910"}},{"scope":"punctuation.definition.bold","settings":{"foreground":"#d5a910"}},{"scope":"punctuation.definition.bold.markdown","settings":{"foreground":"#d5a910"}},{"scope":["markup.italic","punctuation.definition.italic","todo.emphasis"],"settings":{"foreground":"#fc2b73","fontStyle":"italic"}},{"scope":"emphasis md","settings":{"foreground":"#fc2b73"}},{"scope":"markup.italic.markdown","settings":{"fontStyle":"italic"}},{"scope":["markup.underline.link.markdown","markup.underline.link.image.markdown"],"settings":{"foreground":"#fc2b73"}},{"scope":["string.other.link.title.markdown","string.other.link.description.markdown"],"settings":{"foreground":"#7b43f8"}},{"scope":"punctuation.definition.metadata.markdown","settings":{"foreground":"#d52c36"}},{"scope":["markup.inline.raw.markdown","markup.inline.raw.string.markdown"],"settings":{"foreground":"#199f43"}},{"scope":"punctuation.definition.list.begin.markdown","settings":{"foreground":"#d52c36"}},{"scope":"punctuation.definition.list.markdown","settings":{"foreground":"#d52c36"}},{"scope":"beginning.punctuation.definition.list.markdown","settings":{"foreground":"#d52c36"}},{"scope":["punctuation.definition.string.begin.markdown","punctuation.definition.string.end.markdown"],"settings":{"foreground":"#d52c36"}},{"scope":"markup.quote.markdown","settings":{"foreground":"#84848A"}},{"scope":"keyword.other.unit","settings":{"foreground":"#d52c36"}},{"scope":"markup.changed.diff","settings":{"foreground":"#d5a910"}},{"scope":["meta.diff.header.from-file","meta.diff.header.to-file","punctuation.definition.from-file.diff","punctuation.definition.to-file.diff"],"settings":{"foreground":"#7b43f8"}},{"scope":"markup.inserted.diff","settings":{"foreground":"#199f43"}},{"scope":"markup.deleted.diff","settings":{"foreground":"#d52c36"}},{"scope":"string.regexp","settings":{"foreground":"#17a5af"}},{"scope":"constant.other.character-class.regexp","settings":{"foreground":"#d52c36"}},{"scope":"keyword.operator.quantifier.regexp","settings":{"foreground":"#d5a910"}},{"scope":"constant.character.escape","settings":{"foreground":"#1ca1c7"}},{"scope":"source.json meta.structure.dictionary.json > string.quoted.json","settings":{"foreground":"#d52c36"}},{"scope":"source.json meta.structure.dictionary.json > string.quoted.json > punctuation.string","settings":{"foreground":"#d52c36"}},{"scope":["source.json meta.structure.dictionary.json > value.json > string.quoted.json","source.json meta.structure.array.json > value.json > string.quoted.json","source.json meta.structure.dictionary.json > value.json > string.quoted.json > punctuation","source.json meta.structure.array.json > value.json > string.quoted.json > punctuation"],"settings":{"foreground":"#199f43"}},{"scope":["source.json meta.structure.dictionary.json > constant.language.json","source.json meta.structure.array.json > constant.language.json"],"settings":{"foreground":"#08c0ef"}},{"scope":"support.type.property-name.json","settings":{"foreground":"#d52c36"}},{"scope":"support.type.property-name.json punctuation","settings":{"foreground":"#d52c36"}},{"scope":"punctuation.definition.block.sequence.item.yaml","settings":{"foreground":"#79797F"}},{"scope":"block.scope.end","settings":{"foreground":"#79797F"}},{"scope":"block.scope.begin","settings":{"foreground":"#79797F"}},{"scope":"token.info-token","settings":{"foreground":"#7b43f8"}},{"scope":"token.warn-token","settings":{"foreground":"#d5a910"}},{"scope":"token.error-token","settings":{"foreground":"#f44747"}},{"scope":"token.debug-token","settings":{"foreground":"#fc2b73"}},{"scope":"invalid.illegal","settings":{"foreground":"#070707"}},{"scope":"invalid.broken","settings":{"foreground":"#070707"}},{"scope":"invalid.deprecated","settings":{"foreground":"#070707"}},{"scope":"invalid.unimplemented","settings":{"foreground":"#070707"}}],"semanticTokenColors":{"comment":"#84848A","string":"#199f43","number":"#1ca1c7","regexp":"#17a5af","keyword":"#fc2b73","variable":"#d47628","parameter":"#79797F","property":"#d47628","function":"#7b43f8","method":"#7b43f8","type":"#c635e4","class":"#c635e4","namespace":"#d5a910","enumMember":"#08c0ef","variable.constant":"#d5a910","variable.defaultLibrary":"#d5a910"}}'));export{e as default}; diff --git a/lib/crates/fabro-spa/assets/assets/chunk-q2qv5qr4.js b/lib/crates/fabro-spa/assets/assets/chunk-q2qv5qr4.js deleted file mode 100644 index 8d5674785..000000000 --- a/lib/crates/fabro-spa/assets/assets/chunk-q2qv5qr4.js +++ /dev/null @@ -1 +0,0 @@ -import"./chunk-q07bg6gn.js";var b="pierre-dark",h="dark",q={"editor.background":"#070707","editor.foreground":"#fbfbfb",foreground:"#fbfbfb",focusBorder:"#009fff","selection.background":"#19283c","editor.selectionBackground":"#009fff4d","editor.lineHighlightBackground":"#19283c8c","editorCursor.foreground":"#009fff","editorLineNumber.foreground":"#84848A","editorLineNumber.activeForeground":"#adadb1","editorIndentGuide.background":"#39393c","editorIndentGuide.activeBackground":"#2e2e30","diffEditor.insertedTextBackground":"#00cab11a","diffEditor.deletedTextBackground":"#ff2e3f1a","sideBar.background":"#141415","sideBar.foreground":"#adadb1","sideBar.border":"#070707","sideBarTitle.foreground":"#fbfbfb","sideBarSectionHeader.background":"#141415","sideBarSectionHeader.foreground":"#adadb1","sideBarSectionHeader.border":"#070707","activityBar.background":"#141415","activityBar.foreground":"#fbfbfb","activityBar.border":"#070707","activityBar.activeBorder":"#009fff","activityBarBadge.background":"#009fff","activityBarBadge.foreground":"#070707","titleBar.activeBackground":"#141415","titleBar.activeForeground":"#fbfbfb","titleBar.inactiveBackground":"#141415","titleBar.inactiveForeground":"#84848A","titleBar.border":"#070707","list.activeSelectionBackground":"#19283c99","list.activeSelectionForeground":"#fbfbfb","list.inactiveSelectionBackground":"#19283c73","list.hoverBackground":"#19283c59","list.focusOutline":"#009fff","tab.activeBackground":"#070707","tab.activeForeground":"#fbfbfb","tab.activeBorderTop":"#009fff","tab.inactiveBackground":"#141415","tab.inactiveForeground":"#84848A","tab.border":"#070707","editorGroupHeader.tabsBackground":"#141415","editorGroupHeader.tabsBorder":"#070707","panel.background":"#141415","panel.border":"#070707","panelTitle.activeBorder":"#009fff","panelTitle.activeForeground":"#fbfbfb","panelTitle.inactiveForeground":"#84848A","statusBar.background":"#141415","statusBar.foreground":"#adadb1","statusBar.border":"#070707","statusBar.noFolderBackground":"#141415","statusBar.debuggingBackground":"#ffca00","statusBar.debuggingForeground":"#070707","statusBarItem.remoteBackground":"#141415","statusBarItem.remoteForeground":"#adadb1","input.background":"#1F1F21","input.border":"#424245","input.foreground":"#fbfbfb","input.placeholderForeground":"#79797F","dropdown.background":"#1F1F21","dropdown.border":"#424245","dropdown.foreground":"#fbfbfb","button.background":"#009fff","button.foreground":"#070707","button.hoverBackground":"#0190e6","textLink.foreground":"#009fff","textLink.activeForeground":"#009fff","gitDecoration.addedResourceForeground":"#00cab1","gitDecoration.conflictingResourceForeground":"#ffca00","gitDecoration.modifiedResourceForeground":"#009fff","gitDecoration.deletedResourceForeground":"#ff2e3f","gitDecoration.untrackedResourceForeground":"#00cab1","gitDecoration.ignoredResourceForeground":"#84848A","terminal.titleForeground":"#adadb1","terminal.titleInactiveForeground":"#84848A","terminal.background":"#141415","terminal.foreground":"#adadb1","terminal.ansiBlack":"#141415","terminal.ansiRed":"#ff2e3f","terminal.ansiGreen":"#0dbe4e","terminal.ansiYellow":"#ffca00","terminal.ansiBlue":"#009fff","terminal.ansiMagenta":"#c635e4","terminal.ansiCyan":"#08c0ef","terminal.ansiWhite":"#c6c6c8","terminal.ansiBrightBlack":"#141415","terminal.ansiBrightRed":"#ff2e3f","terminal.ansiBrightGreen":"#0dbe4e","terminal.ansiBrightYellow":"#ffca00","terminal.ansiBrightBlue":"#009fff","terminal.ansiBrightMagenta":"#c635e4","terminal.ansiBrightCyan":"#08c0ef","terminal.ansiBrightWhite":"#c6c6c8"},v=[{scope:["comment","punctuation.definition.comment"],settings:{foreground:"#84848A"}},{scope:"comment markup.link",settings:{foreground:"#84848A"}},{scope:["string","constant.other.symbol"],settings:{foreground:"#5ecc71"}},{scope:["punctuation.definition.string.begin","punctuation.definition.string.end"],settings:{foreground:"#5ecc71"}},{scope:["constant.numeric","constant.language.boolean"],settings:{foreground:"#68cdf2"}},{scope:"constant",settings:{foreground:"#ffd452"}},{scope:"punctuation.definition.constant",settings:{foreground:"#ffd452"}},{scope:"constant.language",settings:{foreground:"#68cdf2"}},{scope:"variable.other.constant",settings:{foreground:"#ffca00"}},{scope:"keyword",settings:{foreground:"#ff678d"}},{scope:"keyword.control",settings:{foreground:"#ff678d"}},{scope:["storage","storage.type","storage.modifier"],settings:{foreground:"#ff678d"}},{scope:"token.storage",settings:{foreground:"#ff678d"}},{scope:["keyword.operator.new","keyword.operator.expression.instanceof","keyword.operator.expression.typeof","keyword.operator.expression.void","keyword.operator.expression.delete","keyword.operator.expression.in","keyword.operator.expression.of","keyword.operator.expression.keyof"],settings:{foreground:"#ff678d"}},{scope:"keyword.operator.delete",settings:{foreground:"#ff678d"}},{scope:["variable","identifier","meta.definition.variable"],settings:{foreground:"#ffa359"}},{scope:["variable.other.readwrite","meta.object-literal.key","support.variable.property","support.variable.object.process","support.variable.object.node"],settings:{foreground:"#ffa359"}},{scope:"variable.language",settings:{foreground:"#ffca00"}},{scope:"variable.parameter.function",settings:{foreground:"#adadb1"}},{scope:"function.parameter",settings:{foreground:"#adadb1"}},{scope:"variable.parameter",settings:{foreground:"#adadb1"}},{scope:"variable.parameter.function.language.python",settings:{foreground:"#ffd452"}},{scope:"variable.parameter.function.python",settings:{foreground:"#ffd452"}},{scope:["support.function","entity.name.function","meta.function-call","meta.require","support.function.any-method","variable.function"],settings:{foreground:"#9d6afb"}},{scope:"keyword.other.special-method",settings:{foreground:"#9d6afb"}},{scope:"entity.name.function",settings:{foreground:"#9d6afb"}},{scope:"support.function.console",settings:{foreground:"#9d6afb"}},{scope:["support.type","entity.name.type","entity.name.class","storage.type"],settings:{foreground:"#d568ea"}},{scope:["support.class","entity.name.type.class"],settings:{foreground:"#d568ea"}},{scope:["entity.name.class","variable.other.class.js","variable.other.class.ts"],settings:{foreground:"#d568ea"}},{scope:"entity.name.class.identifier.namespace.type",settings:{foreground:"#d568ea"}},{scope:"entity.name.type.namespace",settings:{foreground:"#ffca00"}},{scope:"entity.other.inherited-class",settings:{foreground:"#d568ea"}},{scope:"entity.name.namespace",settings:{foreground:"#ffca00"}},{scope:"keyword.operator",settings:{foreground:"#79797F"}},{scope:["keyword.operator.logical","keyword.operator.bitwise","keyword.operator.channel"],settings:{foreground:"#08c0ef"}},{scope:["keyword.operator.arithmetic","keyword.operator.comparison","keyword.operator.relational","keyword.operator.increment","keyword.operator.decrement"],settings:{foreground:"#08c0ef"}},{scope:"keyword.operator.assignment",settings:{foreground:"#08c0ef"}},{scope:"keyword.operator.assignment.compound",settings:{foreground:"#ff678d"}},{scope:["keyword.operator.assignment.compound.js","keyword.operator.assignment.compound.ts"],settings:{foreground:"#08c0ef"}},{scope:"keyword.operator.ternary",settings:{foreground:"#ff678d"}},{scope:"keyword.operator.optional",settings:{foreground:"#ff678d"}},{scope:"punctuation",settings:{foreground:"#79797F"}},{scope:"punctuation.separator.delimiter",settings:{foreground:"#79797F"}},{scope:"punctuation.separator.key-value",settings:{foreground:"#79797F"}},{scope:"punctuation.terminator",settings:{foreground:"#79797F"}},{scope:"meta.brace",settings:{foreground:"#79797F"}},{scope:"meta.brace.square",settings:{foreground:"#79797F"}},{scope:"meta.brace.round",settings:{foreground:"#79797F"}},{scope:"function.brace",settings:{foreground:"#79797F"}},{scope:["punctuation.definition.parameters","punctuation.definition.typeparameters"],settings:{foreground:"#79797F"}},{scope:["punctuation.definition.block","punctuation.definition.tag"],settings:{foreground:"#79797F"}},{scope:["meta.tag.tsx","meta.tag.jsx","meta.tag.js","meta.tag.ts"],settings:{foreground:"#79797F"}},{scope:"keyword.operator.expression.import",settings:{foreground:"#9d6afb"}},{scope:"keyword.operator.module",settings:{foreground:"#ff678d"}},{scope:"support.type.object.console",settings:{foreground:"#ffa359"}},{scope:["support.module.node","support.type.object.module","entity.name.type.module"],settings:{foreground:"#ffca00"}},{scope:"support.constant.math",settings:{foreground:"#ffca00"}},{scope:"support.constant.property.math",settings:{foreground:"#ffd452"}},{scope:"support.constant.json",settings:{foreground:"#ffd452"}},{scope:"support.type.object.dom",settings:{foreground:"#08c0ef"}},{scope:["support.variable.dom","support.variable.property.dom"],settings:{foreground:"#ffa359"}},{scope:"support.variable.property.process",settings:{foreground:"#ffd452"}},{scope:"meta.property.object",settings:{foreground:"#ffa359"}},{scope:"variable.parameter.function.js",settings:{foreground:"#ffa359"}},{scope:["keyword.other.template.begin","keyword.other.template.end"],settings:{foreground:"#5ecc71"}},{scope:["keyword.other.substitution.begin","keyword.other.substitution.end"],settings:{foreground:"#5ecc71"}},{scope:["punctuation.definition.template-expression.begin","punctuation.definition.template-expression.end"],settings:{foreground:"#ff678d"}},{scope:"meta.template.expression",settings:{foreground:"#79797F"}},{scope:"punctuation.section.embedded",settings:{foreground:"#ffa359"}},{scope:"variable.interpolation",settings:{foreground:"#ffa359"}},{scope:["punctuation.section.embedded.begin","punctuation.section.embedded.end"],settings:{foreground:"#ff678d"}},{scope:"punctuation.quasi.element",settings:{foreground:"#ff678d"}},{scope:["support.type.primitive.ts","support.type.builtin.ts","support.type.primitive.tsx","support.type.builtin.tsx"],settings:{foreground:"#d568ea"}},{scope:"support.type.type.flowtype",settings:{foreground:"#9d6afb"}},{scope:"support.type.primitive",settings:{foreground:"#d568ea"}},{scope:"support.variable.magic.python",settings:{foreground:"#ff6762"}},{scope:"variable.parameter.function.language.special.self.python",settings:{foreground:"#ffca00"}},{scope:["punctuation.separator.period.python","punctuation.separator.element.python","punctuation.parenthesis.begin.python","punctuation.parenthesis.end.python"],settings:{foreground:"#79797F"}},{scope:["punctuation.definition.arguments.begin.python","punctuation.definition.arguments.end.python","punctuation.separator.arguments.python","punctuation.definition.list.begin.python","punctuation.definition.list.end.python"],settings:{foreground:"#79797F"}},{scope:"support.type.python",settings:{foreground:"#08c0ef"}},{scope:"keyword.operator.logical.python",settings:{foreground:"#ff678d"}},{scope:"meta.function-call.generic.python",settings:{foreground:"#9d6afb"}},{scope:"constant.character.format.placeholder.other.python",settings:{foreground:"#ffd452"}},{scope:"meta.function.decorator.python",settings:{foreground:"#9d6afb"}},{scope:["support.token.decorator.python","meta.function.decorator.identifier.python"],settings:{foreground:"#08c0ef"}},{scope:"storage.modifier.lifetime.rust",settings:{foreground:"#79797F"}},{scope:"support.function.std.rust",settings:{foreground:"#9d6afb"}},{scope:"entity.name.lifetime.rust",settings:{foreground:"#ffca00"}},{scope:"variable.language.rust",settings:{foreground:"#ff6762"}},{scope:"keyword.operator.misc.rust",settings:{foreground:"#79797F"}},{scope:"keyword.operator.sigil.rust",settings:{foreground:"#ff678d"}},{scope:"support.constant.core.rust",settings:{foreground:"#ffd452"}},{scope:["meta.function.c","meta.function.cpp"],settings:{foreground:"#ff6762"}},{scope:["punctuation.section.block.begin.bracket.curly.cpp","punctuation.section.block.end.bracket.curly.cpp","punctuation.terminator.statement.c","punctuation.section.block.begin.bracket.curly.c","punctuation.section.block.end.bracket.curly.c","punctuation.section.parens.begin.bracket.round.c","punctuation.section.parens.end.bracket.round.c","punctuation.section.parameters.begin.bracket.round.c","punctuation.section.parameters.end.bracket.round.c"],settings:{foreground:"#79797F"}},{scope:["keyword.operator.assignment.c","keyword.operator.comparison.c","keyword.operator.c","keyword.operator.increment.c","keyword.operator.decrement.c","keyword.operator.bitwise.shift.c"],settings:{foreground:"#ff678d"}},{scope:["keyword.operator.assignment.cpp","keyword.operator.comparison.cpp","keyword.operator.cpp","keyword.operator.increment.cpp","keyword.operator.decrement.cpp","keyword.operator.bitwise.shift.cpp"],settings:{foreground:"#ff678d"}},{scope:["punctuation.separator.c","punctuation.separator.cpp"],settings:{foreground:"#ff678d"}},{scope:["support.type.posix-reserved.c","support.type.posix-reserved.cpp"],settings:{foreground:"#08c0ef"}},{scope:["keyword.operator.sizeof.c","keyword.operator.sizeof.cpp"],settings:{foreground:"#ff678d"}},{scope:"variable.c",settings:{foreground:"#79797F"}},{scope:["storage.type.annotation.java","storage.type.object.array.java"],settings:{foreground:"#ffca00"}},{scope:"source.java",settings:{foreground:"#ff6762"}},{scope:["punctuation.section.block.begin.java","punctuation.section.block.end.java","punctuation.definition.method-parameters.begin.java","punctuation.definition.method-parameters.end.java","meta.method.identifier.java","punctuation.section.method.begin.java","punctuation.section.method.end.java","punctuation.terminator.java","punctuation.section.class.begin.java","punctuation.section.class.end.java","punctuation.section.inner-class.begin.java","punctuation.section.inner-class.end.java","meta.method-call.java","punctuation.section.class.begin.bracket.curly.java","punctuation.section.class.end.bracket.curly.java","punctuation.section.method.begin.bracket.curly.java","punctuation.section.method.end.bracket.curly.java","punctuation.separator.period.java","punctuation.bracket.angle.java","punctuation.definition.annotation.java","meta.method.body.java"],settings:{foreground:"#79797F"}},{scope:"meta.method.java",settings:{foreground:"#9d6afb"}},{scope:["storage.modifier.import.java","storage.type.java","storage.type.generic.java"],settings:{foreground:"#ffca00"}},{scope:"keyword.operator.instanceof.java",settings:{foreground:"#ff678d"}},{scope:"meta.definition.variable.name.java",settings:{foreground:"#ff6762"}},{scope:"token.variable.parameter.java",settings:{foreground:"#79797F"}},{scope:"import.storage.java",settings:{foreground:"#ffca00"}},{scope:"token.package.keyword",settings:{foreground:"#ff678d"}},{scope:"token.package",settings:{foreground:"#79797F"}},{scope:"token.storage.type.java",settings:{foreground:"#ffca00"}},{scope:"keyword.operator.assignment.go",settings:{foreground:"#ffca00"}},{scope:["keyword.operator.arithmetic.go","keyword.operator.address.go"],settings:{foreground:"#ff678d"}},{scope:"entity.name.package.go",settings:{foreground:"#ffca00"}},{scope:["support.other.namespace.use.php","support.other.namespace.use-as.php","support.other.namespace.php","entity.other.alias.php","meta.interface.php"],settings:{foreground:"#ffca00"}},{scope:"keyword.operator.error-control.php",settings:{foreground:"#ff678d"}},{scope:"keyword.operator.type.php",settings:{foreground:"#ff678d"}},{scope:["punctuation.section.array.begin.php","punctuation.section.array.end.php"],settings:{foreground:"#79797F"}},{scope:["storage.type.php","meta.other.type.phpdoc.php","keyword.other.type.php","keyword.other.array.phpdoc.php"],settings:{foreground:"#ffca00"}},{scope:["meta.function-call.php","meta.function-call.object.php","meta.function-call.static.php"],settings:{foreground:"#9d6afb"}},{scope:["punctuation.definition.parameters.begin.bracket.round.php","punctuation.definition.parameters.end.bracket.round.php","punctuation.separator.delimiter.php","punctuation.section.scope.begin.php","punctuation.section.scope.end.php","punctuation.terminator.expression.php","punctuation.definition.arguments.begin.bracket.round.php","punctuation.definition.arguments.end.bracket.round.php","punctuation.definition.storage-type.begin.bracket.round.php","punctuation.definition.storage-type.end.bracket.round.php","punctuation.definition.array.begin.bracket.round.php","punctuation.definition.array.end.bracket.round.php","punctuation.definition.begin.bracket.round.php","punctuation.definition.end.bracket.round.php","punctuation.definition.begin.bracket.curly.php","punctuation.definition.end.bracket.curly.php","punctuation.definition.section.switch-block.end.bracket.curly.php","punctuation.definition.section.switch-block.start.bracket.curly.php","punctuation.definition.section.switch-block.begin.bracket.curly.php","punctuation.definition.section.switch-block.end.bracket.curly.php"],settings:{foreground:"#79797F"}},{scope:["support.constant.ext.php","support.constant.std.php","support.constant.core.php","support.constant.parser-token.php"],settings:{foreground:"#ffd452"}},{scope:["entity.name.goto-label.php","support.other.php"],settings:{foreground:"#9d6afb"}},{scope:["keyword.operator.logical.php","keyword.operator.bitwise.php","keyword.operator.arithmetic.php"],settings:{foreground:"#08c0ef"}},{scope:"keyword.operator.regexp.php",settings:{foreground:"#ff678d"}},{scope:"keyword.operator.comparison.php",settings:{foreground:"#08c0ef"}},{scope:["keyword.operator.heredoc.php","keyword.operator.nowdoc.php"],settings:{foreground:"#ff678d"}},{scope:"variable.other.class.php",settings:{foreground:"#ff6762"}},{scope:"invalid.illegal.non-null-typehinted.php",settings:{foreground:"#f44747"}},{scope:"variable.other.generic-type.haskell",settings:{foreground:"#ff678d"}},{scope:"storage.type.haskell",settings:{foreground:"#ffd452"}},{scope:"storage.type.cs",settings:{foreground:"#ffca00"}},{scope:"entity.name.variable.local.cs",settings:{foreground:"#ff6762"}},{scope:"entity.name.label.cs",settings:{foreground:"#ffca00"}},{scope:["entity.name.scope-resolution.function.call","entity.name.scope-resolution.function.definition"],settings:{foreground:"#ffca00"}},{scope:["punctuation.definition.delayed.unison","punctuation.definition.list.begin.unison","punctuation.definition.list.end.unison","punctuation.definition.ability.begin.unison","punctuation.definition.ability.end.unison","punctuation.operator.assignment.as.unison","punctuation.separator.pipe.unison","punctuation.separator.delimiter.unison","punctuation.definition.hash.unison"],settings:{foreground:"#ff6762"}},{scope:"support.constant.edge",settings:{foreground:"#ff678d"}},{scope:"support.type.prelude.elm",settings:{foreground:"#08c0ef"}},{scope:"support.constant.elm",settings:{foreground:"#ffd452"}},{scope:"entity.global.clojure",settings:{foreground:"#ffca00"}},{scope:"meta.symbol.clojure",settings:{foreground:"#ff6762"}},{scope:"constant.keyword.clojure",settings:{foreground:"#08c0ef"}},{scope:["meta.arguments.coffee","variable.parameter.function.coffee"],settings:{foreground:"#ff6762"}},{scope:"storage.modifier.import.groovy",settings:{foreground:"#ffca00"}},{scope:"meta.method.groovy",settings:{foreground:"#9d6afb"}},{scope:"meta.definition.variable.name.groovy",settings:{foreground:"#ff6762"}},{scope:"meta.definition.class.inherited.classes.groovy",settings:{foreground:"#5ecc71"}},{scope:"support.variable.semantic.hlsl",settings:{foreground:"#ffca00"}},{scope:["support.type.texture.hlsl","support.type.sampler.hlsl","support.type.object.hlsl","support.type.object.rw.hlsl","support.type.fx.hlsl","support.type.object.hlsl"],settings:{foreground:"#ff678d"}},{scope:["text.variable","text.bracketed"],settings:{foreground:"#ff6762"}},{scope:["support.type.swift","support.type.vb.asp"],settings:{foreground:"#ffca00"}},{scope:"meta.scope.prerequisites.makefile",settings:{foreground:"#ff6762"}},{scope:"source.makefile",settings:{foreground:"#ffca00"}},{scope:"source.ini",settings:{foreground:"#5ecc71"}},{scope:"constant.language.symbol.ruby",settings:{foreground:"#08c0ef"}},{scope:["function.parameter.ruby","function.parameter.cs"],settings:{foreground:"#79797F"}},{scope:"constant.language.symbol.elixir",settings:{foreground:"#08c0ef"}},{scope:"text.html.laravel-blade source.php.embedded.line.html entity.name.tag.laravel-blade",settings:{foreground:"#ff678d"}},{scope:"text.html.laravel-blade source.php.embedded.line.html support.constant.laravel-blade",settings:{foreground:"#ff678d"}},{scope:"entity.name.function.xi",settings:{foreground:"#ffca00"}},{scope:"entity.name.class.xi",settings:{foreground:"#08c0ef"}},{scope:"constant.character.character-class.regexp.xi",settings:{foreground:"#ff6762"}},{scope:"constant.regexp.xi",settings:{foreground:"#ff678d"}},{scope:"keyword.control.xi",settings:{foreground:"#08c0ef"}},{scope:"invalid.xi",settings:{foreground:"#79797F"}},{scope:"beginning.punctuation.definition.quote.markdown.xi",settings:{foreground:"#5ecc71"}},{scope:"beginning.punctuation.definition.list.markdown.xi",settings:{foreground:"#84848A"}},{scope:"constant.character.xi",settings:{foreground:"#9d6afb"}},{scope:"accent.xi",settings:{foreground:"#9d6afb"}},{scope:"wikiword.xi",settings:{foreground:"#ffd452"}},{scope:"constant.other.color.rgb-value.xi",settings:{foreground:"#ffffff"}},{scope:"punctuation.definition.tag.xi",settings:{foreground:"#84848A"}},{scope:["support.constant.property-value.scss","support.constant.property-value.css"],settings:{foreground:"#ffd452"}},{scope:["keyword.operator.css","keyword.operator.scss","keyword.operator.less"],settings:{foreground:"#08c0ef"}},{scope:["support.constant.color.w3c-standard-color-name.css","support.constant.color.w3c-standard-color-name.scss"],settings:{foreground:"#ffd452"}},{scope:"punctuation.separator.list.comma.css",settings:{foreground:"#79797F"}},{scope:"support.type.vendored.property-name.css",settings:{foreground:"#08c0ef"}},{scope:"support.type.property-name.css",settings:{foreground:"#08c0ef"}},{scope:"support.type.property-name",settings:{foreground:"#79797F"}},{scope:"support.constant.property-value",settings:{foreground:"#79797F"}},{scope:"support.constant.font-name",settings:{foreground:"#ffd452"}},{scope:"entity.other.attribute-name.class.css",settings:{foreground:"#61d5c0",fontStyle:"normal"}},{scope:"entity.other.attribute-name.id",settings:{foreground:"#9d6afb",fontStyle:"normal"}},{scope:["entity.other.attribute-name.pseudo-element","entity.other.attribute-name.pseudo-class"],settings:{foreground:"#08c0ef"}},{scope:"meta.selector",settings:{foreground:"#ff678d"}},{scope:"selector.sass",settings:{foreground:"#ff6762"}},{scope:"rgb-value",settings:{foreground:"#08c0ef"}},{scope:"inline-color-decoration rgb-value",settings:{foreground:"#ffd452"}},{scope:"less rgb-value",settings:{foreground:"#ffd452"}},{scope:"control.elements",settings:{foreground:"#ffd452"}},{scope:"keyword.operator.less",settings:{foreground:"#ffd452"}},{scope:"entity.name.tag",settings:{foreground:"#ff6762"}},{scope:"entity.other.attribute-name",settings:{foreground:"#61d5c0",fontStyle:"normal"}},{scope:"constant.character.entity",settings:{foreground:"#ff6762"}},{scope:"meta.tag",settings:{foreground:"#79797F"}},{scope:"invalid.illegal.bad-ampersand.html",settings:{foreground:"#79797F"}},{scope:"markup.heading",settings:{foreground:"#ff6762"}},{scope:["markup.heading punctuation.definition.heading","entity.name.section"],settings:{foreground:"#9d6afb"}},{scope:"entity.name.section.markdown",settings:{foreground:"#ff6762"}},{scope:"punctuation.definition.heading.markdown",settings:{foreground:"#ff6762"}},{scope:"markup.heading.setext",settings:{foreground:"#79797F"}},{scope:["markup.heading.setext.1.markdown","markup.heading.setext.2.markdown"],settings:{foreground:"#ff6762"}},{scope:["markup.bold","todo.bold"],settings:{foreground:"#ffd452"}},{scope:"punctuation.definition.bold",settings:{foreground:"#ffca00"}},{scope:"punctuation.definition.bold.markdown",settings:{foreground:"#ffd452"}},{scope:["markup.italic","punctuation.definition.italic","todo.emphasis"],settings:{foreground:"#ff678d",fontStyle:"italic"}},{scope:"emphasis md",settings:{foreground:"#ff678d"}},{scope:"markup.italic.markdown",settings:{fontStyle:"italic"}},{scope:["markup.underline.link.markdown","markup.underline.link.image.markdown"],settings:{foreground:"#ff678d"}},{scope:["string.other.link.title.markdown","string.other.link.description.markdown"],settings:{foreground:"#9d6afb"}},{scope:"punctuation.definition.metadata.markdown",settings:{foreground:"#ff6762"}},{scope:["markup.inline.raw.markdown","markup.inline.raw.string.markdown"],settings:{foreground:"#5ecc71"}},{scope:"punctuation.definition.list.begin.markdown",settings:{foreground:"#ff6762"}},{scope:"punctuation.definition.list.markdown",settings:{foreground:"#ff6762"}},{scope:"beginning.punctuation.definition.list.markdown",settings:{foreground:"#ff6762"}},{scope:["punctuation.definition.string.begin.markdown","punctuation.definition.string.end.markdown"],settings:{foreground:"#ff6762"}},{scope:"markup.quote.markdown",settings:{foreground:"#84848A"}},{scope:"keyword.other.unit",settings:{foreground:"#ff6762"}},{scope:"markup.changed.diff",settings:{foreground:"#ffca00"}},{scope:["meta.diff.header.from-file","meta.diff.header.to-file","punctuation.definition.from-file.diff","punctuation.definition.to-file.diff"],settings:{foreground:"#9d6afb"}},{scope:"markup.inserted.diff",settings:{foreground:"#5ecc71"}},{scope:"markup.deleted.diff",settings:{foreground:"#ff6762"}},{scope:"string.regexp",settings:{foreground:"#64d1db"}},{scope:"constant.other.character-class.regexp",settings:{foreground:"#ff6762"}},{scope:"keyword.operator.quantifier.regexp",settings:{foreground:"#ffd452"}},{scope:"constant.character.escape",settings:{foreground:"#68cdf2"}},{scope:"source.json meta.structure.dictionary.json > string.quoted.json",settings:{foreground:"#ff6762"}},{scope:"source.json meta.structure.dictionary.json > string.quoted.json > punctuation.string",settings:{foreground:"#ff6762"}},{scope:["source.json meta.structure.dictionary.json > value.json > string.quoted.json","source.json meta.structure.array.json > value.json > string.quoted.json","source.json meta.structure.dictionary.json > value.json > string.quoted.json > punctuation","source.json meta.structure.array.json > value.json > string.quoted.json > punctuation"],settings:{foreground:"#5ecc71"}},{scope:["source.json meta.structure.dictionary.json > constant.language.json","source.json meta.structure.array.json > constant.language.json"],settings:{foreground:"#08c0ef"}},{scope:"support.type.property-name.json",settings:{foreground:"#ff6762"}},{scope:"support.type.property-name.json punctuation",settings:{foreground:"#ff6762"}},{scope:"punctuation.definition.block.sequence.item.yaml",settings:{foreground:"#79797F"}},{scope:"block.scope.end",settings:{foreground:"#79797F"}},{scope:"block.scope.begin",settings:{foreground:"#79797F"}},{scope:"token.info-token",settings:{foreground:"#9d6afb"}},{scope:"token.warn-token",settings:{foreground:"#ffd452"}},{scope:"token.error-token",settings:{foreground:"#f44747"}},{scope:"token.debug-token",settings:{foreground:"#ff678d"}},{scope:"invalid.illegal",settings:{foreground:"#ffffff"}},{scope:"invalid.broken",settings:{foreground:"#ffffff"}},{scope:"invalid.deprecated",settings:{foreground:"#ffffff"}},{scope:"invalid.unimplemented",settings:{foreground:"#ffffff"}}],w={comment:"#84848A",string:"#5ecc71",number:"#68cdf2",regexp:"#64d1db",keyword:"#ff678d",variable:"#ffa359",parameter:"#adadb1",property:"#ffa359",function:"#9d6afb",method:"#9d6afb",type:"#d568ea",class:"#d568ea",namespace:"#ffca00",enumMember:"#08c0ef","variable.constant":"#ffd452","variable.defaultLibrary":"#ffca00"},x={name:b,type:h,colors:q,tokenColors:v,semanticTokenColors:w};export{h as type,v as tokenColors,w as semanticTokenColors,b as name,x as default,q as colors}; diff --git a/lib/crates/fabro-spa/assets/assets/chunk-tqzz87j8.js b/lib/crates/fabro-spa/assets/assets/chunk-tqzz87j8.js deleted file mode 100644 index b56d27055..000000000 --- a/lib/crates/fabro-spa/assets/assets/chunk-tqzz87j8.js +++ /dev/null @@ -1 +0,0 @@ -import"./chunk-q07bg6gn.js";var b="pierre-light",q="light",v={"editor.background":"#ffffff","editor.foreground":"#070707",foreground:"#070707",focusBorder:"#009fff","selection.background":"#dfebff","editor.selectionBackground":"#009fff2e","editor.lineHighlightBackground":"#dfebff8c","editorCursor.foreground":"#009fff","editorLineNumber.foreground":"#84848A","editorLineNumber.activeForeground":"#6C6C71","editorIndentGuide.background":"#eeeeef","editorIndentGuide.activeBackground":"#dbdbdd","diffEditor.insertedTextBackground":"#00cab133","diffEditor.deletedTextBackground":"#ff2e3f33","sideBar.background":"#f8f8f8","sideBar.foreground":"#6C6C71","sideBar.border":"#eeeeef","sideBarTitle.foreground":"#070707","sideBarSectionHeader.background":"#f8f8f8","sideBarSectionHeader.foreground":"#6C6C71","sideBarSectionHeader.border":"#eeeeef","activityBar.background":"#f8f8f8","activityBar.foreground":"#070707","activityBar.border":"#eeeeef","activityBar.activeBorder":"#009fff","activityBarBadge.background":"#009fff","activityBarBadge.foreground":"#ffffff","titleBar.activeBackground":"#f8f8f8","titleBar.activeForeground":"#070707","titleBar.inactiveBackground":"#f8f8f8","titleBar.inactiveForeground":"#84848A","titleBar.border":"#eeeeef","list.activeSelectionBackground":"#dfebffcc","list.activeSelectionForeground":"#070707","list.inactiveSelectionBackground":"#dfebff73","list.hoverBackground":"#dfebff59","list.focusOutline":"#009fff","tab.activeBackground":"#ffffff","tab.activeForeground":"#070707","tab.activeBorderTop":"#009fff","tab.inactiveBackground":"#f8f8f8","tab.inactiveForeground":"#84848A","tab.border":"#eeeeef","editorGroupHeader.tabsBackground":"#f8f8f8","editorGroupHeader.tabsBorder":"#eeeeef","panel.background":"#f8f8f8","panel.border":"#eeeeef","panelTitle.activeBorder":"#009fff","panelTitle.activeForeground":"#070707","panelTitle.inactiveForeground":"#84848A","statusBar.background":"#f8f8f8","statusBar.foreground":"#6C6C71","statusBar.border":"#eeeeef","statusBar.noFolderBackground":"#f8f8f8","statusBar.debuggingBackground":"#ffca00","statusBar.debuggingForeground":"#ffffff","statusBarItem.remoteBackground":"#f8f8f8","statusBarItem.remoteForeground":"#6C6C71","input.background":"#f2f2f3","input.border":"#dbdbdd","input.foreground":"#070707","input.placeholderForeground":"#8E8E95","dropdown.background":"#f2f2f3","dropdown.border":"#dbdbdd","dropdown.foreground":"#070707","button.background":"#009fff","button.foreground":"#ffffff","button.hoverBackground":"#1aa9ff","textLink.foreground":"#009fff","textLink.activeForeground":"#009fff","gitDecoration.addedResourceForeground":"#00cab1","gitDecoration.conflictingResourceForeground":"#ffca00","gitDecoration.modifiedResourceForeground":"#009fff","gitDecoration.deletedResourceForeground":"#ff2e3f","gitDecoration.untrackedResourceForeground":"#00cab1","gitDecoration.ignoredResourceForeground":"#84848A","terminal.titleForeground":"#6C6C71","terminal.titleInactiveForeground":"#84848A","terminal.background":"#f8f8f8","terminal.foreground":"#6C6C71","terminal.ansiBlack":"#1F1F21","terminal.ansiRed":"#ff2e3f","terminal.ansiGreen":"#0dbe4e","terminal.ansiYellow":"#ffca00","terminal.ansiBlue":"#009fff","terminal.ansiMagenta":"#c635e4","terminal.ansiCyan":"#08c0ef","terminal.ansiWhite":"#c6c6c8","terminal.ansiBrightBlack":"#1F1F21","terminal.ansiBrightRed":"#ff2e3f","terminal.ansiBrightGreen":"#0dbe4e","terminal.ansiBrightYellow":"#ffca00","terminal.ansiBrightBlue":"#009fff","terminal.ansiBrightMagenta":"#c635e4","terminal.ansiBrightCyan":"#08c0ef","terminal.ansiBrightWhite":"#c6c6c8"},w=[{scope:["comment","punctuation.definition.comment"],settings:{foreground:"#84848A"}},{scope:"comment markup.link",settings:{foreground:"#84848A"}},{scope:["string","constant.other.symbol"],settings:{foreground:"#199f43"}},{scope:["punctuation.definition.string.begin","punctuation.definition.string.end"],settings:{foreground:"#199f43"}},{scope:["constant.numeric","constant.language.boolean"],settings:{foreground:"#1ca1c7"}},{scope:"constant",settings:{foreground:"#d5a910"}},{scope:"punctuation.definition.constant",settings:{foreground:"#d5a910"}},{scope:"constant.language",settings:{foreground:"#1ca1c7"}},{scope:"variable.other.constant",settings:{foreground:"#d5a910"}},{scope:"keyword",settings:{foreground:"#fc2b73"}},{scope:"keyword.control",settings:{foreground:"#fc2b73"}},{scope:["storage","storage.type","storage.modifier"],settings:{foreground:"#fc2b73"}},{scope:"token.storage",settings:{foreground:"#fc2b73"}},{scope:["keyword.operator.new","keyword.operator.expression.instanceof","keyword.operator.expression.typeof","keyword.operator.expression.void","keyword.operator.expression.delete","keyword.operator.expression.in","keyword.operator.expression.of","keyword.operator.expression.keyof"],settings:{foreground:"#fc2b73"}},{scope:"keyword.operator.delete",settings:{foreground:"#fc2b73"}},{scope:["variable","identifier","meta.definition.variable"],settings:{foreground:"#d47628"}},{scope:["variable.other.readwrite","meta.object-literal.key","support.variable.property","support.variable.object.process","support.variable.object.node"],settings:{foreground:"#d47628"}},{scope:"variable.language",settings:{foreground:"#d5a910"}},{scope:"variable.parameter.function",settings:{foreground:"#79797F"}},{scope:"function.parameter",settings:{foreground:"#79797F"}},{scope:"variable.parameter",settings:{foreground:"#79797F"}},{scope:"variable.parameter.function.language.python",settings:{foreground:"#d5a910"}},{scope:"variable.parameter.function.python",settings:{foreground:"#d5a910"}},{scope:["support.function","entity.name.function","meta.function-call","meta.require","support.function.any-method","variable.function"],settings:{foreground:"#7b43f8"}},{scope:"keyword.other.special-method",settings:{foreground:"#7b43f8"}},{scope:"entity.name.function",settings:{foreground:"#7b43f8"}},{scope:"support.function.console",settings:{foreground:"#7b43f8"}},{scope:["support.type","entity.name.type","entity.name.class","storage.type"],settings:{foreground:"#c635e4"}},{scope:["support.class","entity.name.type.class"],settings:{foreground:"#c635e4"}},{scope:["entity.name.class","variable.other.class.js","variable.other.class.ts"],settings:{foreground:"#c635e4"}},{scope:"entity.name.class.identifier.namespace.type",settings:{foreground:"#c635e4"}},{scope:"entity.name.type.namespace",settings:{foreground:"#d5a910"}},{scope:"entity.other.inherited-class",settings:{foreground:"#c635e4"}},{scope:"entity.name.namespace",settings:{foreground:"#d5a910"}},{scope:"keyword.operator",settings:{foreground:"#79797F"}},{scope:["keyword.operator.logical","keyword.operator.bitwise","keyword.operator.channel"],settings:{foreground:"#08c0ef"}},{scope:["keyword.operator.arithmetic","keyword.operator.comparison","keyword.operator.relational","keyword.operator.increment","keyword.operator.decrement"],settings:{foreground:"#08c0ef"}},{scope:"keyword.operator.assignment",settings:{foreground:"#08c0ef"}},{scope:"keyword.operator.assignment.compound",settings:{foreground:"#fc2b73"}},{scope:["keyword.operator.assignment.compound.js","keyword.operator.assignment.compound.ts"],settings:{foreground:"#08c0ef"}},{scope:"keyword.operator.ternary",settings:{foreground:"#fc2b73"}},{scope:"keyword.operator.optional",settings:{foreground:"#fc2b73"}},{scope:"punctuation",settings:{foreground:"#79797F"}},{scope:"punctuation.separator.delimiter",settings:{foreground:"#79797F"}},{scope:"punctuation.separator.key-value",settings:{foreground:"#79797F"}},{scope:"punctuation.terminator",settings:{foreground:"#79797F"}},{scope:"meta.brace",settings:{foreground:"#79797F"}},{scope:"meta.brace.square",settings:{foreground:"#79797F"}},{scope:"meta.brace.round",settings:{foreground:"#79797F"}},{scope:"function.brace",settings:{foreground:"#79797F"}},{scope:["punctuation.definition.parameters","punctuation.definition.typeparameters"],settings:{foreground:"#79797F"}},{scope:["punctuation.definition.block","punctuation.definition.tag"],settings:{foreground:"#79797F"}},{scope:["meta.tag.tsx","meta.tag.jsx","meta.tag.js","meta.tag.ts"],settings:{foreground:"#79797F"}},{scope:"keyword.operator.expression.import",settings:{foreground:"#7b43f8"}},{scope:"keyword.operator.module",settings:{foreground:"#fc2b73"}},{scope:"support.type.object.console",settings:{foreground:"#d47628"}},{scope:["support.module.node","support.type.object.module","entity.name.type.module"],settings:{foreground:"#d5a910"}},{scope:"support.constant.math",settings:{foreground:"#d5a910"}},{scope:"support.constant.property.math",settings:{foreground:"#d5a910"}},{scope:"support.constant.json",settings:{foreground:"#d5a910"}},{scope:"support.type.object.dom",settings:{foreground:"#08c0ef"}},{scope:["support.variable.dom","support.variable.property.dom"],settings:{foreground:"#d47628"}},{scope:"support.variable.property.process",settings:{foreground:"#d5a910"}},{scope:"meta.property.object",settings:{foreground:"#d47628"}},{scope:"variable.parameter.function.js",settings:{foreground:"#d47628"}},{scope:["keyword.other.template.begin","keyword.other.template.end"],settings:{foreground:"#199f43"}},{scope:["keyword.other.substitution.begin","keyword.other.substitution.end"],settings:{foreground:"#199f43"}},{scope:["punctuation.definition.template-expression.begin","punctuation.definition.template-expression.end"],settings:{foreground:"#fc2b73"}},{scope:"meta.template.expression",settings:{foreground:"#79797F"}},{scope:"punctuation.section.embedded",settings:{foreground:"#d47628"}},{scope:"variable.interpolation",settings:{foreground:"#d47628"}},{scope:["punctuation.section.embedded.begin","punctuation.section.embedded.end"],settings:{foreground:"#fc2b73"}},{scope:"punctuation.quasi.element",settings:{foreground:"#fc2b73"}},{scope:["support.type.primitive.ts","support.type.builtin.ts","support.type.primitive.tsx","support.type.builtin.tsx"],settings:{foreground:"#c635e4"}},{scope:"support.type.type.flowtype",settings:{foreground:"#7b43f8"}},{scope:"support.type.primitive",settings:{foreground:"#c635e4"}},{scope:"support.variable.magic.python",settings:{foreground:"#d52c36"}},{scope:"variable.parameter.function.language.special.self.python",settings:{foreground:"#d5a910"}},{scope:["punctuation.separator.period.python","punctuation.separator.element.python","punctuation.parenthesis.begin.python","punctuation.parenthesis.end.python"],settings:{foreground:"#79797F"}},{scope:["punctuation.definition.arguments.begin.python","punctuation.definition.arguments.end.python","punctuation.separator.arguments.python","punctuation.definition.list.begin.python","punctuation.definition.list.end.python"],settings:{foreground:"#79797F"}},{scope:"support.type.python",settings:{foreground:"#08c0ef"}},{scope:"keyword.operator.logical.python",settings:{foreground:"#fc2b73"}},{scope:"meta.function-call.generic.python",settings:{foreground:"#7b43f8"}},{scope:"constant.character.format.placeholder.other.python",settings:{foreground:"#d5a910"}},{scope:"meta.function.decorator.python",settings:{foreground:"#7b43f8"}},{scope:["support.token.decorator.python","meta.function.decorator.identifier.python"],settings:{foreground:"#08c0ef"}},{scope:"storage.modifier.lifetime.rust",settings:{foreground:"#79797F"}},{scope:"support.function.std.rust",settings:{foreground:"#7b43f8"}},{scope:"entity.name.lifetime.rust",settings:{foreground:"#d5a910"}},{scope:"variable.language.rust",settings:{foreground:"#d52c36"}},{scope:"keyword.operator.misc.rust",settings:{foreground:"#79797F"}},{scope:"keyword.operator.sigil.rust",settings:{foreground:"#fc2b73"}},{scope:"support.constant.core.rust",settings:{foreground:"#d5a910"}},{scope:["meta.function.c","meta.function.cpp"],settings:{foreground:"#d52c36"}},{scope:["punctuation.section.block.begin.bracket.curly.cpp","punctuation.section.block.end.bracket.curly.cpp","punctuation.terminator.statement.c","punctuation.section.block.begin.bracket.curly.c","punctuation.section.block.end.bracket.curly.c","punctuation.section.parens.begin.bracket.round.c","punctuation.section.parens.end.bracket.round.c","punctuation.section.parameters.begin.bracket.round.c","punctuation.section.parameters.end.bracket.round.c"],settings:{foreground:"#79797F"}},{scope:["keyword.operator.assignment.c","keyword.operator.comparison.c","keyword.operator.c","keyword.operator.increment.c","keyword.operator.decrement.c","keyword.operator.bitwise.shift.c"],settings:{foreground:"#fc2b73"}},{scope:["keyword.operator.assignment.cpp","keyword.operator.comparison.cpp","keyword.operator.cpp","keyword.operator.increment.cpp","keyword.operator.decrement.cpp","keyword.operator.bitwise.shift.cpp"],settings:{foreground:"#fc2b73"}},{scope:["punctuation.separator.c","punctuation.separator.cpp"],settings:{foreground:"#fc2b73"}},{scope:["support.type.posix-reserved.c","support.type.posix-reserved.cpp"],settings:{foreground:"#08c0ef"}},{scope:["keyword.operator.sizeof.c","keyword.operator.sizeof.cpp"],settings:{foreground:"#fc2b73"}},{scope:"variable.c",settings:{foreground:"#79797F"}},{scope:["storage.type.annotation.java","storage.type.object.array.java"],settings:{foreground:"#d5a910"}},{scope:"source.java",settings:{foreground:"#d52c36"}},{scope:["punctuation.section.block.begin.java","punctuation.section.block.end.java","punctuation.definition.method-parameters.begin.java","punctuation.definition.method-parameters.end.java","meta.method.identifier.java","punctuation.section.method.begin.java","punctuation.section.method.end.java","punctuation.terminator.java","punctuation.section.class.begin.java","punctuation.section.class.end.java","punctuation.section.inner-class.begin.java","punctuation.section.inner-class.end.java","meta.method-call.java","punctuation.section.class.begin.bracket.curly.java","punctuation.section.class.end.bracket.curly.java","punctuation.section.method.begin.bracket.curly.java","punctuation.section.method.end.bracket.curly.java","punctuation.separator.period.java","punctuation.bracket.angle.java","punctuation.definition.annotation.java","meta.method.body.java"],settings:{foreground:"#79797F"}},{scope:"meta.method.java",settings:{foreground:"#7b43f8"}},{scope:["storage.modifier.import.java","storage.type.java","storage.type.generic.java"],settings:{foreground:"#d5a910"}},{scope:"keyword.operator.instanceof.java",settings:{foreground:"#fc2b73"}},{scope:"meta.definition.variable.name.java",settings:{foreground:"#d52c36"}},{scope:"token.variable.parameter.java",settings:{foreground:"#79797F"}},{scope:"import.storage.java",settings:{foreground:"#d5a910"}},{scope:"token.package.keyword",settings:{foreground:"#fc2b73"}},{scope:"token.package",settings:{foreground:"#79797F"}},{scope:"token.storage.type.java",settings:{foreground:"#d5a910"}},{scope:"keyword.operator.assignment.go",settings:{foreground:"#d5a910"}},{scope:["keyword.operator.arithmetic.go","keyword.operator.address.go"],settings:{foreground:"#fc2b73"}},{scope:"entity.name.package.go",settings:{foreground:"#d5a910"}},{scope:["support.other.namespace.use.php","support.other.namespace.use-as.php","support.other.namespace.php","entity.other.alias.php","meta.interface.php"],settings:{foreground:"#d5a910"}},{scope:"keyword.operator.error-control.php",settings:{foreground:"#fc2b73"}},{scope:"keyword.operator.type.php",settings:{foreground:"#fc2b73"}},{scope:["punctuation.section.array.begin.php","punctuation.section.array.end.php"],settings:{foreground:"#79797F"}},{scope:["storage.type.php","meta.other.type.phpdoc.php","keyword.other.type.php","keyword.other.array.phpdoc.php"],settings:{foreground:"#d5a910"}},{scope:["meta.function-call.php","meta.function-call.object.php","meta.function-call.static.php"],settings:{foreground:"#7b43f8"}},{scope:["punctuation.definition.parameters.begin.bracket.round.php","punctuation.definition.parameters.end.bracket.round.php","punctuation.separator.delimiter.php","punctuation.section.scope.begin.php","punctuation.section.scope.end.php","punctuation.terminator.expression.php","punctuation.definition.arguments.begin.bracket.round.php","punctuation.definition.arguments.end.bracket.round.php","punctuation.definition.storage-type.begin.bracket.round.php","punctuation.definition.storage-type.end.bracket.round.php","punctuation.definition.array.begin.bracket.round.php","punctuation.definition.array.end.bracket.round.php","punctuation.definition.begin.bracket.round.php","punctuation.definition.end.bracket.round.php","punctuation.definition.begin.bracket.curly.php","punctuation.definition.end.bracket.curly.php","punctuation.definition.section.switch-block.end.bracket.curly.php","punctuation.definition.section.switch-block.start.bracket.curly.php","punctuation.definition.section.switch-block.begin.bracket.curly.php","punctuation.definition.section.switch-block.end.bracket.curly.php"],settings:{foreground:"#79797F"}},{scope:["support.constant.ext.php","support.constant.std.php","support.constant.core.php","support.constant.parser-token.php"],settings:{foreground:"#d5a910"}},{scope:["entity.name.goto-label.php","support.other.php"],settings:{foreground:"#7b43f8"}},{scope:["keyword.operator.logical.php","keyword.operator.bitwise.php","keyword.operator.arithmetic.php"],settings:{foreground:"#08c0ef"}},{scope:"keyword.operator.regexp.php",settings:{foreground:"#fc2b73"}},{scope:"keyword.operator.comparison.php",settings:{foreground:"#08c0ef"}},{scope:["keyword.operator.heredoc.php","keyword.operator.nowdoc.php"],settings:{foreground:"#fc2b73"}},{scope:"variable.other.class.php",settings:{foreground:"#d52c36"}},{scope:"invalid.illegal.non-null-typehinted.php",settings:{foreground:"#f44747"}},{scope:"variable.other.generic-type.haskell",settings:{foreground:"#fc2b73"}},{scope:"storage.type.haskell",settings:{foreground:"#d5a910"}},{scope:"storage.type.cs",settings:{foreground:"#d5a910"}},{scope:"entity.name.variable.local.cs",settings:{foreground:"#d52c36"}},{scope:"entity.name.label.cs",settings:{foreground:"#d5a910"}},{scope:["entity.name.scope-resolution.function.call","entity.name.scope-resolution.function.definition"],settings:{foreground:"#d5a910"}},{scope:["punctuation.definition.delayed.unison","punctuation.definition.list.begin.unison","punctuation.definition.list.end.unison","punctuation.definition.ability.begin.unison","punctuation.definition.ability.end.unison","punctuation.operator.assignment.as.unison","punctuation.separator.pipe.unison","punctuation.separator.delimiter.unison","punctuation.definition.hash.unison"],settings:{foreground:"#d52c36"}},{scope:"support.constant.edge",settings:{foreground:"#fc2b73"}},{scope:"support.type.prelude.elm",settings:{foreground:"#08c0ef"}},{scope:"support.constant.elm",settings:{foreground:"#d5a910"}},{scope:"entity.global.clojure",settings:{foreground:"#d5a910"}},{scope:"meta.symbol.clojure",settings:{foreground:"#d52c36"}},{scope:"constant.keyword.clojure",settings:{foreground:"#08c0ef"}},{scope:["meta.arguments.coffee","variable.parameter.function.coffee"],settings:{foreground:"#d52c36"}},{scope:"storage.modifier.import.groovy",settings:{foreground:"#d5a910"}},{scope:"meta.method.groovy",settings:{foreground:"#7b43f8"}},{scope:"meta.definition.variable.name.groovy",settings:{foreground:"#d52c36"}},{scope:"meta.definition.class.inherited.classes.groovy",settings:{foreground:"#199f43"}},{scope:"support.variable.semantic.hlsl",settings:{foreground:"#d5a910"}},{scope:["support.type.texture.hlsl","support.type.sampler.hlsl","support.type.object.hlsl","support.type.object.rw.hlsl","support.type.fx.hlsl","support.type.object.hlsl"],settings:{foreground:"#fc2b73"}},{scope:["text.variable","text.bracketed"],settings:{foreground:"#d52c36"}},{scope:["support.type.swift","support.type.vb.asp"],settings:{foreground:"#d5a910"}},{scope:"meta.scope.prerequisites.makefile",settings:{foreground:"#d52c36"}},{scope:"source.makefile",settings:{foreground:"#d5a910"}},{scope:"source.ini",settings:{foreground:"#199f43"}},{scope:"constant.language.symbol.ruby",settings:{foreground:"#08c0ef"}},{scope:["function.parameter.ruby","function.parameter.cs"],settings:{foreground:"#79797F"}},{scope:"constant.language.symbol.elixir",settings:{foreground:"#08c0ef"}},{scope:"text.html.laravel-blade source.php.embedded.line.html entity.name.tag.laravel-blade",settings:{foreground:"#fc2b73"}},{scope:"text.html.laravel-blade source.php.embedded.line.html support.constant.laravel-blade",settings:{foreground:"#fc2b73"}},{scope:"entity.name.function.xi",settings:{foreground:"#d5a910"}},{scope:"entity.name.class.xi",settings:{foreground:"#08c0ef"}},{scope:"constant.character.character-class.regexp.xi",settings:{foreground:"#d52c36"}},{scope:"constant.regexp.xi",settings:{foreground:"#fc2b73"}},{scope:"keyword.control.xi",settings:{foreground:"#08c0ef"}},{scope:"invalid.xi",settings:{foreground:"#79797F"}},{scope:"beginning.punctuation.definition.quote.markdown.xi",settings:{foreground:"#199f43"}},{scope:"beginning.punctuation.definition.list.markdown.xi",settings:{foreground:"#84848A"}},{scope:"constant.character.xi",settings:{foreground:"#7b43f8"}},{scope:"accent.xi",settings:{foreground:"#7b43f8"}},{scope:"wikiword.xi",settings:{foreground:"#d5a910"}},{scope:"constant.other.color.rgb-value.xi",settings:{foreground:"#ffffff"}},{scope:"punctuation.definition.tag.xi",settings:{foreground:"#84848A"}},{scope:["support.constant.property-value.scss","support.constant.property-value.css"],settings:{foreground:"#d5a910"}},{scope:["keyword.operator.css","keyword.operator.scss","keyword.operator.less"],settings:{foreground:"#08c0ef"}},{scope:["support.constant.color.w3c-standard-color-name.css","support.constant.color.w3c-standard-color-name.scss"],settings:{foreground:"#d5a910"}},{scope:"punctuation.separator.list.comma.css",settings:{foreground:"#79797F"}},{scope:"support.type.vendored.property-name.css",settings:{foreground:"#08c0ef"}},{scope:"support.type.property-name.css",settings:{foreground:"#08c0ef"}},{scope:"support.type.property-name",settings:{foreground:"#79797F"}},{scope:"support.constant.property-value",settings:{foreground:"#79797F"}},{scope:"support.constant.font-name",settings:{foreground:"#d5a910"}},{scope:"entity.other.attribute-name.class.css",settings:{foreground:"#16a994",fontStyle:"normal"}},{scope:"entity.other.attribute-name.id",settings:{foreground:"#7b43f8",fontStyle:"normal"}},{scope:["entity.other.attribute-name.pseudo-element","entity.other.attribute-name.pseudo-class"],settings:{foreground:"#08c0ef"}},{scope:"meta.selector",settings:{foreground:"#fc2b73"}},{scope:"selector.sass",settings:{foreground:"#d52c36"}},{scope:"rgb-value",settings:{foreground:"#08c0ef"}},{scope:"inline-color-decoration rgb-value",settings:{foreground:"#d5a910"}},{scope:"less rgb-value",settings:{foreground:"#d5a910"}},{scope:"control.elements",settings:{foreground:"#d5a910"}},{scope:"keyword.operator.less",settings:{foreground:"#d5a910"}},{scope:"entity.name.tag",settings:{foreground:"#d52c36"}},{scope:"entity.other.attribute-name",settings:{foreground:"#16a994",fontStyle:"normal"}},{scope:"constant.character.entity",settings:{foreground:"#d52c36"}},{scope:"meta.tag",settings:{foreground:"#79797F"}},{scope:"invalid.illegal.bad-ampersand.html",settings:{foreground:"#79797F"}},{scope:"markup.heading",settings:{foreground:"#d52c36"}},{scope:["markup.heading punctuation.definition.heading","entity.name.section"],settings:{foreground:"#7b43f8"}},{scope:"entity.name.section.markdown",settings:{foreground:"#d52c36"}},{scope:"punctuation.definition.heading.markdown",settings:{foreground:"#d52c36"}},{scope:"markup.heading.setext",settings:{foreground:"#79797F"}},{scope:["markup.heading.setext.1.markdown","markup.heading.setext.2.markdown"],settings:{foreground:"#d52c36"}},{scope:["markup.bold","todo.bold"],settings:{foreground:"#d5a910"}},{scope:"punctuation.definition.bold",settings:{foreground:"#d5a910"}},{scope:"punctuation.definition.bold.markdown",settings:{foreground:"#d5a910"}},{scope:["markup.italic","punctuation.definition.italic","todo.emphasis"],settings:{foreground:"#fc2b73",fontStyle:"italic"}},{scope:"emphasis md",settings:{foreground:"#fc2b73"}},{scope:"markup.italic.markdown",settings:{fontStyle:"italic"}},{scope:["markup.underline.link.markdown","markup.underline.link.image.markdown"],settings:{foreground:"#fc2b73"}},{scope:["string.other.link.title.markdown","string.other.link.description.markdown"],settings:{foreground:"#7b43f8"}},{scope:"punctuation.definition.metadata.markdown",settings:{foreground:"#d52c36"}},{scope:["markup.inline.raw.markdown","markup.inline.raw.string.markdown"],settings:{foreground:"#199f43"}},{scope:"punctuation.definition.list.begin.markdown",settings:{foreground:"#d52c36"}},{scope:"punctuation.definition.list.markdown",settings:{foreground:"#d52c36"}},{scope:"beginning.punctuation.definition.list.markdown",settings:{foreground:"#d52c36"}},{scope:["punctuation.definition.string.begin.markdown","punctuation.definition.string.end.markdown"],settings:{foreground:"#d52c36"}},{scope:"markup.quote.markdown",settings:{foreground:"#84848A"}},{scope:"keyword.other.unit",settings:{foreground:"#d52c36"}},{scope:"markup.changed.diff",settings:{foreground:"#d5a910"}},{scope:["meta.diff.header.from-file","meta.diff.header.to-file","punctuation.definition.from-file.diff","punctuation.definition.to-file.diff"],settings:{foreground:"#7b43f8"}},{scope:"markup.inserted.diff",settings:{foreground:"#199f43"}},{scope:"markup.deleted.diff",settings:{foreground:"#d52c36"}},{scope:"string.regexp",settings:{foreground:"#17a5af"}},{scope:"constant.other.character-class.regexp",settings:{foreground:"#d52c36"}},{scope:"keyword.operator.quantifier.regexp",settings:{foreground:"#d5a910"}},{scope:"constant.character.escape",settings:{foreground:"#1ca1c7"}},{scope:"source.json meta.structure.dictionary.json > string.quoted.json",settings:{foreground:"#d52c36"}},{scope:"source.json meta.structure.dictionary.json > string.quoted.json > punctuation.string",settings:{foreground:"#d52c36"}},{scope:["source.json meta.structure.dictionary.json > value.json > string.quoted.json","source.json meta.structure.array.json > value.json > string.quoted.json","source.json meta.structure.dictionary.json > value.json > string.quoted.json > punctuation","source.json meta.structure.array.json > value.json > string.quoted.json > punctuation"],settings:{foreground:"#199f43"}},{scope:["source.json meta.structure.dictionary.json > constant.language.json","source.json meta.structure.array.json > constant.language.json"],settings:{foreground:"#08c0ef"}},{scope:"support.type.property-name.json",settings:{foreground:"#d52c36"}},{scope:"support.type.property-name.json punctuation",settings:{foreground:"#d52c36"}},{scope:"punctuation.definition.block.sequence.item.yaml",settings:{foreground:"#79797F"}},{scope:"block.scope.end",settings:{foreground:"#79797F"}},{scope:"block.scope.begin",settings:{foreground:"#79797F"}},{scope:"token.info-token",settings:{foreground:"#7b43f8"}},{scope:"token.warn-token",settings:{foreground:"#d5a910"}},{scope:"token.error-token",settings:{foreground:"#f44747"}},{scope:"token.debug-token",settings:{foreground:"#fc2b73"}},{scope:"invalid.illegal",settings:{foreground:"#ffffff"}},{scope:"invalid.broken",settings:{foreground:"#ffffff"}},{scope:"invalid.deprecated",settings:{foreground:"#ffffff"}},{scope:"invalid.unimplemented",settings:{foreground:"#ffffff"}}],x={comment:"#84848A",string:"#199f43",number:"#1ca1c7",regexp:"#17a5af",keyword:"#fc2b73",variable:"#d47628",parameter:"#79797F",property:"#d47628",function:"#7b43f8",method:"#7b43f8",type:"#c635e4",class:"#c635e4",namespace:"#d5a910",enumMember:"#08c0ef","variable.constant":"#d5a910","variable.defaultLibrary":"#d5a910"},z={name:b,type:q,colors:v,tokenColors:w,semanticTokenColors:x};export{q as type,w as tokenColors,x as semanticTokenColors,b as name,z as default,v as colors}; diff --git a/lib/crates/fabro-spa/assets/assets/entry-70cq40fr.js b/lib/crates/fabro-spa/assets/assets/entry-70cq40fr.js deleted file mode 100644 index 652bd935a..000000000 --- a/lib/crates/fabro-spa/assets/assets/entry-70cq40fr.js +++ /dev/null @@ -1,1969 +0,0 @@ -import{X as h,Y as U8,Z as a5,_ as I}from"./chunk-q07bg6gn.js";var Z0=U8((Hc,mW)=>{(function(){function Z(y,s){Object.defineProperty(z.prototype,y,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",s[0],s[1])}})}function Y(y){if(y===null||typeof y!=="object")return null;return y=g1&&y[g1]||y["@@iterator"],typeof y==="function"?y:null}function J(y,s){y=(y=y.constructor)&&(y.displayName||y.name)||"ReactClass";var A0=y+"."+s;b0[A0]||(console.error("Can't call %s on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the %s component.",s,y),b0[A0]=!0)}function z(y,s,A0){this.props=y,this.context=s,this.refs=n5,this.updater=A0||p1}function B(){}function U(y,s,A0){this.props=y,this.context=s,this.refs=n5,this.updater=A0||p1}function W(){}function $(y){return""+y}function G(y){try{$(y);var s=!1}catch(I0){s=!0}if(s){s=console;var A0=s.error,L0=typeof Symbol==="function"&&Symbol.toStringTag&&y[Symbol.toStringTag]||y.constructor.name||"Object";return A0.call(s,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",L0),$(y)}}function w(y){if(y==null)return null;if(typeof y==="function")return y.$$typeof===j6?null:y.displayName||y.name||null;if(typeof y==="string")return y;switch(y){case N0:return"Fragment";case K0:return"Profiler";case S:return"StrictMode";case F1:return"Suspense";case O0:return"SuspenseList";case o1:return"Activity"}if(typeof y==="object")switch(typeof y.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),y.$$typeof){case e:return"Portal";case G0:return y.displayName||"Context";case M0:return(y._context.displayName||"Context")+".Consumer";case x0:var s=y.render;return y=y.displayName,y||(y=s.displayName||s.name||"",y=y!==""?"ForwardRef("+y+")":"ForwardRef"),y;case G1:return s=y.displayName||null,s!==null?s:w(y.type)||"Memo";case V1:s=y._payload,y=y._init;try{return w(y(s))}catch(A0){}}return null}function N(y){if(y===N0)return"<>";if(typeof y==="object"&&y!==null&&y.$$typeof===V1)return"<...>";try{var s=w(y);return s?"<"+s+">":"<...>"}catch(A0){return"<...>"}}function O(){var y=Q1.A;return y===null?null:y.getOwner()}function A(){return Error("react-stack-top-frame")}function _(y){if(B4.call(y,"key")){var s=Object.getOwnPropertyDescriptor(y,"key").get;if(s&&s.isReactWarning)return!1}return y.key!==void 0}function R(y,s){function A0(){U6||(U6=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",s))}A0.isReactWarning=!0,Object.defineProperty(y,"key",{get:A0,configurable:!0})}function L(){var y=w(this.type);return E4[y]||(E4[y]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),y=this.props.ref,y!==void 0?y:null}function b(y,s,A0,L0,I0,o0){var S0=A0.ref;return y={$$typeof:B0,type:y,key:s,props:A0,_owner:L0},(S0!==void 0?S0:null)!==null?Object.defineProperty(y,"ref",{enumerable:!1,get:L}):Object.defineProperty(y,"ref",{enumerable:!1,value:null}),y._store={},Object.defineProperty(y._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(y,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(y,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:I0}),Object.defineProperty(y,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:o0}),Object.freeze&&(Object.freeze(y.props),Object.freeze(y)),y}function T(y,s){return s=b(y.type,s,y.props,y._owner,y._debugStack,y._debugTask),y._store&&(s._store.validated=y._store.validated),s}function C(y){V(y)?y._store&&(y._store.validated=1):typeof y==="object"&&y!==null&&y.$$typeof===V1&&(y._payload.status==="fulfilled"?V(y._payload.value)&&y._payload.value._store&&(y._payload.value._store.validated=1):y._store&&(y._store.validated=1))}function V(y){return typeof y==="object"&&y!==null&&y.$$typeof===B0}function E(y){var s={"=":"=0",":":"=2"};return"$"+y.replace(/[=:]/g,function(A0){return s[A0]})}function x(y,s){return typeof y==="object"&&y!==null&&y.key!=null?(G(y.key),E(""+y.key)):s.toString(36)}function k(y){switch(y.status){case"fulfilled":return y.value;case"rejected":throw y.reason;default:switch(typeof y.status==="string"?y.then(W,W):(y.status="pending",y.then(function(s){y.status==="pending"&&(y.status="fulfilled",y.value=s)},function(s){y.status==="pending"&&(y.status="rejected",y.reason=s)})),y.status){case"fulfilled":return y.value;case"rejected":throw y.reason}}throw y}function f(y,s,A0,L0,I0){var o0=typeof y;if(o0==="undefined"||o0==="boolean")y=null;var S0=!1;if(y===null)S0=!0;else switch(o0){case"bigint":case"string":case"number":S0=!0;break;case"object":switch(y.$$typeof){case B0:case e:S0=!0;break;case V1:return S0=y._init,f(S0(y._payload),s,A0,L0,I0)}}if(S0){S0=y,I0=I0(S0);var n0=L0===""?"."+x(S0,0):L0;return K1(I0)?(A0="",n0!=null&&(A0=n0.replace(s2,"$&/")+"/"),f(I0,s,A0,"",function(M5){return M5})):I0!=null&&(V(I0)&&(I0.key!=null&&(S0&&S0.key===I0.key||G(I0.key)),A0=T(I0,A0+(I0.key==null||S0&&S0.key===I0.key?"":(""+I0.key).replace(s2,"$&/")+"/")+n0),L0!==""&&S0!=null&&V(S0)&&S0.key==null&&S0._store&&!S0._store.validated&&(A0._store.validated=2),I0=A0),s.push(I0)),1}if(S0=0,n0=L0===""?".":L0+":",K1(y))for(var y0=0;y0 import('./MyComponent')) - -Did you accidentally put curly braces around the import?`,s),"default"in s||console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s - -Your code should look like: - const MyComponent = lazy(() => import('./MyComponent'))`,s),s.default;throw y._result}function j(){var y=Q1.H;return y===null&&console.error(`Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.`),y}function o(){Q1.asyncTransitions--}function $0(y){if(U4===null)try{var s=("require"+Math.random()).slice(0,7);U4=(mW&&mW[s]).call(mW,"timers").setImmediate}catch(A0){U4=function(L0){K2===!1&&(K2=!0,typeof MessageChannel>"u"&&console.error("This browser does not have a MessageChannel implementation, so enqueuing tasks via await act(async () => ...) will fail. Please file an issue at https://github.com/facebook/react/issues if you encounter this warning."));var I0=new MessageChannel;I0.port1.onmessage=L0,I0.port2.postMessage(void 0)}}return U4(y)}function H0(y){return 1 ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);"))}),{then:function(y0,M5){I0=!0,S0.then(function(X5){if(t(s,A0),A0===0){try{X0(L0),$0(function(){return c(X5,y0,M5)})}catch(e5){Q1.thrownErrors.push(e5)}if(0 ...)"))}),Q1.actQueue=null),0Q1.recentlyCreatedOwnerStacks++;return b(y,I0,L0,O(),y0?Error("react-stack-top-frame"):x2,y0?E1(N(y)):K6)},Hc.createRef=function(){var y={current:null};return Object.seal(y),y},Hc.forwardRef=function(y){y!=null&&y.$$typeof===G1?console.error("forwardRef requires a render function but received a `memo` component. Instead of forwardRef(memo(...)), use memo(forwardRef(...))."):typeof y!=="function"?console.error("forwardRef requires a render function but was given %s.",y===null?"null":typeof y):y.length!==0&&y.length!==2&&console.error("forwardRef render functions accept exactly two parameters: props and ref. %s",y.length===1?"Did you forget to use the ref parameter?":"Any additional parameter will be undefined."),y!=null&&y.defaultProps!=null&&console.error("forwardRef render functions do not support defaultProps. Did you accidentally pass a React component?");var s={$$typeof:x0,render:y},A0;return Object.defineProperty(s,"displayName",{enumerable:!1,configurable:!0,get:function(){return A0},set:function(L0){A0=L0,y.name||y.displayName||(Object.defineProperty(y,"name",{value:L0}),y.displayName=L0)}}),s},Hc.isValidElement=V,Hc.lazy=function(y){y={_status:-1,_result:y};var s={$$typeof:V1,_payload:y,_init:Y0},A0={name:"lazy",start:-1,end:-1,value:null,owner:null,debugStack:Error("react-stack-top-frame"),debugTask:console.createTask?console.createTask("lazy()"):null};return y._ioInfo=A0,s._debugInfo=[{awaited:A0}],s},Hc.memo=function(y,s){y==null&&console.error("memo: The first argument must be a component. Instead received: %s",y===null?"null":typeof y),s={$$typeof:G1,type:y,compare:s===void 0?null:s};var A0;return Object.defineProperty(s,"displayName",{enumerable:!1,configurable:!0,get:function(){return A0},set:function(L0){A0=L0,y.name||y.displayName||(Object.defineProperty(y,"name",{value:L0}),y.displayName=L0)}}),s},Hc.startTransition=function(y){var s=Q1.T,A0={};A0._updatedFibers=new Set,Q1.T=A0;try{var L0=y(),I0=Q1.S;I0!==null&&I0(A0,L0),typeof L0==="object"&&L0!==null&&typeof L0.then==="function"&&(Q1.asyncTransitions++,L0.then(o,o),L0.then(W,V5))}catch(o0){V5(o0)}finally{s===null&&A0._updatedFibers&&(y=A0._updatedFibers.size,A0._updatedFibers.clear(),10{(function(){function Z(){if(E=!1,p){var c=Mc.unstable_now();o=c;var X0=!0;try{Z:{C=!1,V&&(V=!1,k(Y0),Y0=-1),T=!0;var B0=b;try{Y:{U(c);for(L=J(A);L!==null&&!(L.expirationTime>c&&$());){var e=L.callback;if(typeof e==="function"){L.callback=null,b=L.priorityLevel;var N0=e(L.expirationTime<=c);if(c=Mc.unstable_now(),typeof N0==="function"){L.callback=N0,U(c),X0=!0;break Y}L===J(A)&&z(A),U(c)}else z(A);L=J(A)}if(L!==null)X0=!0;else{var S=J(_);S!==null&&G(W,S.startTime-c),X0=!1}}break Z}finally{L=null,b=B0,T=!1}X0=void 0}}finally{X0?$0():p=!1}}}function Y(c,X0){var B0=c.length;c.push(X0);Z:for(;0>>1,N0=c[e];if(0>>1;eB(M0,B0))G0B(x0,M0)?(c[e]=x0,c[G0]=B0,e=G0):(c[e]=M0,c[K0]=B0,e=K0);else if(G0B(x0,B0))c[e]=x0,c[G0]=B0,e=G0;else break Z}}return X0}function B(c,X0){var B0=c.sortIndex-X0.sortIndex;return B0!==0?B0:c.id-X0.id}function U(c){for(var X0=J(_);X0!==null;){if(X0.callback===null)z(_);else if(X0.startTime<=c)z(_),X0.sortIndex=X0.expirationTime,Y(A,X0);else break;X0=J(_)}}function W(c){if(V=!1,U(c),!C)if(J(A)!==null)C=!0,p||(p=!0,$0());else{var X0=J(_);X0!==null&&G(W,X0.startTime-c)}}function $(){return E?!0:Mc.unstable_now()-oc||125e?(c.sortIndex=B0,Y(_,c),J(A)===null&&c===J(_)&&(V?(k(Y0),Y0=-1):V=!0,G(W,B0-e))):(c.sortIndex=N0,Y(A,c),C||T||(C=!0,p||(p=!0,$0()))),c},Mc.unstable_shouldYield=$,Mc.unstable_wrapCallback=function(c){var X0=b;return function(){var B0=b;b=X0;try{return c.apply(this,arguments)}finally{b=B0}}},typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop==="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())})()});var KD=U8((wc)=>{var aO=h(Z0());(function(){function Z(){}function Y(N){return""+N}function J(N,O,A){var _=3` tag.%s',A),typeof N==="string"&&typeof O==="object"&&O!==null&&typeof O.as==="string"){A=O.as;var _=z(A,O.crossOrigin);$.d.L(N,A,{crossOrigin:_,integrity:typeof O.integrity==="string"?O.integrity:void 0,nonce:typeof O.nonce==="string"?O.nonce:void 0,type:typeof O.type==="string"?O.type:void 0,fetchPriority:typeof O.fetchPriority==="string"?O.fetchPriority:void 0,referrerPolicy:typeof O.referrerPolicy==="string"?O.referrerPolicy:void 0,imageSrcSet:typeof O.imageSrcSet==="string"?O.imageSrcSet:void 0,imageSizes:typeof O.imageSizes==="string"?O.imageSizes:void 0,media:typeof O.media==="string"?O.media:void 0})}},wc.preloadModule=function(N,O){var A="";typeof N==="string"&&N||(A+=" The `href` argument encountered was "+B(N)+"."),O!==void 0&&typeof O!=="object"?A+=" The `options` argument encountered was "+B(O)+".":O&&("as"in O)&&typeof O.as!=="string"&&(A+=" The `as` option encountered was "+B(O.as)+"."),A&&console.error('ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `` tag.%s',A),typeof N==="string"&&(O?(A=z(O.as,O.crossOrigin),$.d.m(N,{as:typeof O.as==="string"&&O.as!=="script"?O.as:void 0,crossOrigin:A,integrity:typeof O.integrity==="string"?O.integrity:void 0})):$.d.m(N))},wc.requestFormReset=function(N){$.d.r(N)},wc.unstable_batchedUpdates=function(N,O){return N(O)},wc.useFormState=function(N,O,A){return W().useFormState(N,O,A)},wc.useFormStatus=function(){return W().useHostTransitionStatus()},wc.version="19.2.4",typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop==="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())})()});var H3=U8((R30,WD)=>{var Nc=h(KD());WD.exports=Nc});var $D=U8((Oc)=>{var l1=h(UD()),XJ=h(Z0()),iO=h(H3());(function(){function Z(Q,X){for(Q=Q.memoizedState;Q!==null&&0=X.length)return K;var H=X[q],M=V2(Q)?Q.slice():T1({},Q);return M[H]=Y(Q[H],X,q+1,K),M}function J(Q,X,q){if(X.length!==q.length)console.warn("copyWithRename() expects paths of the same length");else{for(var K=0;Kl3?console.error("Unexpected pop."):(X!==CN[l3]&&console.error("Unexpected Fiber popped."),Q.current=VN[l3],VN[l3]=null,CN[l3]=null,l3--)}function H0(Q,X,q){l3++,VN[l3]=Q.current,CN[l3]=q,Q.current=X}function t(Q){return Q===null&&console.error("Expected host context to exist. This error is likely caused by a bug in React. Please file an issue."),Q}function c(Q,X){H0(Y9,X,Q),H0(hz,Q,Q),H0(Z9,null,Q);var q=X.nodeType;switch(q){case 9:case 11:q=q===9?"#document":"#fragment",X=(X=X.documentElement)?(X=X.namespaceURI)?lC(X):z8:z8;break;default:if(q=X.tagName,X=X.namespaceURI)X=lC(X),X=rC(X,q);else switch(q){case"svg":X=QJ;break;case"math":X=xW;break;default:X=z8}}q=q.toLowerCase(),q=gR(null,q),q={context:X,ancestorInfo:q},$0(Z9,Q),H0(Z9,q,Q)}function X0(Q){$0(Z9,Q),$0(hz,Q),$0(Y9,Q)}function B0(){return t(Z9.current)}function e(Q){Q.memoizedState!==null&&H0(kK,Q,Q);var X=t(Z9.current),q=Q.type,K=rC(X.context,q);q=gR(X.ancestorInfo,q),K={context:K,ancestorInfo:q},X!==K&&(H0(hz,Q,Q),H0(Z9,K,Q))}function N0(Q){hz.current===Q&&($0(Z9,Q),$0(hz,Q)),kK.current===Q&&($0(kK,Q),Eq._currentValue=nZ)}function S(){}function K0(){if(mz===0){Rv=console.log,Lv=console.info,Vv=console.warn,Cv=console.error,vv=console.group,Tv=console.groupCollapsed,bv=console.groupEnd;var Q={configurable:!0,enumerable:!0,value:S,writable:!0};Object.defineProperties(console,{info:Q,log:Q,warn:Q,error:Q,group:Q,groupCollapsed:Q,groupEnd:Q})}mz++}function M0(){if(mz--,mz===0){var Q={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:T1({},Q,{value:Rv}),info:T1({},Q,{value:Lv}),warn:T1({},Q,{value:Vv}),error:T1({},Q,{value:Cv}),group:T1({},Q,{value:vv}),groupCollapsed:T1({},Q,{value:Tv}),groupEnd:T1({},Q,{value:bv})})}0>mz&&console.error("disabledDepth fell below zero. This is a bug in React. Please file an issue.")}function G0(Q){var X=Error.prepareStackTrace;if(Error.prepareStackTrace=void 0,Q=Q.stack,Error.prepareStackTrace=X,Q.startsWith(`Error: react-stack-top-frame -`)&&(Q=Q.slice(29)),X=Q.indexOf(` -`),X!==-1&&(Q=Q.slice(X+1)),X=Q.indexOf("react_stack_bottom_frame"),X!==-1&&(X=Q.lastIndexOf(` -`,X)),X!==-1)Q=Q.slice(0,X);else return"";return Q}function x0(Q){if(vN===void 0)try{throw Error()}catch(q){var X=q.stack.trim().match(/\n( *(at )?)/);vN=X&&X[1]||"",Dv=-1)":-1F||D[M]!==r[F]){var a=` -`+D[M].replace(" at new "," at ");return Q.displayName&&a.includes("")&&(a=a.replace("",Q.displayName)),typeof Q==="function"&&bN.set(Q,a),a}while(1<=M&&0<=F);break}}}finally{TN=!1,U0.H=K,M0(),Error.prepareStackTrace=q}return D=(D=Q?Q.displayName||Q.name:"")?x0(D):"",typeof Q==="function"&&bN.set(Q,D),D}function O0(Q,X){switch(Q.tag){case 26:case 27:case 5:return x0(Q.type);case 16:return x0("Lazy");case 13:return Q.child!==X&&X!==null?x0("Suspense Fallback"):x0("Suspense");case 19:return x0("SuspenseList");case 0:case 15:return F1(Q.type,!1);case 11:return F1(Q.type.render,!1);case 1:return F1(Q.type,!0);case 31:return x0("Activity");default:return""}}function G1(Q){try{var X="",q=null;do{X+=O0(Q,q);var K=Q._debugInfo;if(K)for(var H=K.length-1;0<=H;H--){var M=K[H];if(typeof M.name==="string"){var F=X;Z:{var{name:P,env:v,debugLocation:D}=M;if(D!=null){var r=G0(D),a=r.lastIndexOf(` -`),m=a===-1?r:r.slice(a+1);if(m.indexOf(P)!==-1){var Q0=` -`+m;break Z}}Q0=x0(P+(v?" ["+v+"]":""))}X=F+Q0}}q=Q,Q=Q.return}while(Q);return X}catch(V0){return` -Error generating stack: `+V0.message+` -`+V0.stack}}function V1(Q){return(Q=Q?Q.displayName||Q.name:"")?x0(Q):""}function o1(){if(O4===null)return null;var Q=O4._debugOwner;return Q!=null?Y0(Q):null}function g1(){if(O4===null)return"";var Q=O4;try{var X="";switch(Q.tag===6&&(Q=Q.return),Q.tag){case 26:case 27:case 5:X+=x0(Q.type);break;case 13:X+=x0("Suspense");break;case 19:X+=x0("SuspenseList");break;case 31:X+=x0("Activity");break;case 30:case 0:case 15:case 1:Q._debugOwner||X!==""||(X+=V1(Q.type));break;case 11:Q._debugOwner||X!==""||(X+=V1(Q.type.render))}for(;Q;)if(typeof Q.tag==="number"){var q=Q;Q=q._debugOwner;var K=q._debugStack;if(Q&&K){var H=G0(K);H!==""&&(X+=` -`+H)}}else if(Q.debugStack!=null){var M=Q.debugStack;(Q=Q.owner)&&M&&(X+=` -`+G0(M))}else break;var F=X}catch(P){F=` -Error generating stack: `+P.message+` -`+P.stack}return F}function b0(Q,X,q,K,H,M,F){var P=O4;p1(Q);try{return Q!==null&&Q._debugTask?Q._debugTask.run(X.bind(null,q,K,H,M,F)):X(q,K,H,M,F)}finally{p1(P)}throw Error("runWithFiberInDEV should never be called in production. This is a bug in React.")}function p1(Q){U0.getCurrentStack=Q===null?null:g1,J3=!1,O4=Q}function t5(Q){return typeof Symbol==="function"&&Symbol.toStringTag&&Q[Symbol.toStringTag]||Q.constructor.name||"Object"}function n5(Q){try{return H5(Q),!1}catch(X){return!0}}function H5(Q){return""+Q}function K1(Q,X){if(n5(Q))return console.error("The provided `%s` attribute is an unsupported type %s. This value must be coerced to a string before using it here.",X,t5(Q)),H5(Q)}function j6(Q,X){if(n5(Q))return console.error("The provided `%s` CSS property is an unsupported type %s. This value must be coerced to a string before using it here.",X,t5(Q)),H5(Q)}function Q1(Q){if(n5(Q))return console.error("Form field values (value, checked, defaultValue, or defaultChecked props) must be strings, not %s. This value must be coerced to a string before using it here.",t5(Q)),H5(Q)}function B4(Q){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u")return!1;var X=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(X.isDisabled)return!0;if(!X.supportsFiber)return console.error("The installed version of React DevTools is too old and will not work with the current version of React. Please update React DevTools. https://react.dev/link/react-devtools"),!0;try{VQ=X.inject(Q),M7=X}catch(q){console.error("React instrumentation encountered an error: %o.",q)}return X.checkDCE?!0:!1}function E1(Q){if(typeof ym==="function"&&Em(Q),M7&&typeof M7.setStrictMode==="function")try{M7.setStrictMode(VQ,Q)}catch(X){X3||(X3=!0,console.error("React instrumentation encountered an error: %o",X))}}function U6(Q){return Q>>>=0,Q===0?32:31-(fm(Q)/Im|0)|0}function o2(Q){var X=Q&42;if(X!==0)return X;switch(Q&-Q){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return Q&261888;case 262144:case 524288:case 1048576:case 2097152:return Q&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return Q&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return console.error("Should have found matching lanes. This is a bug in React."),Q}}function E4(Q,X,q){var K=Q.pendingLanes;if(K===0)return 0;var H=0,M=Q.suspendedLanes,F=Q.pingedLanes;Q=Q.warmLanes;var P=K&134217727;return P!==0?(K=P&~M,K!==0?H=o2(K):(F&=P,F!==0?H=o2(F):q||(q=P&~Q,q!==0&&(H=o2(q))))):(P=K&~M,P!==0?H=o2(P):F!==0?H=o2(F):q||(q=K&~Q,q!==0&&(H=o2(q)))),H===0?0:X!==0&&X!==H&&(X&M)===0&&(M=H&-H,q=X&-X,M>=q||M===32&&(q&4194048)!==0)?X:H}function x2(Q,X){return(Q.pendingLanes&~(Q.suspendedLanes&~Q.pingedLanes)&X)===0}function K6(Q,X){switch(Q){case 1:case 2:case 4:case 8:case 64:return X+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return X+5000;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return console.error("Should have found matching lanes. This is a bug in React."),-1}}function W6(){var Q=hK;return hK<<=1,(hK&62914560)===0&&(hK=4194304),Q}function s2(Q){for(var X=[],q=0;31>q;q++)X.push(Q);return X}function V5(Q,X){Q.pendingLanes|=X,X!==268435456&&(Q.suspendedLanes=0,Q.pingedLanes=0,Q.warmLanes=0)}function K2(Q,X,q,K,H,M){var F=Q.pendingLanes;Q.pendingLanes=q,Q.suspendedLanes=0,Q.pingedLanes=0,Q.warmLanes=0,Q.expiredLanes&=q,Q.entangledLanes&=q,Q.errorRecoveryDisabledLanes&=q,Q.shellSuspendCounter=0;var{entanglements:P,expirationTimes:v,hiddenUpdates:D}=Q;for(q=F&~q;0"u")return null;try{return Q.activeElement||Q.body}catch(X){return Q.body}}function f0(Q){return Q.replace(um,function(X){return"\\"+X.charCodeAt(0).toString(16)+" "})}function d0(Q,X){X.checked===void 0||X.defaultChecked===void 0||Sv||(console.error("%s contains an input of type %s with both checked and defaultChecked props. Input elements must be either controlled or uncontrolled (specify either the checked prop, or the defaultChecked prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props. More info: https://react.dev/link/controlled-components",o1()||"A component",X.type),Sv=!0),X.value===void 0||X.defaultValue===void 0||xv||(console.error("%s contains an input of type %s with both value and defaultValue props. Input elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props. More info: https://react.dev/link/controlled-components",o1()||"A component",X.type),xv=!0)}function p0(Q,X,q,K,H,M,F,P){if(Q.name="",F!=null&&typeof F!=="function"&&typeof F!=="symbol"&&typeof F!=="boolean"?(K1(F,"type"),Q.type=F):Q.removeAttribute("type"),X!=null)if(F==="number"){if(X===0&&Q.value===""||Q.value!=X)Q.value=""+i(X)}else Q.value!==""+i(X)&&(Q.value=""+i(X));else F!=="submit"&&F!=="reset"||Q.removeAttribute("value");X!=null?c0(Q,F,i(X)):q!=null?c0(Q,F,i(q)):K!=null&&Q.removeAttribute("value"),H==null&&M!=null&&(Q.defaultChecked=!!M),H!=null&&(Q.checked=H&&typeof H!=="function"&&typeof H!=="symbol"),P!=null&&typeof P!=="function"&&typeof P!=="symbol"&&typeof P!=="boolean"?(K1(P,"name"),Q.name=""+i(P)):Q.removeAttribute("name")}function s0(Q,X,q,K,H,M,F,P){if(M!=null&&typeof M!=="function"&&typeof M!=="symbol"&&typeof M!=="boolean"&&(K1(M,"type"),Q.type=M),X!=null||q!=null){if(!(M!=="submit"&&M!=="reset"||X!==void 0&&X!==null)){P0(Q);return}q=q!=null?""+i(q):"",X=X!=null?""+i(X):q,P||X===Q.value||(Q.value=X),Q.defaultValue=X}K=K!=null?K:H,K=typeof K!=="function"&&typeof K!=="symbol"&&!!K,Q.checked=P?Q.checked:!!K,Q.defaultChecked=!!K,F!=null&&typeof F!=="function"&&typeof F!=="symbol"&&typeof F!=="boolean"&&(K1(F,"name"),Q.name=F),P0(Q)}function c0(Q,X,q){X==="number"&&E0(Q.ownerDocument)===Q||Q.defaultValue===""+q||(Q.defaultValue=""+q)}function h1(Q,X){X.value==null&&(typeof X.children==="object"&&X.children!==null?XJ.Children.forEach(X.children,function(q){q==null||typeof q==="string"||typeof q==="number"||typeof q==="bigint"||kv||(kv=!0,console.error("Cannot infer the option value of complex children. Pass a `value` prop or use a plain string as children to