@bud.sh/app 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7510,7 +7510,7 @@ var logWithLevel$1 = (level) => (...message) => {
7510
7510
  return void_$2;
7511
7511
  });
7512
7512
  };
7513
- var colors = {
7513
+ var colors$1 = {
7514
7514
  bold: "1",
7515
7515
  red: "31",
7516
7516
  green: "32",
@@ -7522,7 +7522,7 @@ var colors = {
7522
7522
  black: "30",
7523
7523
  bgBrightRed: "101"
7524
7524
  };
7525
- colors.gray, colors.blue, colors.green, colors.yellow, colors.red, colors.bgBrightRed, colors.black;
7525
+ colors$1.gray, colors$1.blue, colors$1.green, colors$1.yellow, colors$1.red, colors$1.bgBrightRed, colors$1.black;
7526
7526
  var defaultDateFormat = (date) => `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${date.getSeconds().toString().padStart(2, "0")}.${date.getMilliseconds().toString().padStart(3, "0")}`;
7527
7527
  /** @internal */
7528
7528
  var defaultLogger = /*#__PURE__*/ loggerMake(({ cause, date, fiber, logLevel, message }) => {
@@ -28628,6 +28628,113 @@ var BudLogoSchema = createSchema((value, context) => {
28628
28628
  return fail(logoMessage, context.path);
28629
28629
  });
28630
28630
  //#endregion
28631
+ //#region ../project/src/lib/theme.ts
28632
+ /**
28633
+ * Bud's colors and shadows a theme may set, as `--bud-<name>` in its styles. Everything else
28634
+ * Bud derives from them.
28635
+ */
28636
+ var THEME_TOKENS = Object.freeze([
28637
+ "background",
28638
+ "shell",
28639
+ "main",
28640
+ "canvas",
28641
+ "panel",
28642
+ "board",
28643
+ "editor",
28644
+ "editor-tabs",
28645
+ "foreground",
28646
+ "muted",
28647
+ "primary",
28648
+ "primary-hover",
28649
+ "primary-foreground",
28650
+ "border",
28651
+ "tab-divider",
28652
+ "hover",
28653
+ "selected",
28654
+ "control",
28655
+ "control-active",
28656
+ "control-selected",
28657
+ "card",
28658
+ "menu",
28659
+ "menu-hover",
28660
+ "card-frame",
28661
+ "card-surface",
28662
+ "card-border",
28663
+ "card-frame-border",
28664
+ "card-badge",
28665
+ "overlay-shadow",
28666
+ "tooltip",
28667
+ "board-control",
28668
+ "board-control-hover",
28669
+ "board-card",
28670
+ "control-elevation",
28671
+ "board-elevation",
28672
+ "board-card-elevation",
28673
+ "card-elevation",
28674
+ "board-card-lift",
28675
+ "frame-control",
28676
+ "modal-elevation",
28677
+ "segment-elevation",
28678
+ "control-open-elevation",
28679
+ "board-segment",
28680
+ "scrollbar",
28681
+ "focus",
28682
+ "scrollbar-hover",
28683
+ "tooltip-border",
28684
+ "tooltip-shadow"
28685
+ ]);
28686
+ var themeMessage = `theme must be { light, dark }, each mapping Bud's tokens (${THEME_TOKENS.slice(0, 3).join(", ")}, …) to CSS colors or shadows.`;
28687
+ function cssValue(value) {
28688
+ if (typeof value !== "string") return null;
28689
+ let trimmed = value.trim();
28690
+ if (!trimmed || trimmed.length > 300) return null;
28691
+ if (!/^[#a-zA-Z0-9(),.%\s/+-]+$/.test(trimmed) || /url\s*\(/i.test(trimmed)) return null;
28692
+ return trimmed;
28693
+ }
28694
+ function colors(value) {
28695
+ if (value === void 0) return {};
28696
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
28697
+ let result = {};
28698
+ for (let [name, raw] of Object.entries(value)) {
28699
+ let checked = cssValue(raw);
28700
+ if (!THEME_TOKENS.includes(name) || checked === null) return null;
28701
+ result[name] = checked;
28702
+ }
28703
+ return Object.freeze(result);
28704
+ }
28705
+ /** A theme in its one resolved form; Bud's own colors when absent. */
28706
+ var BudThemeSchema = createSchema((value, context) => {
28707
+ if (value === void 0) return { value: {
28708
+ light: {},
28709
+ dark: {}
28710
+ } };
28711
+ if (!value || typeof value !== "object" || Array.isArray(value)) return fail(themeMessage, context.path);
28712
+ let { light, dark, ...rest } = value;
28713
+ let resolved = {
28714
+ light: colors(light),
28715
+ dark: colors(dark)
28716
+ };
28717
+ if (Object.keys(rest).length || !resolved.light || !resolved.dark) return fail(themeMessage, context.path);
28718
+ return { value: {
28719
+ light: resolved.light,
28720
+ dark: resolved.dark
28721
+ } };
28722
+ });
28723
+ /**
28724
+ * The theme as styles that follow Bud's own, so its tokens win in each color scheme.
28725
+ * @param theme - The resolved theme.
28726
+ * @returns A `<style>` element, or an empty string for Bud's own colors.
28727
+ */
28728
+ function themeStyle(theme) {
28729
+ let block = (selector, values) => {
28730
+ let entries = Object.entries(values);
28731
+ if (!entries.length) return "";
28732
+ return `${selector}{${entries.map(([name, value]) => `--bud-${name}:${value};`).join("")}}`;
28733
+ };
28734
+ let css = block(":root:not([data-theme='dark'])", theme.light) + block(":root[data-theme='dark']", theme.dark);
28735
+ return css ? `<style data-bud-theme>${css}</style>` : "";
28736
+ }
28737
+ //#endregion
28631
28738
  //#region ../project/src/lib/branches.ts
28632
28739
  var message$1 = "branches must be { main?, build?: { install?, build?, serve? } } with a branch name and nonempty shell commands.";
28633
28740
  function branch(value) {
@@ -28976,6 +29083,7 @@ var ConfigFields = check(section("Bud config must export an object.", {
28976
29083
  previews: any(),
28977
29084
  files: any(),
28978
29085
  logo: any(),
29086
+ theme: any(),
28979
29087
  picker: any(),
28980
29088
  branches: any(),
28981
29089
  flows: any()
@@ -29051,6 +29159,7 @@ var BudConfigSchema = delegate(check(delegate(check(delegate(check(delegate(Conf
29051
29159
  previews: parseConfig(BudPreviewsSchema, config.previews),
29052
29160
  files: parseConfig(BudFilesSchema, config.files),
29053
29161
  logo: parseConfig(BudLogoSchema, config.logo),
29162
+ theme: parseConfig(BudThemeSchema, config.theme),
29054
29163
  picker: parseConfig(BudPickerSchema, config.picker),
29055
29164
  branches: parseConfig(BudBranchesSchema, config.branches)
29056
29165
  }));
@@ -33491,4 +33600,4 @@ function branchPreviewsLayer(project, options) {
33491
33600
  }));
33492
33601
  }
33493
33602
  //#endregion
33494
- export { shutdown$1 as $, makeUnsafe$4 as $n, provideService as $t, debounce as A, uninterruptibleMask as An, clockWith as At, merge as B, empty$2 as Bn, forkIn as Bt, RuntimePolicy as C, tapError as Cn, asSome as Ct, callback as D, try_ as Dn, catchIf as Dt, as as E, tryPromise as En, callback$1 as Et, fromPubSub as F, build as Fn, filterOrFail as Ft, makeUnsafe as G, provide$2 as Gn, mapError$2 as Gt, tap as H, makeMemoMapUnsafe as Hn, gen as Ht, ignore as I, buildWithMemoMap as In, flatMap$1 as It, shutdown as J, succeedContext as Jn, orDie as Jt, offer as K, provideMerge as Kn, match as Kt, make$7 as L, effect as Ln, flatten$1 as Lt, empty as M, withFiber as Mn, die as Mt, filter as N, yieldNow as Nn, ensuring as Nt, changes as O, undefined_$2 as On, catchTag as Ot, fromEffect as P, currentTimeMillis as Pn, fail$4 as Pt, publishAll as Q, forkUnsafe as Qn, provideContext as Qt, mapEffect as R, effectContext as Rn, forEach$1 as Rt, ProcessRunner as S, tap$1 as Sn, as$1 as St, FileSystem as T, timeoutOrElse as Tn, cached as Tt, unwrap as U, merge$2 as Un, ignore$2 as Ut, runForEach as V, isLayer as Vn, forkScoped as Vt, make$8 as W, mergeAll$1 as Wn, map$2 as Wt, take as X, unwrap$4 as Xn, promise as Xt, sliding as Y, sync$1 as Yn, orElseSucceed as Yt, publish as Z, close as Zn, provide as Zt, resolveStorage as _, sleep as _n, acquireRelease as _t, followCapture as a, runForkWith as an, scopeRemoveFinalizerUnsafe as ar, ArraySchema as at, readText as b, suspend$2 as bn, all$1 as bt, previewsLayer as c, runPromiseExitWith as cn, getOption as cr, Struct as ct, gitLayer as d, runSyncExit as dn, getOrUndefined$1 as dr, decodeEffect as dt, result as en, _await as er, sliding$1 as et, Project as f, runSyncExitWith as fn, isNone as fr, isMaxLength as ft, resolveScreenRoutes as g, serviceOption as gn, bytes as gt, defaultScreens as h, scoped as hn, TaggedError as hr, optional$1 as ht, projectFlows as i, runFork as in, void_$1 as ir, runIn as it, drop as j, void_ as jn, context as jt, concat as k, uninterruptible as kn, catch_$1 as kt, PreviewSession as l, runPromiseWith as ln, make$25 as lr, Undefined as lt, projectModuleFile as m, scope as mn, some as mr, isPattern as mt, branchIndexName as n, runCallback as nn, make$23 as nr, await_ as nt, startBranchBuild as o, runPromise as on, Service as or, Record as ot, createProjectContext as p, runSyncWith as pn, none as pr, isNonEmpty as pt, offerUnsafe as q, succeed$3 as qn, option as qt, branchPreviewsLayer as r, runCallbackWith as rn, succeed$4 as rr, interrupt as rt, Previews as s, runPromiseExit as sn, add as sr, String$1 as st, BranchPreviews as t, retry as tn, doneUnsafe as tr, unbounded$1 as tt, Git as u, runSync$1 as un, getOrNull as ur, Union as ut, LOGO_TYPES as v, succeed$2 as vn, acquireUseRelease as vt, Path$1 as w, timeoutOption as wn, asVoid as wt, writeTextAtomic as x, sync as xn, andThen as xt, nodeLayer as y, succeedNone as yn, addFinalizer as yt, mapError as z, effectDiscard as zn, forever as zt };
33603
+ export { publishAll as $, forkUnsafe as $n, provideContext as $t, concat as A, uninterruptible as An, catch_$1 as At, mapError as B, effectDiscard as Bn, forever as Bt, ProcessRunner as C, tap$1 as Cn, as$1 as Ct, as as D, tryPromise as Dn, callback$1 as Dt, FileSystem as E, timeoutOrElse as En, cached as Et, fromEffect as F, currentTimeMillis as Fn, fail$4 as Ft, make$8 as G, mergeAll$1 as Gn, map$2 as Gt, runForEach as H, isLayer as Hn, forkScoped as Ht, fromPubSub as I, build as In, filterOrFail as It, offerUnsafe as J, succeed$3 as Jn, option as Jt, makeUnsafe as K, provide$2 as Kn, mapError$2 as Kt, ignore as L, buildWithMemoMap as Ln, flatMap$1 as Lt, drop as M, void_ as Mn, context as Mt, empty as N, withFiber as Nn, die as Nt, callback as O, try_ as On, catchIf as Ot, filter as P, yieldNow as Pn, ensuring as Pt, publish as Q, close as Qn, provide as Qt, make$7 as R, effect as Rn, flatten$1 as Rt, writeTextAtomic as S, sync as Sn, andThen as St, Path$1 as T, timeoutOption as Tn, asVoid as Tt, tap as U, makeMemoMapUnsafe as Un, gen as Ut, merge as V, empty$2 as Vn, forkIn as Vt, unwrap as W, merge$2 as Wn, ignore$2 as Wt, sliding as X, sync$1 as Xn, orElseSucceed as Xt, shutdown as Y, succeedContext as Yn, orDie as Yt, take as Z, unwrap$4 as Zn, promise as Zt, resolveStorage as _, serviceOption as _n, bytes as _t, followCapture as a, runFork as an, void_$1 as ar, runIn as at, nodeLayer as b, succeedNone as bn, addFinalizer as bt, previewsLayer as c, runPromiseExit as cn, add as cr, String$1 as ct, gitLayer as d, runSync$1 as dn, getOrNull as dr, Union as dt, provideService as en, makeUnsafe$4 as er, shutdown$1 as et, Project as f, runSyncExit as fn, getOrUndefined$1 as fr, decodeEffect as ft, resolveScreenRoutes as g, scoped as gn, TaggedError as gr, optional$1 as gt, defaultScreens as h, scope as hn, some as hr, isPattern as ht, projectFlows as i, runCallbackWith as in, succeed$4 as ir, interrupt as it, debounce as j, uninterruptibleMask as jn, clockWith as jt, changes as k, undefined_$2 as kn, catchTag as kt, PreviewSession as l, runPromiseExitWith as ln, getOption as lr, Struct as lt, projectModuleFile as m, runSyncWith as mn, none as mr, isNonEmpty as mt, branchIndexName as n, retry as nn, doneUnsafe as nr, unbounded$1 as nt, startBranchBuild as o, runForkWith as on, scopeRemoveFinalizerUnsafe as or, ArraySchema as ot, createProjectContext as p, runSyncExitWith as pn, isNone as pr, isMaxLength as pt, offer as q, provideMerge as qn, match as qt, branchPreviewsLayer as r, runCallback as rn, make$23 as rr, await_ as rt, Previews as s, runPromise as sn, Service as sr, Record as st, BranchPreviews as t, result as tn, _await as tr, sliding$1 as tt, Git as u, runPromiseWith as un, make$25 as ur, Undefined as ut, themeStyle as v, sleep as vn, acquireRelease as vt, RuntimePolicy as w, tapError as wn, asSome as wt, readText as x, suspend$2 as xn, all$1 as xt, LOGO_TYPES as y, succeed$2 as yn, acquireUseRelease as yt, mapEffect as z, effectContext as zn, forEach$1 as zt };
@@ -1,5 +1,5 @@
1
- import { Dn as try_, En as tryPromise, Et as callback, Gt as mapError, Ht as gen, It as flatMap, Kt as match, Mt as die, Nt as ensuring, Pt as fail$1, Wt as map, Xt as promise, _t as acquireRelease, g as resolveScreenRoutes, h as defaultScreens, hn as scoped, hr as TaggedError, jn as void_, s as Previews, t as BranchPreviews, u as Git, v as LOGO_TYPES, xn as sync, xt as andThen } from "./branch-previews-C_TVt_HQ.js";
2
- import { C as selected$1, I as WorkError, L as ScreenModules, O as AdapterRegistry, S as ready, T as LiveChannel, V as taskDesignModuleId, a as FileMutations, b as read, c as FileReview, f as Files, g as StoreActivity, h as ReviewActionError, m as FilesInputError, r as FileSaves, t as FileReviewActions, u as FileSearch, w as validate, x as readWorkspace, y as inspect } from "./server-DUBjmaBw.js";
1
+ import { Dn as tryPromise, Dt as callback, Ft as fail$1, Gt as map, Kt as mapError, Lt as flatMap, Mn as void_, Nt as die, On as try_, Pt as ensuring, Sn as sync, St as andThen, Ut as gen, Zt as promise, g as resolveScreenRoutes, gn as scoped, gr as TaggedError, h as defaultScreens, qt as match, s as Previews, t as BranchPreviews, u as Git, v as themeStyle, vt as acquireRelease, y as LOGO_TYPES } from "./branch-previews-BryeA_kA.js";
2
+ import { C as selected$1, I as WorkError, L as ScreenModules, O as AdapterRegistry, S as ready, T as LiveChannel, V as taskDesignModuleId, a as FileMutations, b as read, c as FileReview, f as Files, g as StoreActivity, h as ReviewActionError, m as FilesInputError, r as FileSaves, t as FileReviewActions, u as FileSearch, w as validate, x as readWorkspace, y as inspect } from "./server-DN5uwE4k.js";
3
3
  import { A as parseThreadReplyInput, D as parseThreadId, Dt as parseFileSearchQuery, E as parseThreadFilter, Ht as parseFilePath, N as parseThreadStatusInput, O as parseThreadInput, Rt as parseFileIndexQuery, St as parseReviewSourceQuery, X as parseReviewActionIntent, Xt as parseElementAnchor, Y as parseReviewActionApply, Yt as MAX_CANVAS_Y, _ as taskRoutes, _t as parseReviewHistoryQuery, an as parseWorkDetail, at as parseMutationIntent, cn as parseWorkMutationResult, en as parseSectionData, fn as parseWorkSync, g as pageRoutes, h as fileRoutes, ht as parseReviewDiffQuery, i as routes, in as parseWorkCreate, it as parseMutationApply, j as parseThreadSnapshot, k as parseThreadLinkInput, mn as parseWorkUpdate, pn as parseWorkSyncResult, pt as parseReviewComparison, rt as maxFileSaveBytes, sn as parseWorkItemRef, tn as parseWorkActionInput, tt as parseFileSaveRequest, un as parseWorkQuery, vn as parseMessageAuthor, w as parseThread } from "./events-6z5v7Uca.js";
4
4
  import { $ as openShellTab, B as parseTaskDesign, Bt as Button, Cn as Text, J as FieldCardContent, Q as initialShellTabs, Rt as Loader, Sn as writePreference, X as activeTab, Y as FieldCardHeader, Z as closeShellTab, _ as requestComments, _n as LiveStatus, _t as taskHref, at as tabsCookieValue, et as parseShellTabs, gt as selectedTask, ht as readConversationLocation, it as tabsCookieName, lt as conversationDestination, mn as ShellTabBar, n as unavailableComments, nt as stepShellTab, ot as visitShellTab, pt as legacyConversationHref, q as FieldCard, r as followThreads, rt as tabHref, t as commentsUnavailable, tt as readTabsCookie, v as projectLive, xn as readPreference, xt as legacyFileHref, yn as AppShell } from "./comment-data-BuArfgcc.js";
5
5
  import { d as parsePreviewHash, f as parsePreviewId, l as parsePreviewBranch, m as parsePreviewViewport } from "./parsers-CsiSkwTT.js";
@@ -682,7 +682,7 @@ function createAppController(template, project, runtime) {
682
682
  let title = (conversation ? "Discussion" : screen.label).replace(/[&<>]/g, (character) => `&#${character.charCodeAt(0)};`);
683
683
  let logo = project?.config.logo;
684
684
  let shell = logo ? withLogoIcons(template, logo, (theme) => routes.logo.href({ theme })) : template;
685
- return new Response(shell.replace("<title>bud.sh</title>", () => `<title>${title} · bud.sh</title>`).replace("<!--app-html-->", () => content), { headers: { "Content-Type": "text/html; charset=utf-8" } });
685
+ return new Response(shell.replace("<title>bud.sh</title>", () => `<title>${title} · bud.sh</title>`).replace("</head>", () => project ? `${themeStyle(project.config.theme)}</head>` : "</head>").replace("<!--app-html-->", () => content), { headers: { "Content-Type": "text/html; charset=utf-8" } });
686
686
  }
687
687
  return createController(routes, { actions: {
688
688
  conversation({ params, request }) {
@@ -1,4 +1,4 @@
1
- import { $ as shutdown, $n as makeUnsafe, $t as provideService, A as debounce, An as uninterruptibleMask, At as clockWith, B as merge, Bn as empty, Bt as forkIn, C as RuntimePolicy, Cn as tapError, Ct as asSome, D as callback, Dn as try_, Dt as catchIf, E as as, En as tryPromise, F as fromPubSub, Fn as build, Ft as filterOrFail, Gn as provide$1, Gt as mapError, H as tap$1, Hn as makeMemoMapUnsafe, Ht as gen, I as ignore$1, In as buildWithMemoMap, It as flatMap, J as shutdown$1, Jt as orDie, K as offer, L as make$2, Ln as effect, Lt as flatten, M as empty$1, Mn as withFiber, Mt as die, N as filter, Nn as yieldNow, Nt as ensuring, On as undefined_$1, Ot as catchTag, Pn as currentTimeMillis, Pt as fail$1, Q as publishAll, Qn as forkUnsafe, Qt as provideContext, Rn as effectContext, Rt as forEach, Sn as tap, St as as$1, T as FileSystem, U as unwrap$1, Ut as ignore, V as runForEach, Vn as isLayer, Vt as forkScoped, W as make$3, Wn as mergeAll, Wt as map, X as take, Xn as unwrap, Xt as promise, Y as sliding$1, Yn as sync$1, Yt as orElseSucceed, Z as publish, Zn as close, _n as sleep, _t as acquireRelease, an as runForkWith, ar as scopeRemoveFinalizerUnsafe, bn as suspend, bt as all, cn as runPromiseExitWith, cr as getOption, dn as runSyncExit, dr as getOrUndefined, en as result, er as _await, et as sliding, fn as runSyncExitWith, fr as isNone, gn as serviceOption, gt as bytes$1, hn as scoped, hr as TaggedError, in as runFork, ir as void_, it as runIn, jn as void_$1, kn as uninterruptible, kt as catch_, ln as runPromiseWith, lr as make$1, m as projectModuleFile, mn as scope, mr as some, nn as runCallback, nr as make$4, nt as await_, on as runPromise, or as Service, pn as runSyncWith, pr as none, q as offerUnsafe, qn as succeed$1, qt as option, rn as runCallbackWith, rr as succeed$2, rt as interrupt, sn as runPromiseExit, sr as add, tr as doneUnsafe, tt as unbounded, u as Git, un as runSync, ur as getOrNull, vn as succeed, w as Path, wn as timeoutOption, wt as asVoid, x as writeTextAtomic, xn as sync, xt as andThen, yn as succeedNone, yt as addFinalizer, zn as effectDiscard, zt as forever } from "./branch-previews-C_TVt_HQ.js";
1
+ import { $ as publishAll, $n as forkUnsafe, $t as provideContext, An as uninterruptible, At as catch_, Bn as effectDiscard, Bt as forever, Cn as tap, Ct as as$1, D as as, Dn as tryPromise, E as FileSystem, Fn as currentTimeMillis, Ft as fail$1, G as make$3, Gn as mergeAll, Gt as map, H as runForEach, Hn as isLayer, Ht as forkScoped, I as fromPubSub, In as build, It as filterOrFail, J as offerUnsafe, Jn as succeed$1, Jt as option, Kn as provide$1, Kt as mapError, L as ignore$1, Ln as buildWithMemoMap, Lt as flatMap, Mn as void_$1, N as empty$1, Nn as withFiber, Nt as die, O as callback, On as try_, Ot as catchIf, P as filter, Pn as yieldNow, Pt as ensuring, Q as publish, Qn as close, R as make$2, Rn as effect, Rt as flatten, S as writeTextAtomic, Sn as sync, St as andThen, T as Path, Tn as timeoutOption, Tt as asVoid, U as tap$1, Un as makeMemoMapUnsafe, Ut as gen, V as merge, Vn as empty, Vt as forkIn, W as unwrap$1, Wt as ignore, X as sliding$1, Xn as sync$1, Xt as orElseSucceed, Y as shutdown$1, Yt as orDie, Z as take, Zn as unwrap, Zt as promise, _n as serviceOption, _t as bytes$1, an as runFork, ar as void_, at as runIn, bn as succeedNone, bt as addFinalizer, cn as runPromiseExit, cr as add, dn as runSync, dr as getOrNull, en as provideService, er as makeUnsafe, et as shutdown, fn as runSyncExit, fr as getOrUndefined, gn as scoped, gr as TaggedError, hn as scope, hr as some, in as runCallbackWith, ir as succeed$2, it as interrupt, j as debounce, jn as uninterruptibleMask, jt as clockWith, kn as undefined_$1, kt as catchTag, ln as runPromiseExitWith, lr as getOption, m as projectModuleFile, mn as runSyncWith, mr as none, nr as doneUnsafe, nt as unbounded, on as runForkWith, or as scopeRemoveFinalizerUnsafe, pn as runSyncExitWith, pr as isNone, q as offer, rn as runCallback, rr as make$4, rt as await_, sn as runPromise, sr as Service, tn as result, tr as _await, tt as sliding, u as Git, un as runPromiseWith, ur as make$1, vn as sleep, vt as acquireRelease, w as RuntimePolicy, wn as tapError, wt as asSome, xn as suspend, xt as all, yn as succeed, zn as effectContext, zt as forEach } from "./branch-previews-BryeA_kA.js";
2
2
  import { $ as parseReviewActionRecovery, A as parseThreadReplyInput, An as iconNames, At as filterFileEntries, Bt as isWithinDirectory, Cn as WorkValidationError, Ct as compileSearchPattern, Dn as record$1, Dt as parseFileSearchQuery, E as parseThreadFilter, En as parseWork, Et as searchPathMatches, Gt as list, Ht as parseFilePath, Jt as strict$1, Kt as parseContract, L as applyReviewSelection, N as parseThreadStatusInput, O as parseThreadInput, On as strict, Rt as parseFileIndexQuery, Sn as statusCategory, St as parseReviewSourceQuery, T as parseThreadCapabilities, Tn as nonempty, Ut as pathHierarchy, Vt as parentPath, Wt as integer, X as parseReviewActionIntent, Y as parseReviewActionApply, Zt as parseWorkWorkspace, _n as parseMessage, _t as parseReviewHistoryQuery, an as parseWorkDetail, at as parseMutationIntent, b as MAX_THREADS, bn as fieldByRole, cn as parseWorkMutationResult, dn as parseWorkSnapshot, dt as validateMutationSelection, en as parseSectionData, gn as valueByRole, hn as parseWorkValue, ht as parseReviewDiffQuery, i as routes, in as parseWorkCreate, it as parseMutationApply, j as parseThreadSnapshot, jt as orderFileEntries, k as parseThreadLinkInput, kt as classifyText, lt as parseRecovery, mn as parseWorkUpdate, on as parseWorkItem, pt as parseReviewComparison, qt as revision, r as parseLiveId, rn as parseWorkConnection, sn as parseWorkItemRef, t as RESYNC, tn as parseWorkActionInput, tt as parseFileSaveRequest, un as parseWorkQuery, ut as pathCollisionKey, vn as parseMessageAuthor, w as parseThread, wn as identifier, wt as matchFileText, xn as parseWorkSchema, zt as isProtectedPath } from "./events-6z5v7Uca.js";
3
3
  import { pathToFileURL } from "node:url";
4
4
  import { createHash, randomBytes, randomUUID } from "node:crypto";
@@ -1,5 +1,5 @@
1
- import { A as debounce, C as RuntimePolicy, Dn as try_, Dt as catchIf, E as as$1, Ft as filterOrFail, G as makeUnsafe, Gn as provide, Gt as mapError, Ht as gen, It as flatMap, Jn as succeedContext, Kn as provideMerge, L as make, Ln as effect, M as empty, Mt as die, Nt as ensuring, O as changes, Ot as catchTag, P as fromEffect, Pn as currentTimeMillis, Pt as fail, R as mapEffect, Rn as effectContext, Rt as forEach, S as ProcessRunner, Sn as tap, St as as, T as FileSystem, Tn as timeoutOrElse, Tt as cached, U as unwrap, Un as merge, Ut as ignore, V as runForEach, Vt as forkScoped, Wn as mergeAll, Wt as map, Xn as unwrap$1, Yt as orElseSucceed, at as ArraySchema, bn as suspend, bt as all, c as previewsLayer, ct as Struct, d as gitLayer, dr as getOrUndefined, dt as decodeEffect, en as result, f as Project, ft as isMaxLength, gn as serviceOption, hn as scoped, hr as TaggedError, ht as optional, i as projectFlows, j as drop, jn as void_, jt as context, k as concat, kt as catch_, lr as make$1, lt as Undefined, mt as isPattern, or as Service, ot as Record, pt as isNonEmpty, qn as succeed$1, r as branchPreviewsLayer, s as Previews, sr as add, st as String$1, t as BranchPreviews, tn as retry, u as Git, ut as Union, vn as succeed, vt as acquireUseRelease, w as Path, wt as asVoid, xn as sync, xt as andThen, y as nodeLayer, z as mapError$1, zn as effectDiscard } from "./branch-previews-C_TVt_HQ.js";
2
- import { A as adapterRegistryLayer, D as publishChanges, E as liveChannelLayer, F as WorkAdapter, I as WorkError, M as memoryAdapterLayer, N as parseThreadImport, O as AdapterRegistry, P as ThreadAdapter, R as bundledScreensLayer, T as LiveChannel, _ as storeActivityLayer, c as FileReview, d as fileSearchLayer, f as Files, g as StoreActivity, i as fileSavesLayer, j as defineAdapter, k as adapterModuleLoaderLayer, l as fileReviewLayer, n as fileReviewActionsLayer, o as fileMutationsLayer, p as filesLayer, s as fileWriteLockLayer, v as storeLiveLayer, z as sourceScreensLayer } from "./server-DUBjmaBw.js";
1
+ import { A as concat, At as catch_, B as mapError$1, Bn as effectDiscard, C as ProcessRunner, Cn as tap, Ct as as, D as as$1, E as FileSystem, En as timeoutOrElse, Et as cached, F as fromEffect, Fn as currentTimeMillis, Ft as fail, Gn as mergeAll, Gt as map, H as runForEach, Ht as forkScoped, It as filterOrFail, Jn as succeed$1, K as makeUnsafe, Kn as provide, Kt as mapError, Lt as flatMap, M as drop, Mn as void_, Mt as context, N as empty, Nt as die, On as try_, Ot as catchIf, Pt as ensuring, R as make, Rn as effect, Sn as sync, St as andThen, T as Path, Tt as asVoid, Ut as gen, W as unwrap, Wn as merge, Wt as ignore, Xt as orElseSucceed, Yn as succeedContext, Zn as unwrap$1, _n as serviceOption, b as nodeLayer, c as previewsLayer, cr as add, ct as String$1, d as gitLayer, dt as Union, f as Project, fr as getOrUndefined, ft as decodeEffect, gn as scoped, gr as TaggedError, gt as optional, ht as isPattern, i as projectFlows, j as debounce, k as changes, kt as catchTag, lt as Struct, mt as isNonEmpty, nn as retry, ot as ArraySchema, pt as isMaxLength, qn as provideMerge, r as branchPreviewsLayer, s as Previews, sr as Service, st as Record, t as BranchPreviews, tn as result, u as Git, ur as make$1, ut as Undefined, w as RuntimePolicy, xn as suspend, xt as all, yn as succeed, yt as acquireUseRelease, z as mapEffect, zn as effectContext, zt as forEach } from "./branch-previews-BryeA_kA.js";
2
+ import { A as adapterRegistryLayer, D as publishChanges, E as liveChannelLayer, F as WorkAdapter, I as WorkError, M as memoryAdapterLayer, N as parseThreadImport, O as AdapterRegistry, P as ThreadAdapter, R as bundledScreensLayer, T as LiveChannel, _ as storeActivityLayer, c as FileReview, d as fileSearchLayer, f as Files, g as StoreActivity, i as fileSavesLayer, j as defineAdapter, k as adapterModuleLoaderLayer, l as fileReviewLayer, n as fileReviewActionsLayer, o as fileMutationsLayer, p as filesLayer, s as fileWriteLockLayer, v as storeLiveLayer, z as sourceScreensLayer } from "./server-DN5uwE4k.js";
3
3
  import { A as parseThreadReplyInput, C as parseAnchor, Cn as WorkValidationError, E as parseThreadFilter, M as parseThreadStatus, N as parseThreadStatusInput, O as parseThreadInput, _n as parseMessage, a as CommentMergeError, an as parseWorkDetail, b as MAX_THREADS, c as parseCommentInput, cn as parseWorkMutationResult, d as parseCommentThread, dn as parseWorkSnapshot, en as parseSectionData, f as revision, fn as parseWorkSync, in as parseWorkCreate, j as parseThreadSnapshot, k as parseThreadLinkInput, l as conversationId, mn as parseWorkUpdate, nn as parseWorkActivity, o as mergeThreads, on as parseWorkItem, p as text$2, pn as parseWorkSyncResult, rn as parseWorkConnection, s as stableJson, tn as parseWorkActionInput, u as object$1, un as parseWorkQuery, vn as parseMessageAuthor, w as parseThread, xn as parseWorkSchema } from "./events-6z5v7Uca.js";
4
4
  import { n as PICKER_MODULE_URL, t as pickerPageScript } from "./bridge-B_Blt55E.js";
5
5
  import { createHash, randomUUID } from "node:crypto";
@@ -1,4 +1,4 @@
1
- import { Ht as gen, Kn as provideMerge, Xt as promise, Zt as provide, a as followCapture, d as gitLayer, hn as scoped, i as projectFlows, l as PreviewSession, n as branchIndexName, o as startBranchBuild, on as runPromise, p as createProjectContext, xn as sync, y as nodeLayer, yt as addFinalizer } from "./assets/branch-previews-C_TVt_HQ.js";
1
+ import { Qt as provide, Sn as sync, Ut as gen, Zt as promise, a as followCapture, b as nodeLayer, bt as addFinalizer, d as gitLayer, gn as scoped, i as projectFlows, l as PreviewSession, n as branchIndexName, o as startBranchBuild, p as createProjectContext, qn as provideMerge, sn as runPromise } from "./assets/branch-previews-BryeA_kA.js";
2
2
  import { t as pickerPageScript } from "./assets/bridge-B_Blt55E.js";
3
3
  //#region ../previews/src/server/storage.ts
4
4
  /**
@@ -1,7 +1,7 @@
1
- import { Dn as try_, Gt as mapError, Ht as gen, It as flatMap, _ as resolveStorage, f as Project, on as runPromise, p as createProjectContext, u as Git } from "./assets/branch-previews-C_TVt_HQ.js";
2
- import { H as make, I as WorkError, O as AdapterRegistry } from "./assets/server-DUBjmaBw.js";
1
+ import { Kt as mapError, Lt as flatMap, On as try_, Ut as gen, _ as resolveStorage, f as Project, p as createProjectContext, sn as runPromise, u as Git } from "./assets/branch-previews-BryeA_kA.js";
2
+ import { H as make, I as WorkError, O as AdapterRegistry } from "./assets/server-DN5uwE4k.js";
3
3
  import { j as parseThreadSnapshot, w as parseThread } from "./assets/events-6z5v7Uca.js";
4
- import { n as storageLayer, r as readGitThreadImports } from "./assets/services-Og5rcF50.js";
4
+ import { n as storageLayer, r as readGitThreadImports } from "./assets/services-Ber8opFE.js";
5
5
  //#region app/server/comment-migration.ts
6
6
  function identity(metadata) {
7
7
  if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) return null;
@@ -1,7 +1,7 @@
1
- import { En as tryPromise, Gt as mapError, Ht as gen, Kn as provideMerge, Ln as effect, Xt as promise, _t as acquireRelease, b as readText, kn as uninterruptible, on as runPromise, or as Service, p as createProjectContext } from "./assets/branch-previews-C_TVt_HQ.js";
2
- import { B as sharedModules, H as make } from "./assets/server-DUBjmaBw.js";
3
- import { n as listen, r as createApp, t as ServerError } from "./assets/listener-BVbFsnmX.js";
4
- import { t as applicationLayer } from "./assets/services-Og5rcF50.js";
1
+ import { An as uninterruptible, Dn as tryPromise, Kt as mapError, Rn as effect, Ut as gen, Zt as promise, p as createProjectContext, qn as provideMerge, sn as runPromise, sr as Service, vt as acquireRelease, x as readText } from "./assets/branch-previews-BryeA_kA.js";
2
+ import { B as sharedModules, H as make } from "./assets/server-DN5uwE4k.js";
3
+ import { n as listen, r as createApp, t as ServerError } from "./assets/listener-oKd5ETMj.js";
4
+ import { t as applicationLayer } from "./assets/services-Ber8opFE.js";
5
5
  import { fileURLToPath } from "node:url";
6
6
  //#region app/server/runtime.ts
7
7
  var BudListener = class extends Service()("bud/Listener") {};
@@ -1,6 +1,6 @@
1
- import { Gn as provide, Ht as gen, Ln as effect, b as readText, or as Service, y as nodeLayer } from "./assets/branch-previews-C_TVt_HQ.js";
2
- import { H as make } from "./assets/server-DUBjmaBw.js";
3
- import { n as listen, r as createApp } from "./assets/listener-BVbFsnmX.js";
1
+ import { Kn as provide, Rn as effect, Ut as gen, b as nodeLayer, sr as Service, x as readText } from "./assets/branch-previews-BryeA_kA.js";
2
+ import { H as make } from "./assets/server-DN5uwE4k.js";
3
+ import { n as listen, r as createApp } from "./assets/listener-oKd5ETMj.js";
4
4
  import { fileURLToPath } from "node:url";
5
5
  //#region server.ts
6
6
  var Listener = class extends Service()("bud/StandaloneListener") {};
@@ -55,6 +55,23 @@ interface ResolvedFiles {
55
55
  edit: boolean;
56
56
  }
57
57
  //#endregion
58
+ //#region ../project/src/lib/theme.d.ts
59
+ /** Token values by name, such as `{ primary: '#f5b700' }`. */
60
+ type BudThemeColors = Readonly<Record<string, string>>;
61
+ /**
62
+ * Bud's colors in your project's or platform's palette: token values for the light theme, the
63
+ * dark one, or both; anything left out keeps Bud's own.
64
+ */
65
+ interface BudTheme {
66
+ light?: BudThemeColors;
67
+ dark?: BudThemeColors;
68
+ }
69
+ /** A theme's token values, checked, for each color scheme. */
70
+ interface ResolvedTheme {
71
+ light: BudThemeColors;
72
+ dark: BudThemeColors;
73
+ }
74
+ //#endregion
58
75
  //#region ../project/src/lib/branches.d.ts
59
76
  /**
60
77
  * Branches the canvas captures beside the working tree: main always, others once activated in its
@@ -325,6 +342,11 @@ interface BudConfig {
325
342
  * relative to the project, or `{ light, dark }`.
326
343
  */
327
344
  logo?: BudLogo;
345
+ /**
346
+ * Bud's colors in your palette: `--bud-*` token values for `light`, `dark` or both, such as
347
+ * `{ light: { primary: '#f5b700' } }`. Anything left out keeps Bud's own.
348
+ */
349
+ theme?: BudTheme;
328
350
  /**
329
351
  * What finds the element under a comment: `bud:dom` (the default), `bud:react-grab` for React
330
352
  * projects with React Grab installed, or a ./ module in your project exporting a picker adapter.
@@ -384,8 +406,9 @@ interface ResolvedBudConfig {
384
406
  previews: ResolvedPreviews;
385
407
  files: ResolvedFiles;
386
408
  logo: ResolvedLogo | null;
409
+ theme: ResolvedTheme;
387
410
  picker: ResolvedPicker;
388
411
  branches: ResolvedBranches;
389
412
  }
390
413
  //#endregion
391
- export { defineConfig as a, files as c, ResolvedBudConfig as i, pages as l, BudRoute as n, BudScreen as o, ProjectInfo as r, canvas as s, BudConfig as t, tasks as u };
414
+ export { defineConfig as a, files as c, BudTheme as d, ResolvedBudConfig as i, pages as l, BudRoute as n, BudScreen as o, ProjectInfo as r, canvas as s, BudConfig as t, tasks as u };
@@ -1,4 +1,4 @@
1
- import { i as ResolvedBudConfig } from "./config-BzzRLcL-.js";
1
+ import { i as ResolvedBudConfig } from "./config-Cuauq8xY.js";
2
2
  //#region app/server/hosted/contract.d.ts
3
3
  /** How a hosted Bud's captures stand, as its host reports them. */
4
4
  interface RemoteBranchState {
@@ -1,4 +1,4 @@
1
- import { i as ResolvedBudConfig } from "./assets/config-BzzRLcL-.js";
1
+ import { i as ResolvedBudConfig } from "./assets/config-Cuauq8xY.js";
2
2
  //#region src/companion.d.ts
3
3
  /**
4
4
  * The contract between a host, such as `@bud.sh/app-vite-plugin` and its CLI, and the companion
@@ -1,5 +1,5 @@
1
- import { i as ResolvedBudConfig } from "./assets/config-BzzRLcL-.js";
2
- import { a as HostedAuthor, c as HostedStorage, i as HostedAppOptions, l as RemoteBranchState, n as CreateHostedApp, o as HostedDatabase, r as HostedApp, s as HostedRequestContext, t as BranchRemote, u as hostedScreenModules } from "./assets/contract-jA5pqK6h.js";
1
+ import { i as ResolvedBudConfig } from "./assets/config-Cuauq8xY.js";
2
+ import { a as HostedAuthor, c as HostedStorage, i as HostedAppOptions, l as RemoteBranchState, n as CreateHostedApp, o as HostedDatabase, r as HostedApp, s as HostedRequestContext, t as BranchRemote, u as hostedScreenModules } from "./assets/contract-BsCQbbxD.js";
3
3
  //#region src/hosted.server.d.ts
4
4
  /**
5
5
  * Creates a hosted Bud: Bud's own routes for the canvas and tasks on the host's stores.
@@ -1,5 +1,5 @@
1
1
  import { n as ElementSource } from "./assets/canvas-anchor-CYU3qBPx.js";
2
- import { a as defineConfig, c as files, l as pages, n as BudRoute, o as BudScreen, s as canvas, t as BudConfig, u as tasks } from "./assets/config-BzzRLcL-.js";
2
+ import { a as defineConfig, c as files, l as pages, n as BudRoute, o as BudScreen, s as canvas, t as BudConfig, u as tasks } from "./assets/config-Cuauq8xY.js";
3
3
  //#region ../picker/src/lib/types.d.ts
4
4
  /** What a framework adds about an element, beyond what the page's DOM shows. */
5
5
  interface PickerDescription {
@@ -1,4 +1,5 @@
1
- import { a as HostedAuthor, s as HostedRequestContext } from "./assets/contract-jA5pqK6h.js";
1
+ import { d as BudTheme } from "./assets/config-Cuauq8xY.js";
2
+ import { a as HostedAuthor, s as HostedRequestContext } from "./assets/contract-BsCQbbxD.js";
2
3
  //#region src/node-host.server.d.ts
3
4
  /** Where the project's Bud on Cloudflare is, and the secret its remote API takes. */
4
5
  export interface NodeHostOptions {
@@ -13,6 +14,11 @@ export interface NodeHostOptions {
13
14
  * before a restart reload once.
14
15
  */
15
16
  capability?: string;
17
+ /**
18
+ * Bud's colors in the platform's palette, replacing the project's: `--bud-*` token values for
19
+ * `light` and `dark`.
20
+ */
21
+ theme?: BudTheme;
16
22
  /** Bud's built interface, `dist/client`; this package's own when absent. */
17
23
  client?: string;
18
24
  fetch?: typeof globalThis.fetch;
@@ -1,4 +1,4 @@
1
- import { r as ProjectInfo } from "./assets/config-BzzRLcL-.js";
1
+ import { r as ProjectInfo } from "./assets/config-Cuauq8xY.js";
2
2
  import { i as TaskDesign } from "./assets/task-design-xJOhRNWh.js";
3
3
  import { RequestMethod, Route, RouteMap } from "remix/routes";
4
4
  import { Handle, Props, RemixNode } from "remix/component";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bud.sh/app",
3
3
  "description": "The app, its config, screen and design APIs",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "publishConfig": {
@@ -1,2 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/pages-BVrTX_Eq.js","assets/jsx-B4XNFIzB.js","assets/component-DWct-Tq6.js","assets/on-mixin-iWnqUzq5.js","assets/children-N0l0v7XI.js","assets/attrs-mixin-CmlG_FtV.js","assets/create-element--E6NJ0nh.js","assets/loader-Q6-HPKft.js","assets/screen-Dfvzj6n2.js","assets/task-design-bktfn_Ok.js","assets/lru-BkhKJhvt.js","assets/method-DybmO5PB.js","assets/project-threads-DezXiVK6.js","assets/frame-D6XmK4Df.js","assets/preload-helper-BLdHbfdN.js","assets/cloneFileDiffMetadata-CWfw01dG.js","assets/project-comments-D897aU5O.js","assets/workspace-tab-Bg2MFdMB.js","assets/project-branches-DpxQx-T4.js","assets/canvas-DxaIItAs.js","assets/project-thread-links-Bp_TseD0.js","assets/tasks-request-mWMk9pBo.js","assets/tasks-Cqfj4fQN.js","assets/project-work-CB1JHqGW.js","assets/files-C-7xoSt4.js"])))=>i.map(i=>d[i]);
2
- import{t as e}from"./jsx-B4XNFIzB.js";import{n as t}from"./on-mixin-iWnqUzq5.js";import{n}from"./run-B2H4brp5.js";import{n as r}from"./attrs-mixin-CmlG_FtV.js";import{t as i}from"./preload-helper-BLdHbfdN.js";import{c as a,i as o,l as s,o as c,r as l,t as ee}from"./loader-Q6-HPKft.js";import{Et as u,Fn as d,Gn as f,Hn as p,In as m,Kn as h,Ln as g,Mn as _,Nn as v,Ot as y,Pn as b,Q as x,Un as S,Vn as C,jn as w,yt as T}from"./task-design-bktfn_Ok.js";import{$ as te,At as ne,Dt as re,J as E,Ot as D,Q as O,X as ie,Y as ae,Z as k,b as A,dt as j,et as M,jt as N,kt as oe,nt as se,ot as P,rt as ce,t as F,tt as le,v as ue,y as de}from"./project-threads-DezXiVK6.js";import{d as fe}from"./method-DybmO5PB.js";import{t as pe}from"./project-work-CB1JHqGW.js";import{n as me}from"./workspace-tab-Bg2MFdMB.js";function he(t){let n=`connecting`,i=r((e,r)=>{let{project:i}=t.props;pe(i),F(i);let a=de(i.token);n=a.status;let o=a.watchStatus(e=>{n=e,t.update()});r.addEventListener(`abort`,o,{once:!0}),t.update()});return()=>e(`span`,{class:`contents`,mix:i,children:e(D,{status:n})})}var ge=new WeakMap;function I(e,t){let n=f(e,t,{abortEarly:!0});if(n.success)return n.value;let r=n.issues[0];throw ge.get(r)??Error(r.message)}function L(e,t){return b((n,r)=>{let i=e[`~run`](n,r);return i.issues?g(t,r.path):i})}function R(e,t){return b((n,r)=>{let i=e[`~run`](n,r);if(i.issues)return i;let a=t(i.value);return a===void 0?i:g(a,r.path)})}function z(e,t){return b((n,r)=>{let i=e[`~run`](n,r);if(i.issues)return i;try{return{value:t(i.value)}}catch(e){if(!(e instanceof Error))throw e;let t=g(e.message,r.path);return ge.set(t.issues[0],e),t}})}function B(e){return b((t,n)=>e(t)[`~run`](t,n))}function V(e,t){return b((n,r)=>n==null?{value:t()}:e[`~run`](n,r))}function H(e,t){let n=p(t);return b((r,i)=>{if(!r||typeof r!=`object`||Array.isArray(r))return g(`${e} must be an object.`,i.path);for(let n of Object.keys(r))if(!Object.hasOwn(t,n))return g(`${e}.${n} is not a supported setting.`,[...i.path,n]);return n[`~run`](r,i)})}function _e(e,t,n=0){let r=_(e);return b((e,i)=>!Array.isArray(e)||e.length<n?g(t,i.path):r[`~run`](e,i))}var ve=d(H(`files`,{edit:V(L(v(),`files.edit must be true or false.`),()=>!0)}),()=>({edit:!0})),U=`flows must be [{ id, title, start, script, steps: [{ id, title }], block? }] with short ids, local paths and unique steps.`,W=e=>typeof e==`string`&&/^[a-z0-9][a-z0-9-]{0,62}$/.test(e),G=e=>typeof e==`string`&&e.trim()!==``&&e.length<=200;function ye(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let{id:t,title:n,start:r,script:i,steps:a,block:o=[]}=e;if(!W(t)||!G(n)||!G(i)||i.includes(`\0`)||typeof r!=`string`||!r.startsWith(`/`)||r.startsWith(`//`)||new URL(r,`http://bud.invalid`).origin!==`http://bud.invalid`||!Array.isArray(a)||!a.length||a.length>50)return null;let s=a.map(e=>{let{id:t,title:n}=e??{};return W(t)&&G(n)?{id:t,title:n.trim()}:null});if(s.some(e=>!e))return null;let c=s.map(e=>e.id);return new Set(c).size!==c.length||!Array.isArray(o)||o.some(e=>!G(e))?null:{id:t,title:n.trim(),start:r,script:i.trim(),steps:s,block:o}}var be=b((e,t)=>{if(e===void 0)return{value:[]};if(!Array.isArray(e))return g(U,t.path);let n=e.map(ye);if(n.some(e=>!e))return g(U,t.path);let r=n.map(e=>e.id);return new Set(r).size===r.length?{value:n}:g(U,t.path)});function xe(e,t){return{id:`${e.id}/${t.id}`,path:`${e.start.replace(/#.*$/,``)}#${e.id}-${t.id}`,title:t.title,group:e.title,flow:{id:e.id,step:t.id}}}var Se=Object.freeze({".svg":`image/svg+xml`,".png":`image/png`,".webp":`image/webp`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".gif":`image/gif`,".ico":`image/x-icon`}),Ce=`logo must be an image path inside the project (.svg, .png, .webp, .jpg, .gif or .ico), or { light, dark }.`;function we(e){if(typeof e!=`string`||e.length>1024||e.includes(`\0`))return null;let t=e.trim().replaceAll(`\\`,`/`);if(!t||t.startsWith(`/`)||/^[a-z]:/i.test(t)||t.split(`/`).includes(`..`))return null;let n=t.slice(t.lastIndexOf(`.`)).toLowerCase();return Object.hasOwn(Se,n)?t:null}var Te=b((e,t)=>{if(e===void 0)return{value:null};let n=we(typeof e==`object`&&e?e.light:e),r=typeof e==`object`&&e?e.dark:void 0,i=r===void 0?null:we(r),a=typeof e==`object`&&e?Object.keys(e):[];return n&&(r===void 0||i)&&a.every(e=>e===`light`||e===`dark`)?{value:{light:n,dark:i}}:g(Ce,t.path)}),K=`branches must be { main?, build?: { install?, build?, serve? } } with a branch name and nonempty shell commands.`;function Ee(e){return typeof e==`string`&&e.length<=255&&/^[A-Za-z0-9._/-]+$/.test(e)&&!e.startsWith(`-`)&&!e.startsWith(`/`)&&!e.endsWith(`/`)&&!e.endsWith(`.lock`)&&!e.includes(`..`)&&!e.includes(`//`)?e:null}function q(e){return typeof e==`string`&&e.trim()&&e.length<=4096&&!e.includes(`\0`)?e.trim():null}var De=b((e,t)=>{let n={main:null,install:null,build:null,serve:null};if(e===void 0)return{value:n};if(!e||typeof e!=`object`||Array.isArray(e))return g(K,t.path);let r=e,i=r.build??{};if(!i||typeof i!=`object`||Array.isArray(i)||Object.keys(r).some(e=>e!==`main`&&e!==`build`))return g(K,t.path);let a=i;if(Object.keys(a).some(e=>![`install`,`build`,`serve`].includes(e)))return g(K,t.path);let o={main:r.main===void 0?null:Ee(r.main),install:a.install===void 0?null:q(a.install),build:a.build===void 0?null:q(a.build),serve:a.serve===void 0?null:q(a.serve)};return r.main!==void 0&&!o.main||[`install`,`build`,`serve`].some(e=>a[e]!==void 0&&!o[e])?g(K,t.path):{value:o}});function J(e,t,n){let r=t?/\.server\.ts$/:/\.(?:ts|tsx|js|jsx)$/;return L(h().refine(e=>e.length<=1024&&e.startsWith(`./`)&&!/[\u0000-\u001f\u007f\\?#%]/.test(e)&&r.test(e)&&(t||!/\.server\.[cm]?[jt]sx?$/.test(e))&&!e.slice(2).split(`/`).some(e=>!e||e===`.`||e===`..`||e===`node_modules`)),n??(t?`${e} must be a built-in adapter or a ./ module ending in .server.ts inside the project.`:`${e} must be bud:beads or a ./ browser module ending in .ts, .tsx, .js or .jsx inside the project.`))}var Oe=m([!1,`bud:beads`,`bud:memory`,`bud:git-comments`]);function ke(e){let t=J(`storage.${e}`,!0);return d(R(B(e=>e===!1||e===`bud:beads`||e===`bud:memory`||e===`bud:git-comments`?Oe:t),t=>e===`work`&&t===`bud:git-comments`?`storage.work cannot use bud:git-comments; it only stores threads.`:void 0),`bud:beads`)}var Ae=d(H(`storage`,{work:ke(`work`),threads:ke(`threads`)}),()=>({work:`bud:beads`,threads:`bud:beads`})),je=d(H(`designs`,{tasks:d(B(e=>e===`bud:beads`?m([`bud:beads`]):J(`designs.tasks`,!1)),`bud:beads`),pages:d(m([`path`,`title`]),`path`)}),()=>({tasks:`bud:beads`,pages:`path`})),Me=new Set([`bud:dom`,`bud:react`,`bud:react-grab`]),Ne=J(`picker`,!1,`picker must be bud:dom, bud:react, bud:react-grab or a ./ browser module ending in .ts, .tsx, .js or .jsx inside the project.`),Pe=b((e,t)=>{if(e===void 0)return{value:{name:`bud:dom`,module:null}};if(typeof e==`string`&&Me.has(e))return{value:{name:e,module:null}};let n=Ne[`~run`](e,t);return n.issues?n:{value:{name:n.value,module:n.value}}}),Fe=`ready must be a CSS selector, { selector } or { expression }.`,Y=b((e,t)=>{let n=typeof e==`string`?{selector:e}:e;if(n&&typeof n==`object`&&!Array.isArray(n)){let e=Object.entries(n),[t,r]=e[0]??[];if(e.length===1&&(t===`selector`||t===`expression`)&&typeof r==`string`&&r.trim()&&r.length<=4096)return{value:t===`selector`?{selector:r.trim()}:{expression:r.trim()}}}return g(Fe,t.path)}),Ie=()=>[`light`,`dark`],Le=()=>[{id:`desktop`,name:`Desktop`,width:1440,height:900,mobile:!1}],X=`previews.viewports must list up to 4 { name, width, height?, mobile? } with distinct names, widths from 240 to 3840 and heights from 240 to 4000.`;function Re(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,32)}var ze=b((e,t)=>{if(!Array.isArray(e)||e.length===0||e.length>4)return g(X,t.path);let n=[];for(let r of e){if(!r||typeof r!=`object`||Array.isArray(r))return g(X,t.path);let{name:e,width:i,height:a,mobile:o,...s}=r,c=(e,t,n)=>typeof e==`number`&&Number.isInteger(e)&&e>=t&&e<=n;if(Object.keys(s).length||typeof e!=`string`||!e.trim()||e.length>40||!Re(e)||!c(i,240,3840)||a!==void 0&&!c(a,240,4e3)||o!==void 0&&typeof o!=`boolean`)return g(X,t.path);let l=o??i<800;n.push({id:Re(e),name:e.trim(),width:i,height:a??(l?Math.round(i*844/390):900),mobile:l})}return new Set(n.map(e=>e.id)).size===n.length?{value:n}:g(X,t.path)}),Be=d(H(`previews`,{scale:V(L(C().refine(e=>Number.isInteger(e)&&e>=1&&e<=3),`previews.scale must be 1, 2 or 3.`),()=>2),themes:V(L(_(m([`light`,`dark`])).refine(e=>e.length>0&&new Set(e).size===e.length),`previews.themes must list light, dark or both, once each.`),Ie),viewports:V(ze,Le),ready:V(Y,()=>null),readyTimeout:V(L(C().refine(e=>Number.isInteger(e)&&e>=1e3&&e<=6e5),`previews.readyTimeout must be whole milliseconds from 1000 to 600000.`),()=>6e4),css:V(L(h().refine(e=>e.length<=2e4&&!e.includes(`<`)),`previews.css must be CSS text without <, up to 20000 characters.`),()=>``)}),()=>({scale:2,themes:Ie(),viewports:Le(),ready:null,readyTimeout:6e4,css:``}));function Ve(e,t){let n=[],r=new Set;function i(e,a){if(!e||typeof e!=`object`||Array.isArray(e)||r.has(e))throw Error(`Screen routes must be a Remix route map.`);r.add(e);for(let[r,o]of Object.entries(e)){let e=a?`${a}.${r}`:r;if(!o||typeof o!=`object`)throw Error(`Screen route ${e} must be a Remix route.`);if(!(`pattern`in o)){i(o,e);continue}if(![`GET`,`ANY`].includes(o.method)||typeof o.href!=`function`||typeof o.pattern?.source!=`string`)throw Error(`Screen route ${e} must be a GET route.`);let s=fe.parse(o.pattern.source),c=s.toJSON(),l=`/${c.pathname}`;if(c.protocol||c.hostname||c.port||c.pathname.split(`/`).some(e=>/^\.{1,2}$/.test(decodeURIComponent(e)))||l!==t&&!l.startsWith(`${t}/`)&&!l.startsWith(`${t}(/`))throw Error(`Screen route ${e} must stay under ${t}.`);n.push({name:e,pattern:s.source})}r.delete(e)}if(i(e,``),!n.length)throw Error(`Screen routes must contain at least one route.`);return n}function He(){return{id:`pages`,label:`Pages`,icon:`browser`,path:`/pages`,module:`bud:pages`}}function Ue(){return{id:`canvas`,label:`Canvas`,icon:`grid`,path:`/canvas`,module:`bud:canvas`}}function We(){return{id:`tasks`,label:`Tasks`,icon:`tasks`,path:`/tasks`,module:`bud:tasks`}}function Ge(){return{id:`files`,label:`Files`,icon:`files`,path:`/files`,module:`bud:files`}}var Z=[He(),Ue(),We(),Ge()],Ke=new Map(Z.map(e=>[e.module,e])),qe=[`/comments`,...Z.map(e=>e.path),`/api`,`/health`,`/__bud`,`/assets`,`/app`,`/src`,`/node_modules`,`/agents`,`/brand`,`/fonts`,`/frameworks`,`/licenses`],Je=R(L(w().refine(e=>!!e&&typeof e==`object`),`Each screen must be an object.`),({id:e,label:t,icon:n=`layers`,module:r,path:i})=>{if(typeof e!=`string`||!/^[a-z][a-z0-9-]{0,31}$/.test(e))return`Screen ids are 1-32 lowercase letters, digits and hyphens.`;if(typeof t!=`string`||!t.trim())return`Screen ${e} needs a label.`;if(typeof n!=`string`||!n)return`Screen ${e} needs an icon name.`;if(typeof r!=`string`)return`Screen ${e} needs a module.`;let a=Ke.get(r);if(i??=a?.path??`/${e}`,a)return e!==a.id||i!==a.path?`${r} keeps id "${a.id}" and path "${a.path}".`:void 0;if(!/^\.\/[^\0\\]+\.(?:ts|tsx|js|jsx)$/.test(r))return`Screen ${e} must be a ./ module ending in .ts, .tsx, .js or .jsx.`;if(typeof i!=`string`||!/^\/[a-z0-9][a-z0-9-]*$/.test(i))return`Screen ${e} needs one static path segment, such as /${e}.`;if(Z.some(t=>t.id===e))return`Screen id "${e}" is reserved for a built-in screen.`;if(qe.includes(i))return`Bud reserves the path ${i}.`}),Ye=d(z(L(_(w()).refine(e=>e.length>0),`screens must list at least one screen.`),e=>{let t=new Set,n=new Set;return e.map(e=>{let r=I(Je,e),{id:i,label:a,icon:o=`layers`,module:s}=r,c=r.path??Ke.get(s)?.path??`/${i}`;if(t.has(i)||n.has(c))throw Error(`Screen ids and paths must be unique.`);return t.add(i),n.add(c),r.routes!==void 0&&Ve(r.routes,c),{id:i,label:a,icon:o,path:c,module:s,...r.routes===void 0?{}:{routes:r.routes}}})}),()=>Z.map(e=>({...e}))),Xe=e=>!!e&&typeof e==`object`;function Q(e,t){let n=p(t);return b((t,r)=>Xe(t)?n[`~run`](Array.isArray(t)?{...t}:t,r):g(e,r.path))}var Ze=R(Q(`Bud config must export an object.`,{routes:L(_(w()).refine(e=>e.length>0),`bud.config must define at least one route.`),name:S(L(h().refine(e=>!!e.trim()),`name must be a nonempty string.`)),target:S(Q(`target must be an object.`,{origin:w(),port:w()})),comments:S(Q(`comments must be an object.`,{remote:w()})),port:w(),screens:w(),storage:w(),designs:w(),previews:w(),files:w(),logo:w(),picker:w(),branches:w(),flows:w()}),({target:e})=>{if(e?.port===0)return`target.port must be a listening port, not zero.`;if(e?.origin!==void 0&&(typeof e.origin!=`string`||!e.origin.trim()))return`target.origin must be an HTTP(S) origin.`}),Qe=R(w().transform(e=>typeof e==`string`?{path:e,title:e===`/`?`Home`:e}:e),e=>{if(!e||typeof e.path!=`string`||!e.path.startsWith(`/`)||e.path.startsWith(`//`))return`Canvas routes must be local paths beginning with a single /.`;if(new URL(e.path,`http://bud.invalid`).origin!==`http://bud.invalid`||e.path.includes(`\\`))return`Canvas routes must stay on the target origin.`;let t=e.id??$e(e.path);if(typeof t!=`string`||!t.trim())return`Canvas route IDs and paths must be unique.`;if(typeof e.title!=`string`||!e.title.trim())return`Each route needs a title.`;if(e.pattern!==void 0&&(typeof e.pattern!=`string`||!e.pattern.startsWith(`/`)))return`A route pattern must be a path beginning with /.`;if(e.group!==void 0&&(typeof e.group!=`string`||!e.group.trim()||e.group.length>120))return`A route group must be a short name.`;if(e.ready!==void 0&&e.ready!==!1&&!f(Y,e.ready).success)return`A route ready must be false, a CSS selector, { selector } or { expression }.`}).transform(e=>{let t=$e(e.path);return{id:e.id??t,path:t,title:e.title,...e.pattern===void 0?{}:{pattern:e.pattern},...e.group===void 0?{}:{group:e.group.trim()},...e.ready===void 0?{}:{ready:e.ready===!1?null:I(Y,e.ready)}}});function $e(e){let t=new URL(e,`http://bud.invalid`),n=t.searchParams.toString();return`${t.pathname}${n?`?${n}`:``}${t.hash}`}var et=R(_e(Qe,`bud.config must define at least one route.`,1),e=>new Set(e.map(e=>e.id)).size!==e.length||new Set(e.map(e=>e.path)).size!==e.length?`Canvas route IDs and paths must be unique.`:void 0),tt=e=>e===void 0||Number.isInteger(e)&&e>=0&&e<=65535,nt=e=>typeof e==`string`&&/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(e);z(R(z(R(z(R(z(Ze,e=>({...e,routes:I(et,e.routes)})),({port:e,target:t})=>tt(e??0)&&tt(t?.port)?void 0:`Ports must be integers between 0 and 65535.`),({target:e,...t})=>{let n=e?.origin??(e?.port?`http://127.0.0.1:${e.port}`:void 0);return{...t,targetOrigin:n&&rt(n,`target.origin must be an HTTP(S) origin without a path or credentials.`)}}),({comments:e})=>nt(e?.remote??`origin`)?void 0:`comments.remote must be a Git remote name.`),e=>{let t=I(be,e.flows),n=t.flatMap(e=>e.steps.map(t=>xe(e,t))),r=e.routes.findIndex(e=>e.path===`/`)+1;return{...e,flows:t,routes:[...e.routes.slice(0,r),...n,...e.routes.slice(r)]}}),({routes:e})=>new Set(e.map(e=>e.id)).size!==e.length||new Set(e.map(e=>e.path)).size!==e.length?`A flow step must not reuse a route’s id or path.`:void 0),e=>({name:e.name??`Your project`,routes:e.routes,flows:e.flows,port:e.port??0,targetOrigin:e.targetOrigin,remote:e.comments?.remote??`origin`,screens:I(Ye,e.screens),storage:I(Ae,e.storage),designs:I(je,e.designs),previews:I(Be,e.previews),files:I(ve,e.files),logo:I(Te,e.logo),picker:I(Pe,e.picker),branches:I(De,e.branches)}));function rt(e,t){let n=new URL(e);if(![`http:`,`https:`].includes(n.protocol)||n.username||n.password||n.pathname!==`/`||n.search||n.hash)throw Error(t);return n.origin}function $(e,t){let n=T();for(let t of e)n.add(t.pattern,t.name);let r=n.match(t,{baseURL:`http://bud.invalid`});return r?{route:r.data,params:r.params}:null}function it(e,t){let n=e?$(Ve(e,t.path),t.url):{route:null,params:{}};if(!n)throw Error(`No screen route matches ${t.url.pathname}.`);return{...t,...n}}var at={"bud:pages":()=>i(()=>import(`./pages-BVrTX_Eq.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18])),"bud:canvas":()=>i(()=>import(`./canvas-DxaIItAs.js`),__vite__mapDeps([19,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,21])),"bud:tasks":()=>i(()=>import(`./tasks-Cqfj4fQN.js`),__vite__mapDeps([22,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,21,23,20])),"bud:files":()=>i(()=>import(`./files-C-7xoSt4.js`),__vite__mapDeps([24,10,1,5,3,2,4,6,14,7,8,9,11,15,12,13,16,20,21]))};function ot(e){return Object.hasOwn(at,e)?at[e]():i(()=>import(e),[])}async function st(e,t,n=ot){let r=(await n(e)).default;if(typeof r?.render!=`function`)throw Error(`A screen module must export defineScreen({ render }) as its default.`);let i=await r.load?.(it(r.routes,t));return t.signal.throwIfAborted(),{screen:r,data:i}}async function ct(e,t,n=e=>i(()=>import(e),[])){if(t.throwIfAborted(),!e)return;if(`error`in e)throw Error(e.error);let r=await n(e.url);return t.throwIfAborted(),x(r.default)}function lt(n){let i,u=``;async function d(){let{module:e,project:t,label:r}=n.props;i=void 0,u=``,n.update();let{location:a}=n.props,o={project:t,signal:n.signal,path:a.path,url:new URL(a.href,window.location.origin),active:n.props.active,conversation:a.conversation,route:null,params:{}};try{if(`error`in e)throw Error(e.error);o.taskDesign=await ct(n.props.taskDesign,n.signal),i={...await st(e.url,o),context:o}}catch(e){if(n.signal.aborted)return;console.error(e),u=e instanceof Error&&e.message?e.message:`Could not open ${r}.`}n.update()}let f=r(()=>{d()});return()=>{let{label:r,module:p,location:m}=n.props,h=i?.context,g=``;if(i&&h)try{if(m.routes&&!$(m.routes,m.href))throw Error(`No screen route matches ${m.href}.`);h=it(i.screen.routes,{...h,active:n.props.active,conversation:m.conversation,url:new URL(m.href,h.url.origin)})}catch(e){g=e instanceof Error?e.message:`This screen route is invalid.`}return e(`div`,{class:`h-full min-h-0`,mix:f,children:g?e(`div`,{class:`p-3 md:p-4`,children:e(s,{role:`alert`,children:g})}):i&&h?i.screen.render(i.data,h):u?e(`div`,{class:`h-full overflow-y-auto p-3 md:p-4`,children:e(l,{class:`max-w-2xl`,role:`alert`,children:[e(c,{title:`${r} didn't open`,subtitle:u}),e(o,{class:`flex-col items-start gap-3`,children:[e(s,{as:`p`,variant:`ui`,tone:`muted`,children:`Fix the screen and retry. Details are in the browser console.`}),e(a,{mix:t(`click`,()=>{`error`in p||n.props.taskDesign&&`error`in n.props.taskDesign?window.location.reload():d()}),children:`Retry`})]})]})}):e(ee,{label:`Loading ${r}…`})})}}async function ut(e,t,n,r,i=fetch){e=y(e);let a=await ue(A.comments.get.href({id:e}),n,r,u,i);if(r.throwIfAborted(),a.id!==e)throw Error(`The comments service returned another discussion.`);let o=P(a),s=t.find(e=>e.module===o.module);if(!s)throw Error(`Enable the screen that owns this discussion to open it.`);if(s.routes&&!$(s.routes,o.href))throw Error(`The discussion location is not available in this screen.`);return{active:s.id,module:{url:s.module},location:{path:s.path,href:o.href,...s.routes?{routes:s.routes}:{},conversation:{id:e,original:o.original}}}}function dt(i){let u=new Map,d=i.props,f=``,p=i.props.conversation,m,h=!!p,g=``,_=!1;function v(){i.signal.aborted||i.update()}async function y(e){if(p!==e)return;m?.abort();let t=new AbortController;m=t;let n=AbortSignal.any([i.signal,t.signal]);h=!0,g=``,v();try{let t=i.props.project;if(!t)throw Error(`Connect a project to open this discussion.`);let r=await ut(e,i.props.conversationTargets??[],t.token,n);!n.aborted&&p===e&&(d=r,b.set(r.active,window.location.pathname))}catch(e){n.aborted||(g=e instanceof Error?e.message:`Could not open this discussion.`)}finally{m===t&&!n.aborted&&(h=!1,v())}}let b=new Map,x,S,C=()=>`bud:tabs:${i.props.project?.id}:v1`,w=()=>`${window.location.pathname}${window.location.search}${window.location.hash}`;function T(e){x=e,N(C(),e);let t=i.props.project;t&&(document.cookie=`${le(t.id)}=${se(e)}; Path=/; Max-Age=31536000; SameSite=Strict`),v()}function D(){if(!x)return;let e=w();S===e?S=void 0:M(E(x))!==e&&T(ce(x,e))}function P(e){let t=M(E(e));T(e),t!==w()&&(S=t,n(t,{history:`replace`,resetScroll:!1}))}function F(e){let{pathname:t}=new URL(e,`http://bud.local`);if(j(e))return{href:e,title:`Discussion`,icon:`message`};let n=i.props.screens.map(e=>({item:e,root:new URL(e.href,`http://bud.local`).pathname})).filter(({root:e})=>e===`/`||t===e||t.startsWith(`${e}/`)).sort((e,t)=>t.root.length-e.root.length)[0],r=n?.item??i.props.screens[0];if(r.id===`pages`&&n&&t.startsWith(`${n.root}/`)){let a=t.slice(n.root.length);return{href:e,title:i.props.project?.routes.find(e=>e.path===a)?.title??a,icon:r.icon}}let a=(n&&n.root!==`/`?t.slice(n.root.length):t).split(`/`).filter(Boolean).at(-1);return{href:e,title:(a&&n?.root!==`/`?decodeURIComponent(a):void 0)??r.label,icon:r.icon}}let ue=r((e,t)=>{_=!0,p&&y(p);function r(){let{pathname:e,search:t,hash:n}=window.location,r=`${e}${t}${n}`,i=j(r);if(i)return i!==p&&(p=i,y(i)),d.location.conversation?.id===i&&b.set(d.active,r),!0;let a=u.get(d.active);if(!a)return!1;let o=a.location.path;return e!==o&&(o===`/`||!e.startsWith(`${o}/`))?!1:(m?.abort(),p=void 0,h=!1,g=``,b.set(d.active,r),a.location={...a.location,href:r,conversation:void 0},d={...d,location:a.location},!0)}r(),i.props.project&&T(O(ne(C()),w(),crypto.randomUUID())),i.update(),window.addEventListener(`click`,e=>{if(!x||!(e.metaKey||e.ctrlKey)||e.shiftKey||e.button!==0)return;let t=e.target?.closest?.(`a[href]`);if(!(t instanceof HTMLAnchorElement)||t.target||t.hasAttribute(`download`))return;let n=new URL(t.href);n.origin!==window.location.origin||n.pathname.startsWith(`/api/`)||(e.preventDefault(),e.stopPropagation(),T(k(x,`${n.pathname}${n.search}${n.hash}`,crypto.randomUUID(),!1)))},{capture:!0,signal:t}),window.addEventListener(`popstate`,()=>{!r()&&!window.navigation?.currentEntry?.getState()&&n(window.location.href,{history:`replace`,resetScroll:!1}),window.navigation||D(),i.update()},{signal:t}),window.navigation?.addEventListener(`navigate`,r,{signal:t}),window.navigation?.addEventListener(`currententrychange`,()=>{r(),D(),i.update()},{signal:t}),window.navigation?.addEventListener(`navigatesuccess`,()=>{r(),i.update()},{signal:t})});return()=>{let{screens:r,project:v,taskDesign:C}=i.props,w=JSON.stringify([i.props.active,i.props.location.href,i.props.conversation]);if(f!==w){if(f=w,p=i.props.conversation,m?.abort(),g=``,h=!!p,p){let e=p;_&&i.queueTask(()=>{y(e)})}else d=i.props}let{active:T,module:ne,location:D}=d,O=r.find(e=>e.id===T)??r[0];v&&!h&&!g&&u.set(O.id,{module:ne,location:D,taskDesign:O.id===`tasks`?C:void 0});let j=x??i.props.initialTabs??(v?ie(D.href,`current`):void 0);j&&i.queueTask(()=>me(j.active));let N=r.map(e=>e.id===O.id?e:{...e,href:b.get(e.id)??e.href});return e(oe,{items:N,activeId:O.id,title:O.label,canvas:!!v,logo:v?.logo?{light:A.logo.href({theme:`light`}),dark:v.logo.dark?A.logo.href({theme:`dark`}):void 0,label:v.name}:void 0,status:v?e(he,{project:v}):void 0,tabs:v&&j?e(re,{tabs:j.tabs.map(e=>({id:e.id,...F(M(e))})),active:j.active,recent:E(j).recent.filter(e=>e!==M(E(j))).map(F),canBack:E(j).index>0,canForward:E(j).index<E(j).entries.length-1,onSelect:e=>P({...j,active:e}),onClose:e=>P(ae(j,e)),onBack:()=>P(te(j,-1)),onForward:()=>P(te(j,1)),onNew:()=>P(k(j,r[0]?.href??`/`,crypto.randomUUID(),!0)),onOpen:e=>{S=void 0,n(e)}}):void 0,children:v?e(`div`,{class:`h-full min-h-0`,mix:ue,children:[h?e(ee,{label:`Opening discussion…`}):g?e(`div`,{class:`p-3 md:p-4`,children:e(l,{class:`max-w-2xl`,role:`alert`,children:[e(c,{title:`Discussion didn't open`,subtitle:g}),e(o,{children:e(a,{mix:t(`click`,()=>{p&&y(p)}),children:`Retry`})})]})}):null,[...u].map(([t,{module:n,taskDesign:i,location:a}])=>e(`div`,{class:`h-full min-h-0`,hidden:h||!!g||t!==O.id,children:e(lt,{label:r.find(e=>e.id===t)?.label??t,module:n,taskDesign:i,project:v,location:a,active:!h&&!g&&t===O.id})},`${t}:${v.token}`))]}):e(l,{class:`max-w-2xl`,children:[e(c,{title:`Your project, side by side.`,subtitle:`Open Bud beside a local project to review its pages, files and tasks.`}),e(o,{children:e(s,{as:`p`,variant:`ui`,children:`Start your project with the Bud Vite plugin, or run Bud from its directory. Its screens appear here when the companion connects.`})})]})})}}export{dt as Workspace};