Merge remote-tracking branch 'origin/main'

This commit is contained in:
Bryan Helmkamp 2026-04-27 07:01:53 -07:00
commit d2d962f201
No known key found for this signature in database
403 changed files with 598 additions and 5390 deletions

View file

@ -13,25 +13,8 @@ env:
SEGMENT_WRITE_KEY: ${{ secrets.SEGMENT_WRITE_KEY }}
jobs:
verify-spa:
name: Verify SPA assets
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
no-cache: true
- run: bun install --frozen-lockfile
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
- run: cargo dev spa check
compile:
name: Compile (${{ matrix.target }})
needs: verify-spa
runs-on: ${{ matrix.runner }}
permissions:
contents: read
@ -60,6 +43,13 @@ jobs:
with:
persist-credentials: false
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
no-cache: true
- name: Install bun deps
run: bun install --frozen-lockfile
- name: Install Linux build tools
if: runner.os == 'Linux'
run: |
@ -89,6 +79,9 @@ jobs:
- uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest
- name: Refresh embedded SPA
run: cargo dev spa refresh
- name: Test (x86_64-musl)
# nextest still shells through cargo test for this target, so
# build.rs C code needs an explicit musl compiler/linker.

View file

@ -72,6 +72,5 @@ jobs:
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
- run: bun install --frozen-lockfile
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
- run: cargo dev spa check
- run: cargo build -p fabro-cli --release
- run: cargo dev build -- -p fabro-cli --release
- run: wc -c < target/release/fabro

2
.gitignore vendored
View file

@ -3,6 +3,8 @@ target
.entire
node_modules
apps/fabro-web/dist/
lib/crates/fabro-spa/assets/*
!lib/crates/fabro-spa/assets/.gitkeep
tmp
evals/swe-bench/repos/
evals/swe-bench/results/

View file

@ -22,11 +22,10 @@ macOS note: if `cargo nextest run` fails with `Too many open files (os error 24)
- `cd apps/fabro-web && bun test` — run tests
- `cd apps/fabro-web && bun run typecheck` — type check
- `cd apps/fabro-web && bun run build` — production build (writes to `apps/fabro-web/dist/` only; does NOT update the bundled SPA that ships in the Rust binary)
- `cargo dev spa refresh` — **run this before committing any TypeScript change in `apps/fabro-web/` or `lib/packages/fabro-api-client/`**. It runs the production build, verifies SPA asset budgets, and then copies `dist/` into `lib/crates/fabro-spa/assets/` (which is tracked in git). CI's TypeScript `Build` job runs `cargo dev spa check` — if the committed bundle drifts from source or exceeds budgets, the check fails. `bun run build` on its own is not enough.
- `cargo dev build [-- <cargo args>]` — refreshes the embedded SPA assets from the production build, verifies SPA asset budgets, and then runs `cargo build` with forwarded args. The embedded assets are gitignored except for `.gitkeep`; use this when building a Rust binary that should include a populated SPA bundle. `bun run dev` for local development is unchanged because debug builds prefer `apps/fabro-web/dist/` on disk via the server fallback.
### Docker image
- `cargo dev docker-build` — builds the local Docker image from the current tree using the release pipeline's cargo-zigbuild approach. Honors `--arch amd64|arm64`, `--tag <name>` (default `fabro-sh/fabro`), `--compile-only` (stages `tmp/docker-context/<arch>/fabro` without `docker build`), and `--dry-run` (prints the Docker commands without running them). Prefer this over writing a throwaway Dockerfile; the release pipeline, `Dockerfile`, and this command share the same binary layout.
- Refresh the embedded SPA before rebuilding the image after any `apps/fabro-web` change: `cargo dev spa refresh` runs the bun build, verifies budgets, and copies `dist/` into `lib/crates/fabro-spa/assets/`. Skipping this step produces a Docker image whose Rust binary embeds a stale SPA bundle.
### Docker sandbox provider
- Docker is the default runtime sandbox provider from `defaults.toml`. The Fabro process must have a working Docker client environment (`DOCKER_HOST`, socket access, Docker Desktop behavior, TLS settings, groups/permissions, and any remote daemon policy are operator responsibilities).

View file

@ -2,7 +2,7 @@ import { formatElapsedSecs, formatDurationSecs } from "../lib/format";
import type {
RunListItem,
RunStatus as ApiRunStatus,
StoreRunSummary,
RunSummary,
} from "@qltysh/fabro-api-client";
export type CiStatus = "passing" | "failing" | "pending";
@ -84,9 +84,9 @@ export function mapRunListItem(item: RunListItem): RunItem {
};
}
export type RunSummaryResponse = StoreRunSummary;
export type { RunSummary };
export function mapRunSummaryToRunItem(summary: RunSummaryResponse): RunItem {
export function mapRunSummaryToRunItem(summary: RunSummary): RunItem {
const lifecycleStatus = runStatusKind(summary.status);
return {
id: summary.run_id,

View file

@ -8,6 +8,7 @@ import type {
PaginatedStageTurnList,
RunBilling,
ServerSettings,
RunSummary,
} from "@qltysh/fabro-api-client";
import type { PaginatedWorkflowListResponse, WorkflowDetailResponse } from "./workflow-api";
@ -20,7 +21,6 @@ import {
type PaginatedEnvelope,
} from "./api-client";
import { queryKeys } from "./query-keys";
import type { RunSummaryResponse } from "../data/runs";
const immutableOptions: SWRConfiguration = {
revalidateIfStale: false,
@ -63,7 +63,7 @@ export function useBoardsRuns() {
}
export function useRun(id: string | undefined) {
return useSWR<RunSummaryResponse | null>(
return useSWR<RunSummary | null>(
id ? queryKeys.runs.detail(id) : null,
apiNullableFetcher,
);

View file

@ -10,7 +10,7 @@ import {
isRunStatus,
mapRunSummaryToRunItem,
runStatusDisplay,
type RunSummaryResponse,
type RunSummary,
} from "../data/runs";
import { useDemoMode } from "../lib/demo-mode";
import {
@ -78,7 +78,7 @@ export function lifecycleActionVisibility(status: string | null | undefined) {
};
}
function buildRunDetailRun(summary: RunSummaryResponse): RunDetailRun {
function buildRunDetailRun(summary: RunSummary): RunDetailRun {
const item = mapRunSummaryToRunItem(summary);
const rawStatus = summary.status;
const statusKind = rawStatus.kind;

View file

@ -536,7 +536,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/StoreRunSummary"
$ref: "#/components/schemas/RunSummary"
"400":
description: Selector is invalid or ambiguous
content:
@ -617,7 +617,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/StoreRunSummary"
$ref: "#/components/schemas/RunSummary"
"404":
description: Run not found
content:
@ -2858,7 +2858,7 @@ components:
data:
type: array
items:
$ref: "#/components/schemas/StoreRunSummary"
$ref: "#/components/schemas/RunSummary"
meta:
$ref: "#/components/schemas/PaginationMeta"
@ -4374,7 +4374,7 @@ components:
additionalProperties:
$ref: "#/components/schemas/NodeState"
StoreRunSummary:
RunSummary:
description: Durable run summary derived from the backing store.
type: object
required:

View file

@ -171,9 +171,10 @@ fn main() {
"fabro_types::status::RunControlAction",
&[],
),
("RunSummary", "fabro_types::RunSummary", &[]),
(
"RunStatusRecord",
"fabro_types::status::RunStatusRecord",
"RepositoryReference",
"fabro_types::RepositoryReference",
&[],
),
("WorkflowSettings", "fabro_types::WorkflowSettings", &[]),

View file

@ -27,7 +27,7 @@ pub mod types {
pub use fabro_types::status::{
BlockedReason, FailureReason, RunControlAction, RunStatus, SuccessReason, TerminalStatus,
};
pub use fabro_types::{ServerSettings, WorkflowSettings};
pub use fabro_types::{RepositoryReference, RunSummary, ServerSettings, WorkflowSettings};
pub use crate::generated::types::*;
}

View file

@ -0,0 +1,122 @@
use std::any::{TypeId, type_name};
use std::collections::HashMap;
use chrono::{TimeZone, Utc};
use fabro_api::types::{
RepositoryReference as ApiRepositoryReference, RunSummary as ApiRunSummary,
};
use fabro_types::status::{RunStatus, SuccessReason, TerminalStatus};
use fabro_types::{RepositoryReference, RunId, RunSummary};
use serde_json::json;
#[test]
fn run_summary_reuses_domain_types() {
assert_same_type::<ApiRunSummary, RunSummary>();
assert_same_type::<ApiRepositoryReference, RepositoryReference>();
}
#[test]
fn run_summary_json_matches_openapi_shape() {
let created_at = Utc.with_ymd_and_hms(2026, 4, 20, 12, 0, 0).unwrap();
let run_id = RunId::with_timestamp(created_at, 7);
let superseded_by = RunId::with_timestamp(created_at, 8);
let summary = RunSummary::new(
run_id,
Some("workflow".to_string()),
Some("workflow".to_string()),
String::new(),
HashMap::from([("team".to_string(), "core".to_string())]),
Some("/tmp/fabro".to_string()),
Some(created_at),
RunStatus::Archived {
prior: TerminalStatus::Succeeded {
reason: SuccessReason::PartialSuccess,
},
},
None,
Some(42_000),
Some(123),
Some(superseded_by),
);
assert_eq!(
serde_json::to_value(&summary).unwrap(),
json!({
"run_id": run_id.to_string(),
"workflow_name": "workflow",
"workflow_slug": "workflow",
"goal": "",
"title": "",
"labels": {
"team": "core"
},
"host_repo_path": "/tmp/fabro",
"repository": {
"name": "fabro"
},
"start_time": "2026-04-20T12:00:00Z",
"created_at": "2026-04-20T12:00:00Z",
"status": {
"kind": "archived",
"prior": {
"kind": "succeeded",
"reason": "partial_success"
}
},
"pending_control": null,
"duration_ms": 42000,
"elapsed_secs": 42.0,
"total_usd_micros": 123,
"superseded_by": superseded_by.to_string()
})
);
}
#[test]
fn run_summary_deserializes_when_optional_fields_are_absent() {
let created_at = Utc.with_ymd_and_hms(2026, 4, 20, 12, 0, 0).unwrap();
let run_id = RunId::with_timestamp(created_at, 7);
let summary: RunSummary = serde_json::from_value(json!({
"run_id": run_id.to_string(),
"goal": "ship it",
"title": "ship it",
"labels": {},
"status": {
"kind": "running"
},
"repository": {
"name": "fabro"
},
"created_at": "2026-04-20T12:00:00Z"
}))
.unwrap();
assert_eq!(summary.run_id, run_id);
assert_eq!(summary.workflow_name, None);
assert_eq!(summary.workflow_slug, None);
assert_eq!(summary.goal, "ship it");
assert_eq!(summary.title, "ship it");
assert_eq!(summary.labels, HashMap::new());
assert_eq!(summary.host_repo_path, None);
assert_eq!(summary.repository, RepositoryReference {
name: "fabro".to_string(),
});
assert_eq!(summary.start_time, None);
assert_eq!(summary.created_at, created_at);
assert_eq!(summary.status, RunStatus::Running);
assert_eq!(summary.pending_control, None);
assert_eq!(summary.duration_ms, None);
assert_eq!(summary.elapsed_secs, None);
assert_eq!(summary.total_usd_micros, None);
assert_eq!(summary.superseded_by, None);
}
fn assert_same_type<T: 'static, U: 'static>() {
assert_eq!(
TypeId::of::<T>(),
TypeId::of::<U>(),
"{} should be the same type as {}",
type_name::<T>(),
type_name::<U>()
);
}

View file

@ -65,7 +65,7 @@ impl ServerRunSummaryInfo {
}
pub(crate) fn goal(&self) -> String {
self.summary.goal.clone().unwrap_or_default()
self.summary.goal.clone()
}
}

View file

@ -0,0 +1,23 @@
use anyhow::Result;
use clap::Args;
use super::{PlannedCommand, spa_refresh};
#[derive(Debug, Args)]
pub(crate) struct BuildArgs {
/// Arguments forwarded to `cargo build`.
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
cargo_args: Vec<String>,
}
pub(crate) fn build(args: BuildArgs) -> Result<()> {
let root = super::workspace_root();
spa_refresh::spa_refresh_root(&root)?;
let mut command = PlannedCommand::new("cargo").arg("build");
for arg in args.cargo_args {
command = command.arg(arg);
}
super::run_command(&root, &command)
}

View file

@ -4,7 +4,7 @@ use std::path::PathBuf;
use anyhow::{Context, Result, bail};
use clap::{Args, ValueEnum};
use super::{PlannedCommand, run_command, shell_arg, workspace_root};
use super::{PlannedCommand, run_command, shell_arg, spa_refresh, workspace_root};
const ZIG_VERSION: &str = "0.13.0";
@ -98,6 +98,9 @@ impl DockerBuildPlan {
reason = "dev docker-build command reports progress directly"
)]
fn run(&self) -> Result<()> {
println!("Refreshing embedded SPA assets...");
spa_refresh::spa_refresh_root(&self.workspace_root)?;
println!(
"Building fabro-cli for {} inside rust:1-bookworm via cargo-zigbuild...",
self.arch.target()
@ -130,6 +133,7 @@ impl DockerBuildPlan {
fn dry_run_lines(&self) -> Vec<String> {
let mut lines = vec![
Self::spa_refresh_command().to_shell_line(),
self.build_command().to_shell_line(),
format!("mkdir -p {}", shell_arg(self.relative_context_dir())),
self.extract_command().to_shell_line(),
@ -142,6 +146,13 @@ impl DockerBuildPlan {
lines
}
fn spa_refresh_command() -> PlannedCommand {
PlannedCommand::new("cargo")
.arg("dev")
.arg("spa")
.arg("refresh")
}
fn build_command(&self) -> PlannedCommand {
let arch = self.arch.to_string();
let target = self.arch.target();

View file

@ -1,3 +1,4 @@
mod build;
mod docker_build;
mod docs;
mod docs_cli_reference;
@ -11,6 +12,7 @@ use std::path::{Path, PathBuf};
use std::process::{Command, Output};
use anyhow::{Context, Result};
pub(crate) use build::{BuildArgs, build};
pub(crate) use docker_build::{DockerBuildArgs, docker_build};
pub(crate) use docs::{DocsArgs, docs};
pub(crate) use release::{ReleaseArgs, release};

View file

@ -4,7 +4,7 @@ use anyhow::{Context, Result, bail};
use chrono::{Local, NaiveDate};
use clap::Args;
use super::{PlannedCommand, capture_command, run_command, workspace_root};
use super::{PlannedCommand, capture_command, run_command, spa_refresh, workspace_root};
const RELEASE_EPOCH: &str = "2026-01-01";
const RELEASE_TEST_SEGMENT_WRITE_KEY: &str = "fake-for-local-smoke";
@ -66,7 +66,7 @@ pub(crate) fn release(args: ReleaseArgs) -> Result<()> {
}
plan.ensure_clean_worktree()?;
plan.verify_spa_assets()?;
spa_refresh::spa_refresh_root(&plan.root)?;
plan.verify_release_tests()?;
update_version(&cargo_toml, &current_version, &new_version)?;
println!("Updated {}", cargo_toml.display());
@ -177,10 +177,6 @@ impl ReleasePlan {
Ok(())
}
fn verify_spa_assets(&self) -> Result<()> {
run_command(&self.root, &Self::spa_check_command())
}
#[expect(
clippy::print_stdout,
reason = "dev release command reports release test progress directly"
@ -200,8 +196,8 @@ impl ReleasePlan {
reason = "dev release command reports dry-run commands directly"
)]
fn print_dry_run(&self, current_version: &str, new_version: &str, tag: &str) {
println!("DRY RUN: would verify SPA assets:");
println!("{}", Self::spa_check_command().to_shell_line());
println!("DRY RUN: would refresh SPA assets:");
println!("{}", Self::spa_refresh_command().to_shell_line());
if self.skip_tests {
println!("--skip-tests set, would skip release-mode test smoke");
@ -239,11 +235,11 @@ impl ReleasePlan {
}
}
fn spa_check_command() -> PlannedCommand {
fn spa_refresh_command() -> PlannedCommand {
PlannedCommand::new("cargo")
.arg("dev")
.arg("spa")
.arg("check")
.arg("refresh")
}
fn release_tests_command() -> PlannedCommand {

View file

@ -79,7 +79,7 @@ pub(super) fn check_spa_asset_budgets(
if report.asset_bytes > asset_budget_bytes {
bail!(
"fabro-spa assets exceed budget: {} > {}",
"fabro-spa embedded assets exceed budget: {} > {}",
report.asset_bytes,
asset_budget_bytes
);

View file

@ -16,9 +16,6 @@ pub(crate) struct SpaRefreshArgs {
/// Repository root containing apps/fabro-web and lib/crates/fabro-spa.
#[arg(long, hide = true)]
root: Option<PathBuf>,
/// Skip bun run build and only mirror an existing dist directory.
#[arg(long, hide = true)]
pub(super) skip_build: bool,
/// Override the raw asset budget.
#[arg(long, hide = true, default_value_t = DEFAULT_ASSET_BUDGET_BYTES)]
pub(super) asset_budget_bytes: u64,
@ -29,11 +26,14 @@ pub(crate) struct SpaRefreshArgs {
pub(crate) fn spa_refresh(args: SpaRefreshArgs) -> Result<()> {
let root = args.root.unwrap_or_else(workspace_root);
spa_refresh_root(
&root,
args.skip_build,
args.asset_budget_bytes,
args.payload_budget_bytes,
spa_refresh_root_with_budgets(&root, args.asset_budget_bytes, args.payload_budget_bytes)
}
pub(crate) fn spa_refresh_root(root: &Path) -> Result<()> {
spa_refresh_root_with_budgets(
root,
DEFAULT_ASSET_BUDGET_BYTES,
DEFAULT_PAYLOAD_BUDGET_BYTES,
)
}
@ -41,9 +41,8 @@ pub(crate) fn spa_refresh(args: SpaRefreshArgs) -> Result<()> {
clippy::print_stdout,
reason = "dev spa refresh command reports progress directly"
)]
pub(super) fn spa_refresh_root(
fn spa_refresh_root_with_budgets(
root: &Path,
skip_build: bool,
asset_budget_bytes: u64,
payload_budget_bytes: u64,
) -> Result<()> {
@ -51,20 +50,36 @@ pub(super) fn spa_refresh_root(
let dist_dir = web_dir.join("dist");
let asset_dir = root.join("lib/crates/fabro-spa/assets");
if !skip_build {
println!("Running bun run build in apps/fabro-web...");
run_bun_build(&web_dir)?;
}
println!("Running bun run build in apps/fabro-web...");
run_bun_build(&web_dir)?;
let staging = TempDir::new(root, "refresh")?;
mirror_dist(&dist_dir, staging.path())?;
check_spa_asset_budgets(staging.path(), asset_budget_bytes, payload_budget_bytes)?;
mirror_dist(staging.path(), &asset_dir)?;
refresh_from_dist(
root,
&dist_dir,
&asset_dir,
asset_budget_bytes,
payload_budget_bytes,
)?;
println!("Refreshed lib/crates/fabro-spa/assets");
Ok(())
}
fn refresh_from_dist(
root: &Path,
dist_dir: &Path,
asset_dir: &Path,
asset_budget_bytes: u64,
payload_budget_bytes: u64,
) -> Result<()> {
let staging = TempDir::new(root, "refresh")?;
mirror_dist(dist_dir, staging.path())?;
check_spa_asset_budgets(staging.path(), asset_budget_bytes, payload_budget_bytes)?;
mirror_dist(staging.path(), asset_dir)?;
Ok(())
}
#[expect(
clippy::disallowed_methods,
reason = "dev spa refresh intentionally runs a synchronous Bun subprocess"
@ -128,6 +143,9 @@ pub(super) fn mirror_dist(dist_dir: &Path, asset_dir: &Path) -> Result<()> {
})?;
}
std::fs::write(asset_dir.join(".gitkeep"), b"")
.with_context(|| format!("writing {}", asset_dir.join(".gitkeep").display()))?;
Ok(())
}
@ -170,3 +188,89 @@ impl Drop for TempDir {
let _ = std::fs::remove_dir_all(&self.path);
}
}
#[cfg(test)]
#[expect(
clippy::disallowed_methods,
reason = "tests stage temporary SPA fixture files with sync std::fs operations"
)]
mod tests {
use std::path::Path;
use super::{mirror_dist, refresh_from_dist};
fn write_file(root: &Path, path: &str, contents: impl AsRef<[u8]>) {
let path = root.join(path);
std::fs::create_dir_all(path.parent().expect("fixture path should have parent"))
.expect("creating fixture parent directory");
std::fs::write(path, contents).expect("writing fixture file");
}
fn read_bytes(root: &Path, path: &str) -> Vec<u8> {
std::fs::read(root.join(path)).expect("reading fixture file")
}
#[test]
fn mirror_dist_removes_stale_files_source_maps_and_keeps_directory_tracked() {
let fixture = tempfile::tempdir().expect("creating fixture");
write_file(fixture.path(), "dist/index.html", b"index");
write_file(fixture.path(), "dist/assets/app.js", b"app");
write_file(fixture.path(), "dist/assets/app.js.map", b"map");
write_file(fixture.path(), "assets/stale.txt", b"stale");
mirror_dist(&fixture.path().join("dist"), &fixture.path().join("assets"))
.expect("mirroring dist");
assert!(fixture.path().join("assets/index.html").is_file());
assert!(fixture.path().join("assets/assets/app.js").is_file());
assert!(fixture.path().join("assets/.gitkeep").is_file());
assert!(!fixture.path().join("assets/assets/app.js.map").exists());
assert!(!fixture.path().join("assets/stale.txt").exists());
}
#[test]
fn mirror_dist_missing_source_errors_cleanly() {
let fixture = tempfile::tempdir().expect("creating fixture");
let error = mirror_dist(&fixture.path().join("dist"), &fixture.path().join("assets"))
.expect_err("missing dist should fail");
assert!(
error
.to_string()
.contains("apps/fabro-web/dist is missing; run `bun run build`"),
"missing dist should explain how to recover: {error:#}"
);
}
#[test]
fn refresh_budget_failure_leaves_assets_untouched() {
let fixture = tempfile::tempdir().expect("creating fixture");
write_file(fixture.path(), "apps/fabro-web/dist/index.html", b"hello");
write_file(
fixture.path(),
"lib/crates/fabro-spa/assets/index.html",
b"embedded",
);
let error = refresh_from_dist(
fixture.path(),
&fixture.path().join("apps/fabro-web/dist"),
&fixture.path().join("lib/crates/fabro-spa/assets"),
4,
100,
)
.expect_err("budget failure should fail");
assert!(
error
.to_string()
.contains("fabro-spa embedded assets exceed budget: 5 > 4"),
"budget failure should report raw byte overage: {error:#}"
);
assert_eq!(
read_bytes(fixture.path(), "lib/crates/fabro-spa/assets/index.html"),
b"embedded"
);
}
}

View file

@ -18,6 +18,8 @@ struct Cli {
#[derive(Debug, Subcommand)]
enum Command {
/// Refresh embedded SPA assets and run cargo build.
Build(commands::BuildArgs),
/// Build Fabro Docker images with the release pipeline layout.
DockerBuild(commands::DockerBuildArgs),
/// Manage generated reference documentation.
@ -31,6 +33,7 @@ enum Command {
impl Command {
fn run(self) -> Result<()> {
match self {
Self::Build(args) => commands::build(args),
Self::DockerBuild(args) => commands::docker_build(args),
Self::Docs(args) => commands::docs(args),
Self::Release(args) => commands::release(args),

View file

@ -52,6 +52,10 @@ fn dry_run_prints_equivalent_build_commands() {
.clone();
let stdout = output_text(&output.stdout);
assert!(
stdout.contains("cargo dev spa refresh"),
"dry-run should print SPA refresh command:\n{stdout}"
);
assert!(
stdout.contains("docker run --rm --platform linux/amd64"),
"dry-run should print builder docker run:\n{stdout}"

View file

@ -58,7 +58,7 @@ fn help_lists_scaffolded_commands() {
.clone();
let stdout = output_text(&output.stdout);
for command in ["docker-build", "docs", "release", "spa"] {
for command in ["build", "docker-build", "docs", "release", "spa"] {
assert!(
stdout.contains(command),
"top-level help should list {command}:\n{stdout}"
@ -114,6 +114,22 @@ fn group_only_docs_prints_subcommand_help_successfully() {
}
}
#[test]
fn build_help_lists_forwarded_cargo_args() {
let output = fabro_dev()
.args(["build", "--help"])
.assert()
.success()
.get_output()
.clone();
let stdout = output_text(&output.stdout);
assert!(
stdout.contains("Arguments forwarded to `cargo build`"),
"build help should explain forwarded cargo args:\n{stdout}"
);
}
#[test]
fn cargo_dev_alias_points_at_fabro_dev() {
let config = read_file(&workspace_root(), ".cargo/config.toml");

View file

@ -96,8 +96,8 @@ fn dry_run_computes_stable_version_from_date() {
"dry-run should compute base version from date:\n{stdout}"
);
assert!(
stdout.contains("cargo dev spa check"),
"dry-run should print one SPA verification command:\n{stdout}"
stdout.contains("cargo dev spa refresh"),
"dry-run should print one SPA refresh command:\n{stdout}"
);
assert!(
!stdout.contains("git diff --exit-code -- lib/crates/fabro-spa/assets"),

View file

@ -1,135 +1,19 @@
use super::{fabro_dev, output_text, read_bytes, write_file};
#[test]
fn refresh_mirrors_dist_and_removes_source_maps() {
let fixture = tempfile::tempdir().expect("creating fixture");
write_file(fixture.path(), "apps/fabro-web/dist/index.html", b"index");
write_file(fixture.path(), "apps/fabro-web/dist/assets/app.js", b"app");
write_file(
fixture.path(),
"apps/fabro-web/dist/assets/app.js.map",
b"map",
);
write_file(
fixture.path(),
"lib/crates/fabro-spa/assets/stale.txt",
b"stale",
);
fn refresh_rejects_removed_skip_build_flag() {
let output = fabro_dev()
.args([
"spa",
"refresh",
"--root",
fixture
.path()
.to_str()
.expect("fixture path should be utf-8"),
"--skip-build",
])
.assert()
.success()
.get_output()
.clone();
let stdout = output_text(&output.stdout);
assert!(
stdout.contains("Refreshed lib/crates/fabro-spa/assets"),
"spa refresh should report refreshed assets:\n{stdout}"
);
assert!(
fixture
.path()
.join("lib/crates/fabro-spa/assets/index.html")
.is_file()
);
assert!(
fixture
.path()
.join("lib/crates/fabro-spa/assets/assets/app.js")
.is_file()
);
assert!(
!fixture
.path()
.join("lib/crates/fabro-spa/assets/assets/app.js.map")
.exists()
);
assert!(
!fixture
.path()
.join("lib/crates/fabro-spa/assets/stale.txt")
.exists()
);
}
#[test]
fn refresh_missing_dist_errors_cleanly() {
let fixture = tempfile::tempdir().expect("creating fixture");
let output = fabro_dev()
.args([
"spa",
"refresh",
"--root",
fixture
.path()
.to_str()
.expect("fixture path should be utf-8"),
"--skip-build",
])
.args(["spa", "refresh", "--skip-build"])
.assert()
.failure()
.code(1)
.code(2)
.get_output()
.clone();
let stderr = output_text(&output.stderr);
assert!(
stderr.contains("apps/fabro-web/dist is missing; run `bun run build`"),
"missing dist should explain how to recover:\n{stderr}"
);
}
#[test]
fn refresh_budget_failure_leaves_assets_untouched() {
let fixture = tempfile::tempdir().expect("creating fixture");
write_file(fixture.path(), "apps/fabro-web/dist/index.html", b"hello");
write_file(
fixture.path(),
"lib/crates/fabro-spa/assets/index.html",
b"committed",
);
let output = fabro_dev()
.args([
"spa",
"refresh",
"--root",
fixture
.path()
.to_str()
.expect("fixture path should be utf-8"),
"--skip-build",
"--asset-budget-bytes",
"4",
"--payload-budget-bytes",
"100",
])
.assert()
.failure()
.code(1)
.get_output()
.clone();
let stderr = output_text(&output.stderr);
assert!(
stderr.contains("fabro-spa assets exceed budget: 5 > 4"),
"budget failure should report raw byte overage:\n{stderr}"
);
assert_eq!(
read_bytes(fixture.path(), "lib/crates/fabro-spa/assets/index.html"),
b"committed"
stderr.contains("unexpected argument '--skip-build'"),
"spa refresh should reject removed --skip-build flag:\n{stderr}"
);
}
@ -142,6 +26,7 @@ fn check_passes_when_dist_matches_assets_and_budgets_pass() {
"lib/crates/fabro-spa/assets/index.html",
b"hello",
);
write_file(fixture.path(), "lib/crates/fabro-spa/assets/.gitkeep", b"");
let output = fabro_dev()
.args([
@ -206,7 +91,7 @@ fn check_fails_when_assets_exceed_budget() {
let stderr = output_text(&output.stderr);
assert!(
stderr.contains("fabro-spa assets exceed budget: 5 > 4"),
stderr.contains("fabro-spa embedded assets exceed budget: 5 > 4"),
"budget failure should report raw byte overage:\n{stderr}"
);
}
@ -218,7 +103,7 @@ fn check_fails_when_assets_do_not_match_dist() {
write_file(
fixture.path(),
"lib/crates/fabro-spa/assets/index.html",
b"committed",
b"embedded",
);
let output = fabro_dev()
@ -245,7 +130,7 @@ fn check_fails_when_assets_do_not_match_dist() {
);
assert_eq!(
read_bytes(fixture.path(), "lib/crates/fabro-spa/assets/index.html"),
b"committed"
b"embedded"
);
}

View file

@ -93,7 +93,7 @@ pub(crate) async fn resolve_run(
match resolve_run_by_selector(
&runs,
&params.selector,
|run| run.run_id.clone(),
|run| run.run_id.to_string(),
|run| run.workflow_slug.clone(),
|run| run.workflow_name.clone(),
|run| run.created_at,
@ -312,7 +312,10 @@ pub(crate) async fn get_run_status(
State(_state): State<Arc<AppState>>,
Path(id): Path<String>,
) -> Response {
match runs::summaries().into_iter().find(|run| run.run_id == id) {
match runs::summaries()
.into_iter()
.find(|run| run.run_id.to_string() == id)
{
Some(run) => (StatusCode::OK, Json(run)).into_response(),
None => ApiError::not_found("Run not found.").into_response(),
}
@ -755,18 +758,18 @@ fn ts(s: &str) -> DateTime<Utc> {
mod runs {
use std::collections::HashMap;
use std::sync::OnceLock;
use std::time::Duration;
use fabro_api::types::*;
use fabro_types::WorkflowSettings;
use fabro_types::settings::run::{
DaytonaSettings, DaytonaSnapshotSettings, LocalSandboxSettings, RunGoal, RunModelSettings,
RunNamespace, RunPrepareSettings, RunSandboxSettings,
};
use fabro_types::settings::{InterpString, ProjectNamespace, WorkflowNamespace};
use fabro_types::{RunId, WorkflowSettings};
use super::ts;
use crate::server::truncate_goal;
fn labels(entries: &[(&str, &str)]) -> HashMap<String, String> {
entries
@ -775,8 +778,26 @@ mod runs {
.collect()
}
fn demo_run_ids() -> &'static [RunId; 6] {
static IDS: OnceLock<[RunId; 6]> = OnceLock::new();
IDS.get_or_init(|| {
[
RunId::with_timestamp(ts("2026-03-06T14:30:00Z"), 1),
RunId::with_timestamp(ts("2026-03-06T12:00:00Z"), 2),
RunId::with_timestamp(ts("2026-03-04T15:00:00Z"), 3),
RunId::with_timestamp(ts("2026-03-04T10:00:00Z"), 4),
RunId::with_timestamp(ts("2026-03-03T16:45:00Z"), 5),
RunId::with_timestamp(ts("2026-02-28T14:00:00Z"), 6),
]
})
}
fn demo_run_id(index: usize) -> RunId {
demo_run_ids()[index - 1]
}
fn summary(
run_id: &str,
sequence: u128,
repo_name: &str,
workflow_slug: &str,
workflow_name: &str,
@ -788,28 +809,24 @@ mod runs {
pending_control: Option<RunControlAction>,
total_usd_micros: Option<i64>,
entries: &[(&str, &str)],
) -> StoreRunSummary {
StoreRunSummary {
created_at: ts(created_at),
duration_ms: elapsed_secs.and_then(duration_ms_from_secs),
elapsed_secs,
goal: goal.into(),
host_repo_path: Some(format!("/demo/{repo_name}")),
labels: labels(entries),
pending_control,
repository: RepositoryReference {
name: repo_name.into(),
},
run_id: run_id.into(),
start_time: Some(ts(created_at)),
status: parse_run_status(status, status_reason)
) -> RunSummary {
let created_at = ts(created_at);
let run_id = RunId::with_timestamp(created_at, sequence);
RunSummary::new(
run_id,
Some(workflow_name.into()),
Some(workflow_slug.into()),
goal.into(),
labels(entries),
Some(format!("/demo/{repo_name}")),
Some(created_at),
parse_run_status(status, status_reason)
.unwrap_or_else(|| panic!("invalid demo run status: {status}")),
superseded_by: None,
title: truncate_goal(goal),
pending_control,
elapsed_secs.and_then(duration_ms_from_secs),
total_usd_micros,
workflow_name: Some(workflow_name.into()),
workflow_slug: Some(workflow_slug.into()),
}
None,
)
}
fn parse_run_status(status: &str, status_reason: Option<&str>) -> Option<RunStatus> {
@ -860,22 +877,19 @@ mod runs {
}
}
fn duration_ms_from_secs(secs: f64) -> Option<i64> {
fn duration_ms_from_secs(secs: f64) -> Option<u64> {
let duration = Duration::try_from_secs_f64(secs).ok()?;
duration.as_millis().try_into().ok()
}
fn take_summary(
summaries: &mut HashMap<String, StoreRunSummary>,
run_id: &str,
) -> StoreRunSummary {
fn take_summary(summaries: &mut HashMap<RunId, RunSummary>, run_id: RunId) -> RunSummary {
summaries
.remove(run_id)
.remove(&run_id)
.unwrap_or_else(|| panic!("missing demo summary: {run_id}"))
}
fn board_item(
summary: StoreRunSummary,
summary: RunSummary,
column: BoardColumn,
pull_request: Option<RunPullRequest>,
sandbox: Option<RunSandbox>,
@ -884,7 +898,7 @@ mod runs {
RunListItem {
column,
created_at: summary.created_at,
duration_ms: summary.duration_ms,
duration_ms: summary.duration_ms.and_then(|ms| i64::try_from(ms).ok()),
elapsed_secs: summary.elapsed_secs,
goal: summary.goal,
host_repo_path: summary.host_repo_path,
@ -893,7 +907,7 @@ mod runs {
pull_request,
question,
repository: summary.repository,
run_id: summary.run_id,
run_id: summary.run_id.to_string(),
sandbox,
start_time: summary.start_time,
status: summary.status,
@ -960,10 +974,10 @@ mod runs {
]
}
pub(super) fn summaries() -> Vec<StoreRunSummary> {
pub(super) fn summaries() -> Vec<RunSummary> {
vec![
summary(
"run-1",
1,
"api-server",
"implement",
"Implement",
@ -977,7 +991,7 @@ mod runs {
&[("branch", "rate-limit"), ("team", "platform")],
),
summary(
"run-2",
2,
"web-dashboard",
"implement",
"Implement",
@ -991,7 +1005,7 @@ mod runs {
&[("owner", "frontend")],
),
summary(
"run-3",
3,
"shared-types",
"expand",
"Expand",
@ -1005,7 +1019,7 @@ mod runs {
&[("priority", "high")],
),
summary(
"run-4",
4,
"shared-types",
"implement",
"Implement",
@ -1019,7 +1033,7 @@ mod runs {
&[("owner", "runtime")],
),
summary(
"run-5",
5,
"web-dashboard",
"implement",
"Implement",
@ -1033,7 +1047,7 @@ mod runs {
&[("environment", "staging")],
),
summary(
"run-6",
6,
"api-server",
"implement",
"Implement",
@ -1052,26 +1066,26 @@ mod runs {
pub(super) fn board_items() -> Vec<RunListItem> {
let mut summaries = summaries()
.into_iter()
.map(|summary| (summary.run_id.clone(), summary))
.map(|summary| (summary.run_id, summary))
.collect::<HashMap<_, _>>();
vec![
board_item(
take_summary(&mut summaries, "run-1"),
take_summary(&mut summaries, demo_run_id(1)),
BoardColumn::Running,
None,
Some(sandbox("sb-a1b2c3d4", 4, 8)),
None,
),
board_item(
take_summary(&mut summaries, "run-2"),
take_summary(&mut summaries, demo_run_id(2)),
BoardColumn::Running,
None,
Some(sandbox("sb-e5f6g7h8", 8, 16)),
None,
),
board_item(
take_summary(&mut summaries, "run-3"),
take_summary(&mut summaries, demo_run_id(3)),
BoardColumn::Initializing,
Some(pull_request(0, 567, 234, 0, vec![])),
Some(sandbox("sb-q7r8s9t0", 4, 8)),
@ -1080,7 +1094,7 @@ mod runs {
}),
),
board_item(
take_summary(&mut summaries, "run-4"),
take_summary(&mut summaries, demo_run_id(4)),
BoardColumn::Blocked,
Some(pull_request(0, 145, 23, 0, vec![])),
Some(sandbox("sb-u1v2w3x4", 4, 8)),
@ -1089,7 +1103,7 @@ mod runs {
}),
),
board_item(
take_summary(&mut summaries, "run-5"),
take_summary(&mut summaries, demo_run_id(5)),
BoardColumn::Failed,
Some(pull_request(889, 234, 67, 4, vec![
check("lint", CheckRunStatus::Success, Some(23.0)),
@ -1102,7 +1116,7 @@ mod runs {
None,
),
board_item(
take_summary(&mut summaries, "run-6"),
take_summary(&mut summaries, demo_run_id(6)),
BoardColumn::Succeeded,
Some(pull_request(1249, 189, 45, 7, vec![
check("lint", CheckRunStatus::Success, Some(21.0)),
@ -1410,7 +1424,7 @@ mod runs {
#[test]
fn summary_parses_known_status_reason_values() {
let summary = summary(
"run-test",
99,
"demo-repo",
"implement",
"Implement",
@ -1432,7 +1446,7 @@ mod runs {
#[test]
fn summary_ignores_unknown_status_reason() {
let summary = summary(
"run-test",
99,
"demo-repo",
"implement",
"Implement",
@ -1455,7 +1469,7 @@ mod runs {
fn summary_derives_title_like_server() {
let goal = format!("## Plan: {}", "a".repeat(120));
let summary = summary(
"run-test",
99,
"demo-repo",
"implement",
"Implement",

View file

@ -80,7 +80,6 @@ use fabro_types::{
RunBlobId, RunClientProvenance, RunControlAction, RunEvent, RunId, RunProvenance,
RunServerProvenance, RunSubjectProvenance, ServerSettings,
};
use fabro_util::text::strip_goal_decoration;
use fabro_util::version::FABRO_VERSION;
use fabro_vault::{Error as VaultError, SecretType, Vault};
use fabro_workflow::artifact_upload::ArtifactSink;
@ -2868,56 +2867,6 @@ pub(crate) fn board_columns() -> serde_json::Value {
])
}
pub(crate) fn truncate_goal(goal: &str) -> String {
const MAX_LEN: usize = 100;
let stripped = strip_goal_decoration(goal);
let char_count = stripped.chars().count();
if char_count <= MAX_LEN {
return stripped.to_string();
}
let truncated: String = stripped.chars().take(MAX_LEN - 3).collect();
format!("{truncated}...")
}
fn repository_name(host_repo_path: Option<&str>) -> String {
host_repo_path
.and_then(|path| path.rsplit(['/', '\\']).find(|segment| !segment.is_empty()))
.unwrap_or("unknown")
.to_string()
}
fn elapsed_secs(duration_ms: Option<u64>) -> Option<f64> {
duration_ms.map(|ms| ms as f64 / 1000.0)
}
fn summary_to_api_run_summary(summary: fabro_types::RunSummary) -> serde_json::Value {
let goal = summary.goal.unwrap_or_default();
let title = truncate_goal(&goal);
let repository = repository_name(summary.host_repo_path.as_deref());
let created_at = summary.run_id.created_at().to_rfc3339();
serde_json::json!({
"run_id": summary.run_id.to_string(),
"workflow_name": summary.workflow_name,
"workflow_slug": summary.workflow_slug,
"goal": goal,
"title": title,
"labels": summary.labels,
"host_repo_path": summary.host_repo_path,
"repository": { "name": repository },
"start_time": summary.start_time.map(|time| time.to_rfc3339()),
"status": summary.status,
"pending_control": summary.pending_control,
"duration_ms": summary.duration_ms,
"elapsed_secs": elapsed_secs(summary.duration_ms),
"total_usd_micros": summary.total_usd_micros,
"superseded_by": summary.superseded_by.map(|run_id| run_id.to_string()),
"created_at": created_at,
})
}
async fn board_run_metadata(
state: &AppState,
run_id: RunId,
@ -3010,7 +2959,8 @@ async fn list_board_runs(
let mut data = Vec::with_capacity(page_summaries.len());
for (summary, column) in page_summaries {
let run_id = summary.run_id;
let mut item = summary_to_api_run_summary(summary);
let mut item =
serde_json::to_value(&summary).expect("RunSummary serialization is infallible");
item["column"] = serde_json::json!(column);
if let Some(object) = item.as_object_mut() {
object.extend(board_run_metadata(state.as_ref(), run_id).await);
@ -3045,7 +2995,6 @@ async fn list_runs(
.filter(|summary| {
include_archived || !matches!(summary.status, RunStatus::Archived { .. })
})
.map(summary_to_api_run_summary)
.collect::<Vec<_>>();
let (data, has_more) = paginate_items(items, &params.pagination());
(
@ -3099,11 +3048,7 @@ async fn resolve_run(
|run| run.workflow_name.clone(),
|run| run.run_id.created_at(),
) {
Ok(run) => (
StatusCode::OK,
Json(summary_to_api_run_summary(run.clone())),
)
.into_response(),
Ok(run) => (StatusCode::OK, Json(run.clone())).into_response(),
Err(err @ (ResolveRunError::InvalidSelector | ResolveRunError::AmbiguousPrefix { .. })) => {
ApiError::bad_request(err.to_string()).into_response()
}
@ -5174,7 +5119,7 @@ async fn get_run_status(
.await
{
Ok(runs) => match runs.into_iter().find(|run| run.run_id == id) {
Some(run) => (StatusCode::OK, Json(summary_to_api_run_summary(run))).into_response(),
Some(run) => (StatusCode::OK, Json(run)).into_response(),
None => ApiError::not_found("Run not found.").into_response(),
},
Err(err) => {
@ -13501,18 +13446,24 @@ provider = "local"
}
#[tokio::test]
async fn demo_get_run_returns_store_run_summary_shape() {
async fn demo_get_run_returns_run_summary_shape() {
let state = create_app_state();
let app = build_router(state, AuthMode::Disabled);
let run_id = RunId::with_timestamp(
"2026-03-06T14:30:00Z"
.parse()
.expect("demo timestamp should parse"),
1,
);
let req = Request::builder()
.method("GET")
.uri(api("/runs/run-1"))
.uri(api(&format!("/runs/{run_id}")))
.header("X-Fabro-Demo", "1")
.body(Body::empty())
.unwrap();
let response = app.oneshot(req).await.unwrap();
let body = response_json!(response, StatusCode::OK).await;
// Should have StoreRunSummary fields, not RunStatusResponse fields
// Should have RunSummary fields, not RunStatusResponse fields
assert!(body["run_id"].is_string(), "should have run_id field");
assert!(body["goal"].is_string(), "should have goal field");
assert!(

0
lib/crates/fabro-spa/assets/.gitkeep generated Normal file
View file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{S as a}from"./chunk-c8zhk10v.js";import"./chunk-xg9nsz1a.js";import"./chunk-gf0502ds.js";export{a as default};

View file

@ -1 +0,0 @@
import{d as a}from"./chunk-5q0vf5kd.js";import"./chunk-z1p7fbkb.js";import"./chunk-amk943wr.js";import"./chunk-972wx742.js";import"./chunk-ept66kdn.js";import"./chunk-1ehq66yp.js";import"./chunk-xg9nsz1a.js";import"./chunk-z868q2s0.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{e}from"./chunk-7zy2rxws.js";import"./chunk-gf0502ds.js";var n=Object.freeze(JSON.parse('{"displayName":"Nextflow","name":"nextflow","patterns":[{"include":"#nextflow"}],"repository":{"enum-def":{"begin":"^\\\\s*(enum)\\\\s+(\\\\w+)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"},"2":{"name":"storage.type.groovy"}},"end":"}","patterns":[{"include":"source.nextflow-groovy#groovy"},{"include":"#enum-values"}]},"enum-values":{"patterns":[{"begin":"(?<=;|^)\\\\s*\\\\b([0-9A-Z_]+)(?=\\\\s*(?:[(,}]|$))","beginCaptures":{"1":{"name":"constant.enum.name.groovy"}},"end":",|(?=})|^(?!\\\\s*\\\\w+\\\\s*(?:,|$))","patterns":[{"begin":"\\\\(","end":"\\\\)","name":"meta.enum.value.groovy","patterns":[{"match":",","name":"punctuation.definition.seperator.parameter.groovy"},{"include":"#groovy-code"}]}]}]},"function-body":{"patterns":[{"match":"\\\\s"},{"begin":"(?=[<\\\\w][^(]*\\\\s+[$<\\\\w]+\\\\s*\\\\()","end":"(?=[$\\\\w]+\\\\s*\\\\()","name":"meta.method.return-type.java","patterns":[{"include":"source.nextflow-groovy#types"}]},{"begin":"([$\\\\w]+)\\\\s*\\\\(","beginCaptures":{"1":{"name":"entity.name.function.nextflow"}},"end":"\\\\)","name":"meta.definition.method.signature.java","patterns":[{"begin":"(?=[^)])","end":"(?=\\\\))","name":"meta.method.parameters.groovy","patterns":[{"begin":"(?=[^),])","end":"(?=[),])","name":"meta.method.parameter.groovy","patterns":[{"match":",","name":"punctuation.definition.separator.groovy"},{"begin":"=","beginCaptures":{"0":{"name":"keyword.operator.assignment.groovy"}},"end":"(?=[),])","name":"meta.parameter.default.groovy","patterns":[{"include":"source.nextflow-groovy#groovy-code"}]},{"include":"source.nextflow-groovy#parameters"}]}]}]},{"begin":"(?=<)","end":"(?=\\\\s)","name":"meta.method.paramerised-type.groovy","patterns":[{"begin":"<","end":">","name":"storage.type.parameters.groovy","patterns":[{"include":"source.nextflow-groovy#types"},{"match":",","name":"punctuation.definition.seperator.groovy"}]}]},{"begin":"\\\\{","end":"(?=})","name":"meta.method.body.java","patterns":[{"include":"source.nextflow-groovy#groovy-code"}]}]},"function-def":{"applyEndPatternLast":1,"begin":"(?<=;|^|\\\\{)(?=\\\\s*(?:def|(?:(?:boolean|byte|char|short|int|float|long|double)|@?(?:[A-Za-z]\\\\w*\\\\.)*[A-Z]+\\\\w*)[]\\\\[]*(?:<.*>)?n)\\\\s+([^=]+\\\\s+)?\\\\w+\\\\s*\\\\()","end":"}|(?=[^{])","name":"meta.definition.method.groovy","patterns":[{"include":"#function-body"}]},"include-decl":{"patterns":[{"match":"^\\\\b(include)\\\\b","name":"keyword.nextflow"},{"match":"\\\\b(from)\\\\b","name":"keyword.nextflow"}]},"nextflow":{"patterns":[{"include":"#record-def"},{"include":"#enum-def"},{"include":"#function-def"},{"include":"#process-def"},{"include":"#workflow-def"},{"include":"#params-def"},{"include":"#output-def"},{"include":"#include-decl"},{"include":"source.nextflow-groovy"}]},"output-def":{"begin":"^\\\\s*(output)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"}},"end":"}","name":"output.nextflow","patterns":[{"include":"source.nextflow-groovy#groovy"}]},"params-def":{"begin":"^\\\\s*(params)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"}},"end":"}","name":"params.nextflow","patterns":[{"include":"source.nextflow-groovy#groovy"}]},"process-body":{"patterns":[{"match":"(?:input|output|when|script|shell|exec):","name":"constant.block.nextflow"},{"match":"\\\\b(val|env|file|path|stdin|stdout|tuple)([(\\\\s])","name":"entity.name.function.nextflow"},{"include":"source.nextflow-groovy#groovy"}]},"process-def":{"begin":"^\\\\s*(process)\\\\s+(\\\\w+)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"},"2":{"name":"entity.name.function.nextflow"}},"end":"}","name":"process.nextflow","patterns":[{"include":"#process-body"}]},"record-def":{"begin":"^\\\\s*(record)\\\\s+(\\\\w+)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"},"2":{"name":"storage.type.groovy"}},"end":"}","name":"record.nextflow","patterns":[{"include":"source.nextflow-groovy#groovy"}]},"workflow-body":{"patterns":[{"match":"(?:take|main|emit|publish):","name":"constant.block.nextflow"},{"include":"source.nextflow-groovy#groovy"}]},"workflow-def":{"begin":"^\\\\s*(workflow)(?:\\\\s+(\\\\w+))?\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"},"2":{"name":"entity.name.function.nextflow"}},"end":"}","name":"workflow.nextflow","patterns":[{"include":"#workflow-body"}]}},"scopeName":"source.nextflow","embeddedLangs":["nextflow-groovy"],"aliases":["nf"]}')),t=[...e,n];export{t as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{v as a}from"./chunk-ktx0nkhz.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{O as a}from"./chunk-ept66kdn.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"CODEOWNERS","name":"codeowners","patterns":[{"include":"#comment"},{"include":"#pattern"},{"include":"#owner"}],"repository":{"comment":{"patterns":[{"begin":"^\\\\s*#","captures":{"0":{"name":"punctuation.definition.comment.codeowners"}},"end":"$","name":"comment.line.codeowners"}]},"owner":{"match":"\\\\S*@\\\\S+","name":"storage.type.function.codeowners"},"pattern":{"match":"^\\\\s*(\\\\S+)","name":"variable.other.codeowners"}},"scopeName":"text.codeowners"}')),n=[e];export{n as default};

View file

@ -1 +0,0 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Gettext PO","fileTypes":["po","pot","potx"],"name":"po","patterns":[{"begin":"^(?:(?=(msg(?:id(_plural)?|ctxt))\\\\s*\\"[^\\"])|\\\\s*$)","end":"\\\\z","patterns":[{"include":"#body"}]},{"include":"#comments"},{"match":"^msg(id|str)\\\\s+\\"\\"\\\\s*$\\\\n?","name":"comment.line.number-sign.po"},{"captures":{"1":{"name":"constant.language.po"},"2":{"name":"punctuation.separator.key-value.po"},"3":{"name":"string.other.po"}},"match":"^\\"(?:([^:\\\\s]+)(:)\\\\s+)?([^\\"]*)\\"\\\\s*$\\\\n?","name":"meta.header.po"}],"repository":{"body":{"patterns":[{"begin":"^(msgid(_plural)?)\\\\s+","beginCaptures":{"1":{"name":"keyword.control.msgid.po"}},"end":"^(?!\\")","name":"meta.scope.msgid.po","patterns":[{"begin":"(\\\\G|^)\\"","end":"\\"","name":"string.quoted.double.po","patterns":[{"match":"\\\\\\\\[\\"\\\\\\\\]","name":"constant.character.escape.po"}]}]},{"begin":"^(msgstr)(?:(\\\\[)(\\\\d+)(]))?\\\\s+","beginCaptures":{"1":{"name":"keyword.control.msgstr.po"},"2":{"name":"keyword.control.msgstr.po"},"3":{"name":"constant.numeric.po"},"4":{"name":"keyword.control.msgstr.po"}},"end":"^(?!\\")","name":"meta.scope.msgstr.po","patterns":[{"begin":"(\\\\G|^)\\"","end":"\\"","name":"string.quoted.double.po","patterns":[{"match":"\\\\\\\\[\\"\\\\\\\\]","name":"constant.character.escape.po"}]}]},{"begin":"^(msgctxt)(?:(\\\\[)(\\\\d+)(]))?\\\\s+","beginCaptures":{"1":{"name":"keyword.control.msgctxt.po"},"2":{"name":"keyword.control.msgctxt.po"},"3":{"name":"constant.numeric.po"},"4":{"name":"keyword.control.msgctxt.po"}},"end":"^(?!\\")","name":"meta.scope.msgctxt.po","patterns":[{"begin":"(\\\\G|^)\\"","end":"\\"","name":"string.quoted.double.po","patterns":[{"match":"\\\\\\\\[\\"\\\\\\\\]","name":"constant.character.escape.po"}]}]},{"captures":{"1":{"name":"punctuation.definition.comment.po"}},"match":"^(#~).*$\\\\n?","name":"comment.line.number-sign.obsolete.po"},{"include":"#comments"},{"match":"^(?!\\\\s*$)[^\\"#].*$\\\\n?","name":"invalid.illegal.po"}]},"comments":{"patterns":[{"begin":"^(?=#)","end":"(?!\\\\G)","patterns":[{"begin":"(#,)\\\\s+","beginCaptures":{"1":{"name":"punctuation.definition.comment.po"}},"end":"\\\\n","name":"comment.line.number-sign.flag.po","patterns":[{"captures":{"1":{"name":"entity.name.type.flag.po"}},"match":"(?:\\\\G|,\\\\s*)(fuzzy|(?:no-)?(?:c|objc|sh|lisp|elisp|librep|scheme|smalltalk|java|csharp|awk|object-pascal|ycp|tcl|perl|perl-brace|php|gcc-internal|qt|boost)-format)"}]},{"begin":"#\\\\.","beginCaptures":{"0":{"name":"punctuation.definition.comment.po"}},"end":"\\\\n","name":"comment.line.number-sign.extracted.po"},{"begin":"(#:)[\\\\t ]*","beginCaptures":{"1":{"name":"punctuation.definition.comment.po"}},"end":"\\\\n","name":"comment.line.number-sign.reference.po","patterns":[{"match":"(\\\\S+:)([;\\\\d]*)","name":"storage.type.class.po"}]},{"begin":"#\\\\|","beginCaptures":{"0":{"name":"punctuation.definition.comment.po"}},"end":"\\\\n","name":"comment.line.number-sign.previous.po"},{"begin":"#","beginCaptures":{"0":{"name":"punctuation.definition.comment.po"}},"end":"\\\\n","name":"comment.line.number-sign.po"}]}]}},"scopeName":"source.po","aliases":["pot","potx"]}')),n=[e];export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Tcl","fileTypes":["tcl"],"foldingStartMarker":"\\\\{\\\\s*$","foldingStopMarker":"^\\\\s*}","name":"tcl","patterns":[{"begin":"(?<=^|;)\\\\s*((#))","beginCaptures":{"1":{"name":"comment.line.number-sign.tcl"},"2":{"name":"punctuation.definition.comment.tcl"}},"contentName":"comment.line.number-sign.tcl","end":"\\\\n","patterns":[{"match":"(\\\\\\\\[\\\\n\\\\\\\\])"}]},{"captures":{"1":{"name":"keyword.control.tcl"}},"match":"(?<=^|[;\\\\[{])\\\\s*(if|while|for|catch|default|return|break|continue|switch|exit|foreach|try|throw)\\\\b"},{"captures":{"1":{"name":"keyword.control.tcl"}},"match":"(?<=^|})\\\\s*(then|elseif|else)\\\\b"},{"captures":{"1":{"name":"keyword.other.tcl"},"2":{"name":"entity.name.function.tcl"}},"match":"(?<=^|\\\\{)\\\\s*(proc)\\\\s+(\\\\S+)"},{"captures":{"1":{"name":"keyword.other.tcl"}},"match":"(?<=^|[;\\\\[{])\\\\s*(after|append|array|auto_execok|auto_import|auto_load|auto_mkindex|auto_mkindex_old|auto_qualify|auto_reset|bgerror|binary|cd|clock|close|concat|dde|encoding|eof|error|eval|exec|expr|fblocked|fconfigure|fcopy|file|fileevent|filename|flush|format|gets|glob|global|history|http|incr|info|interp|join|lappend|library|lindex|linsert|list|llength|load|lrange|lreplace|lsearch|lset|lsort|memory|msgcat|namespace|open|package|parray|pid|pkg::create|pkg_mkIndex|proc|puts|pwd|re_syntax|read|registry|rename|resource|scan|seek|set|socket|SafeBase|source|split|string|subst|Tcl|tcl_endOfWord|tcl_findLibrary|tcl_startOfNextWord|tcl_startOfPreviousWord|tcl_wordBreakAfter|tcl_wordBreakBefore|tcltest|tclvars|tell|time|trace|unknown|unset|update|uplevel|upvar|variable|vwait)\\\\b"},{"begin":"(?<=^|[;\\\\[{])\\\\s*(reg(?:exp|sub))\\\\b\\\\s*","beginCaptures":{"1":{"name":"keyword.other.tcl"}},"end":"[]\\\\n;]","patterns":[{"match":"\\\\\\\\(?:.|\\\\n)","name":"constant.character.escape.tcl"},{"match":"-\\\\w+\\\\s*"},{"applyEndPatternLast":1,"begin":"--\\\\s*","end":"","patterns":[{"include":"#regexp"}]},{"include":"#regexp"}]},{"include":"#escape"},{"include":"#variable"},{"include":"#operator"},{"include":"#numeric"},{"begin":"\\"","beginCaptures":{"0":{"name":"punctuation.definition.string.begin.tcl"}},"end":"\\"","endCaptures":{"0":{"name":"punctuation.definition.string.end.tcl"}},"name":"string.quoted.double.tcl","patterns":[{"include":"#escape"},{"include":"#variable"},{"include":"#embedded"}]}],"repository":{"bare-string":{"begin":"(?:^|(?<=\\\\s))\\"","end":"\\"([^]\\\\s]*)","endCaptures":{"1":{"name":"invalid.illegal.tcl"}},"patterns":[{"include":"#escape"},{"include":"#variable"}]},"braces":{"begin":"(?:^|(?<=\\\\s))\\\\{","end":"}([^]\\\\s]*)","endCaptures":{"1":{"name":"invalid.illegal.tcl"}},"patterns":[{"match":"\\\\\\\\[\\\\n{}]","name":"constant.character.escape.tcl"},{"include":"#inner-braces"}]},"embedded":{"begin":"\\\\[","beginCaptures":{"0":{"name":"punctuation.section.embedded.begin.tcl"}},"end":"]","endCaptures":{"0":{"name":"punctuation.section.embedded.end.tcl"}},"name":"source.tcl.embedded","patterns":[{"include":"source.tcl"}]},"escape":{"match":"\\\\\\\\(\\\\d{1,3}|x\\\\h+|u\\\\h{1,4}|.|\\\\n)","name":"constant.character.escape.tcl"},"inner-braces":{"begin":"\\\\{","end":"}","patterns":[{"match":"\\\\\\\\[\\\\n{}]","name":"constant.character.escape.tcl"},{"include":"#inner-braces"}]},"numeric":{"match":"(?<![A-Za-z])([-+]?([0-9]*\\\\.)?[0-9]+f?)(?![.A-Za-z])","name":"constant.numeric.tcl"},"operator":{"match":"(?<=[ \\\\d])([-+~]|&{1,2}|\\\\|{1,2}|<{1,2}|>{1,2}|\\\\*{1,2}|[!%/]|<=|>=|={1,2}|!=|\\\\^)(?=[ \\\\d])","name":"keyword.operator.tcl"},"regexp":{"begin":"(?=\\\\S)(?![]\\\\n;])","end":"(?=[]\\\\n;])","patterns":[{"begin":"(?=[^\\\\t\\\\n ;])","end":"(?=[\\\\t\\\\n ;])","name":"string.regexp.tcl","patterns":[{"include":"#braces"},{"include":"#bare-string"},{"include":"#escape"},{"include":"#variable"}]},{"begin":"[\\\\t ]","end":"(?=[]\\\\n;])","patterns":[{"include":"#variable"},{"include":"#embedded"},{"include":"#escape"},{"include":"#braces"},{"include":"#string"}]}]},"string":{"applyEndPatternLast":1,"begin":"(?:^|(?<=\\\\s))(?=\\")","end":"","name":"string.quoted.double.tcl","patterns":[{"include":"#bare-string"}]},"variable":{"captures":{"1":{"name":"punctuation.definition.variable.tcl"}},"match":"(\\\\$)((?:[0-9A-Z_a-z]|::)+(\\\\([^)]+\\\\))?|\\\\{[^}]*})","name":"support.function.tcl"}},"scopeName":"source.tcl"}')),n=[e];export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Gleam","fileTypes":["gleam"],"name":"gleam","patterns":[{"include":"#comments"},{"include":"#keywords"},{"include":"#strings"},{"include":"#constant"},{"include":"#entity"},{"include":"#discards"}],"repository":{"binary_number":{"match":"\\\\b0[Bb][01_]*\\\\b","name":"constant.numeric.binary.gleam","patterns":[]},"comments":{"patterns":[{"match":"//.*","name":"comment.line.gleam"}]},"constant":{"patterns":[{"include":"#binary_number"},{"include":"#octal_number"},{"include":"#hexadecimal_number"},{"include":"#decimal_number"},{"match":"\\\\p{upper}\\\\p{alnum}*","name":"entity.name.type.gleam"}]},"decimal_number":{"match":"\\\\b([0-9][0-9_]*)(\\\\.([0-9_]*)?(e-?[0-9]+)?)?\\\\b","name":"constant.numeric.decimal.gleam","patterns":[]},"discards":{"match":"\\\\b_\\\\p{word}+{0,1}\\\\b","name":"comment.unused.gleam"},"entity":{"patterns":[{"begin":"\\\\b(\\\\p{lower}\\\\p{word}*)\\\\b\\\\s*\\\\(","captures":{"1":{"name":"entity.name.function.gleam"}},"end":"\\\\)","patterns":[{"include":"$self"}]},{"match":"\\\\b(\\\\p{lower}\\\\p{word}*):\\\\s","name":"variable.parameter.gleam"},{"match":"\\\\b(\\\\p{lower}\\\\p{word}*):","name":"entity.name.namespace.gleam"}]},"hexadecimal_number":{"match":"\\\\b0[Xx][_\\\\h]+\\\\b","name":"constant.numeric.hexadecimal.gleam","patterns":[]},"keywords":{"patterns":[{"match":"\\\\b(as|use|case|if|fn|import|let|assert|pub|type|opaque|const|todo|panic|else|echo)\\\\b","name":"keyword.control.gleam"},{"match":"(<-|->)","name":"keyword.operator.arrow.gleam"},{"match":"\\\\|>","name":"keyword.operator.pipe.gleam"},{"match":"\\\\.\\\\.","name":"keyword.operator.splat.gleam"},{"match":"([!=]=)","name":"keyword.operator.comparison.gleam"},{"match":"([<>]=?\\\\.)","name":"keyword.operator.comparison.float.gleam"},{"match":"(<=|>=|[<>])","name":"keyword.operator.comparison.int.gleam"},{"match":"(&&|\\\\|\\\\|)","name":"keyword.operator.logical.gleam"},{"match":"<>","name":"keyword.operator.string.gleam"},{"match":"\\\\|","name":"keyword.operator.other.gleam"},{"match":"([-*+/]\\\\.)","name":"keyword.operator.arithmetic.float.gleam"},{"match":"([-%*+/])","name":"keyword.operator.arithmetic.int.gleam"},{"match":"=","name":"keyword.operator.assignment.gleam"}]},"octal_number":{"match":"\\\\b0[Oo][0-7_]*\\\\b","name":"constant.numeric.octal.gleam","patterns":[]},"strings":{"begin":"\\"","end":"\\"","name":"string.quoted.double.gleam","patterns":[{"match":"\\\\\\\\.","name":"constant.character.escape.gleam"}]}},"scopeName":"source.gleam"}')),a=[e];export{a as default};

View file

@ -1 +0,0 @@
import{Y as a}from"./chunk-1ehq66yp.js";import"./chunk-xg9nsz1a.js";import"./chunk-z868q2s0.js";import"./chunk-gf0502ds.js";export{a as default};

View file

@ -1 +0,0 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"QML Directory","name":"qmldir","patterns":[{"include":"#comment"},{"include":"#keywords"},{"include":"#version"},{"include":"#names"}],"repository":{"comment":{"patterns":[{"begin":"#","end":"$","name":"comment.line.number-sign.qmldir"}]},"file-name":{"patterns":[{"match":"\\\\b\\\\w+\\\\.(qmltypes|qml|js)\\\\b","name":"string.unquoted.qmldir"}]},"identifier":{"patterns":[{"match":"\\\\b\\\\w+\\\\b","name":"variable.parameter.qmldir"}]},"keywords":{"patterns":[{"match":"\\\\b(module|singleton|internal|plugin|classname|typeinfo|depends|designersupported)\\\\b","name":"keyword.other.qmldir"}]},"module-name":{"patterns":[{"match":"\\\\b[A-Z]\\\\w*\\\\b","name":"entity.name.type.qmldir"}]},"names":{"patterns":[{"include":"#file-name"},{"include":"#module-name"},{"include":"#identifier"}]},"version":{"patterns":[{"match":"\\\\b\\\\d+\\\\.\\\\d+\\\\b","name":"constant.numeric.qml"}]}},"scopeName":"source.qmldir"}')),n=[e];export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{G as n}from"./chunk-z9jws129.js";import{N as t}from"./chunk-71s03bbh.js";import{Y as e}from"./chunk-1ehq66yp.js";import"./chunk-xg9nsz1a.js";import"./chunk-z868q2s0.js";import"./chunk-gf0502ds.js";var a=Object.freeze(JSON.parse('{"displayName":"Edge","injections":{"text.html.edge - (meta.embedded | meta.tag | comment.block.edge), L:(text.html.edge meta.tag - (comment.block.edge | meta.embedded.block.edge)), L:(source.ts.embedded.html - (comment.block.edge | meta.embedded.block.edge))":{"patterns":[{"include":"#comment"},{"include":"#escapedMustache"},{"include":"#safeMustache"},{"include":"#mustache"},{"include":"#nonSeekableTag"},{"include":"#tag"}]}},"name":"edge","patterns":[{"include":"text.html.basic"},{"include":"text.html.derivative"}],"repository":{"comment":{"begin":"\\\\{\\\\{--","beginCaptures":{"0":{"name":"punctuation.definition.comment.begin.edge"}},"end":"--}}","endCaptures":{"0":{"name":"punctuation.definition.comment.end.edge"}},"name":"comment.block"},"escapedMustache":{"begin":"@\\\\{\\\\{","beginCaptures":{"0":{"name":"punctuation.definition.comment.begin.edge"}},"end":"}}","endCaptures":{"0":{"name":"punctuation.definition.comment.end.edge"}},"name":"comment.block"},"mustache":{"begin":"\\\\{\\\\{","beginCaptures":{"0":{"name":"punctuation.mustache.begin"}},"end":"}}","endCaptures":{"0":{"name":"punctuation.mustache.end"}},"name":"meta.embedded.block.javascript","patterns":[{"include":"source.ts#expression"}]},"nonSeekableTag":{"captures":{"2":{"name":"support.function.edge"}},"match":"^(\\\\s*)((@{1,2})(!)?([.A-Z_a-z]+))(~)?$","name":"meta.embedded.block.javascript","patterns":[{"include":"source.ts#expression"}]},"safeMustache":{"begin":"\\\\{\\\\{\\\\{","beginCaptures":{"0":{"name":"punctuation.mustache.begin"}},"end":"}}}","endCaptures":{"0":{"name":"punctuation.mustache.end"}},"name":"meta.embedded.block.javascript","patterns":[{"include":"source.ts#expression"}]},"tag":{"begin":"^(\\\\s*)((@{1,2})(!)?([.A-Z_a-z]+)(\\\\s{0,2}))(\\\\()","beginCaptures":{"2":{"name":"support.function.edge"},"7":{"name":"punctuation.paren.open"}},"end":"\\\\)","endCaptures":{"0":{"name":"punctuation.paren.close"}},"name":"meta.embedded.block.javascript","patterns":[{"include":"source.ts#expression"}]}},"scopeName":"text.html.edge","embeddedLangs":["typescript","html","html-derivative"]}')),i=[...t,...e,...n,a];export{i as default};

View file

@ -1 +0,0 @@
import"./chunk-gf0502ds.js";var t=Object.freeze(JSON.parse('{"displayName":"TSV","fileTypes":["tsv","tab"],"name":"tsv","patterns":[{"captures":{"1":{"name":"rainbow1"},"2":{"name":"keyword.rainbow2"},"3":{"name":"entity.name.function.rainbow3"},"4":{"name":"comment.rainbow4"},"5":{"name":"string.rainbow5"},"6":{"name":"variable.parameter.rainbow6"},"7":{"name":"constant.numeric.rainbow7"},"8":{"name":"entity.name.type.rainbow8"},"9":{"name":"markup.bold.rainbow9"},"10":{"name":"invalid.rainbow10"}},"match":"([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)","name":"rainbowgroup"}],"scopeName":"text.tsv"}')),a=[t];export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{k as a}from"./chunk-pce8yxd3.js";import"./chunk-gf0502ds.js";export{a as default};

View file

@ -1 +0,0 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Rel","name":"rel","patterns":[{"include":"#strings"},{"include":"#comment"},{"include":"#single-line-comment-consuming-line-ending"},{"include":"#deprecated-temporary"},{"include":"#operators"},{"include":"#symbols"},{"include":"#keywords"},{"include":"#otherkeywords"},{"include":"#types"},{"include":"#constants"}],"repository":{"comment":{"patterns":[{"begin":"/\\\\*\\\\*(?!/)","beginCaptures":{"0":{"name":"punctuation.definition.comment.rel"}},"end":"\\\\*/","endCaptures":{"0":{"name":"punctuation.definition.comment.rel"}},"name":"comment.block.documentation.rel","patterns":[{"include":"#docblock"}]},{"begin":"(/\\\\*)(?:\\\\s*((@)internal)(?=\\\\s|(\\\\*/)))?","beginCaptures":{"1":{"name":"punctuation.definition.comment.rel"},"2":{"name":"storage.type.internaldeclaration.rel"},"3":{"name":"punctuation.decorator.internaldeclaration.rel"}},"end":"\\\\*/","endCaptures":{"0":{"name":"punctuation.definition.comment.rel"}},"name":"comment.block.rel"},{"begin":"doc\\"\\"\\"","end":"\\"\\"\\"","name":"comment.block.documentation.rel"},{"begin":"(^[\\\\t ]+)?((//)(?:\\\\s*((@)internal)(?=\\\\s|$))?)","beginCaptures":{"1":{"name":"punctuation.whitespace.comment.leading.rel"},"2":{"name":"comment.line.double-slash.rel"},"3":{"name":"punctuation.definition.comment.rel"},"4":{"name":"storage.type.internaldeclaration.rel"},"5":{"name":"punctuation.decorator.internaldeclaration.rel"}},"contentName":"comment.line.double-slash.rel","end":"(?=$)"}]},"constants":{"patterns":[{"match":"\\\\b((true|false))\\\\b","name":"constant.language.rel"}]},"deprecated-temporary":{"patterns":[{"match":"@inspect","name":"keyword.other.rel"}]},"keywords":{"patterns":[{"match":"\\\\b((def|entity|bound|include|ic|forall|exists|[∀∃]|return|module|^end))\\\\b|(((<)?\\\\|(>)?)|[∀∃])","name":"keyword.control.rel"}]},"operators":{"patterns":[{"match":"\\\\b((if|then|else|and|or|not|eq|neq|lt|lt_eq|gt|gt_eq))\\\\b|([-%*+/=^÷]|!=|[<≠]|<=|[>≤]|>=|[\\\\&≥])|\\\\s+(end)","name":"keyword.other.rel"}]},"otherkeywords":{"patterns":[{"match":"\\\\s*(@inline)\\\\s*|\\\\s*(@auto_number)\\\\s*|\\\\s*(function)\\\\s|\\\\b((implies|select|from|∈|where|for|in))\\\\b|(((<)?\\\\|(>)?)|∈)","name":"keyword.other.rel"}]},"single-line-comment-consuming-line-ending":{"begin":"(^[\\\\t ]+)?((//)(?:\\\\s*((@)internal)(?=\\\\s|$))?)","beginCaptures":{"1":{"name":"punctuation.whitespace.comment.leading.rel"},"2":{"name":"comment.line.double-slash.rel"},"3":{"name":"punctuation.definition.comment.rel"},"4":{"name":"storage.type.internaldeclaration.rel"},"5":{"name":"punctuation.decorator.internaldeclaration.rel"}},"contentName":"comment.line.double-slash.rel","end":"(?=^)"},"strings":{"begin":"\\"","end":"\\"","name":"string.quoted.double.rel","patterns":[{"match":"\\\\\\\\.","name":"constant.character.escape.rel"}]},"symbols":{"patterns":[{"match":"(:[$\\\\[_[:alpha:]](]|[$_[:alnum:]]*))","name":"variable.parameter.rel"}]},"types":{"patterns":[{"match":"\\\\b((Symbol|Char|Bool|Rational|FixedDecimal|Float16|Float32|Float64|Int8|Int16|Int32|Int64|Int128|UInt8|UInt16|UInt32|UInt64|UInt128|Date|DateTime|Day|Week|Month|Year|Nanosecond|Microsecond|Millisecond|Second|Minute|Hour|FilePos|HashValue|AutoNumberValue))\\\\b","name":"entity.name.type.rel"}]}},"scopeName":"source.rel"}')),n=[e];export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{s as a}from"./chunk-crmnbecm.js";import"./chunk-0gpjqeyh.js";import"./chunk-nkw6kj41.js";import"./chunk-71s03bbh.js";import"./chunk-z868q2s0.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Berry","name":"berry","patterns":[{"include":"#controls"},{"include":"#strings"},{"include":"#comment-block"},{"include":"#comments"},{"include":"#keywords"},{"include":"#function"},{"include":"#member"},{"include":"#identifier"},{"include":"#number"},{"include":"#operator"}],"repository":{"comment-block":{"begin":"#-","end":"-#","name":"comment.berry","patterns":[{}]},"comments":{"begin":"#","end":"\\\\n","name":"comment.line.berry","patterns":[{}]},"controls":{"patterns":[{"match":"\\\\b(if|elif|else|for|while|do|end|break|continue|return|try|except|raise)\\\\b","name":"keyword.control.berry"}]},"function":{"patterns":[{"match":"\\\\b([A-Z_a-z][0-9A-Z_a-z]*(?=\\\\s*\\\\())","name":"entity.name.function.berry"}]},"identifier":{"patterns":[{"match":"\\\\b[A-Z_a-z]\\\\w+\\\\b","name":"identifier.berry"}]},"keywords":{"patterns":[{"match":"\\\\b(var|static|def|class|true|false|nil|self|super|import|as|_class)\\\\b","name":"keyword.berry"}]},"member":{"patterns":[{"captures":{"0":{"name":"entity.other.attribute-name.berry"}},"match":"\\\\.([A-Z_a-z][0-9A-Z_a-z]*)"}]},"number":{"patterns":[{"match":"0x\\\\h+|\\\\d+|(\\\\d+\\\\.?|\\\\.\\\\d)\\\\d*([Ee][-+]?\\\\d+)?","name":"constant.numeric.berry"}]},"operator":{"patterns":[{"match":"[-\\\\]!%\\\\&(-+./:<=>\\\\[^|~]","name":"keyword.operator.berry"}]},"strings":{"patterns":[{"begin":"f(?=[\\"\'])","patterns":[{"begin":"\\"","end":"\\"","name":"string.quoted.other.berry","patterns":[{"match":"(\\\\\\\\x\\\\h{2})|(\\\\\\\\[0-7]{3})|(\\\\\\\\\\\\\\\\)|(\\\\\\\\\\")|(\\\\\\\\\')|(\\\\\\\\a)|(\\\\\\\\b)|(\\\\\\\\f)|(\\\\\\\\n)|(\\\\\\\\r)|(\\\\\\\\t)|(\\\\\\\\v)","name":"constant.character.escape.berry"},{"match":"\\\\{\\\\{[^}]*}}","name":"string.quoted.other.berry"},{"begin":"\\\\{","end":"}","name":"keyword.other.unit.berry","patterns":[{"include":"#keywords"},{"include":"#numbers"},{"include":"#identifier"},{"include":"#operator"},{"include":"#member"},{"include":"#function"}]}]},{"begin":"\'","end":"\'","name":"string.quoted.other.berry","patterns":[{"match":"(\\\\\\\\x\\\\h{2})|(\\\\\\\\[0-7]{3})|(\\\\\\\\\\\\\\\\)|(\\\\\\\\\\")|(\\\\\\\\\')|(\\\\\\\\a)|(\\\\\\\\b)|(\\\\\\\\f)|(\\\\\\\\n)|(\\\\\\\\r)|(\\\\\\\\t)|(\\\\\\\\v)","name":"constant.character.escape.berry"},{"match":"\\\\{\\\\{[^}]*}}","name":"string.quoted.other.berry"},{"begin":"\\\\{","end":"}","name":"keyword.other.unit.berry","patterns":[{"include":"#keywords"},{"include":"#numbers"},{"include":"#identifier"},{"include":"#operator"},{"include":"#member"},{"include":"#function"}]}]}],"while":"\\\\G|^[\\\\t ]*(?=[\\"\'])"},{"begin":"([\\"\'])","end":"\\\\1","name":"string.quoted.double.berry","patterns":[{"match":"(\\\\\\\\x\\\\h{2})|(\\\\\\\\[0-7]{3})|(\\\\\\\\\\\\\\\\)|(\\\\\\\\\\")|(\\\\\\\\\')|(\\\\\\\\a)|(\\\\\\\\b)|(\\\\\\\\f)|(\\\\\\\\n)|(\\\\\\\\r)|(\\\\\\\\t)|(\\\\\\\\v)","name":"constant.character.escape.berry"}]}]}},"scopeName":"source.berry","aliases":["be"]}')),r=[e];export{r as default};

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show more