@hachej/boring-workspace 0.1.23 → 0.1.26

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.
@@ -21,6 +21,12 @@ commands, and default workspace plugins.
21
21
  `WorkspaceAgentFront` and `createWorkspaceAgentServer`, where workspace app
22
22
  code may compose with documented `@hachej/boring-agent/server` APIs.
23
23
 
24
+ ## Chat-first workspace boot
25
+
26
+ The default core-composed workspace route is chat-first after identity match: `WorkspaceAgentFront` mounts immediately, while `WorkspaceBackgroundBoot` warms tree/session/runtime readiness in the background. `WorkspaceBootGate` remains available for shells that want blocking boot.
27
+
28
+ Workbench surfaces are locally gated by warmup state. File tree/editor/plugin/left-tab surfaces do not mount while the current workspace is preparing or failed; chat remains visible. See [`packages/core/docs/CHAT_FIRST_WORKSPACE_BOOT.md`](../../core/docs/CHAT_FIRST_WORKSPACE_BOOT.md) for the product contract and stable readiness errors.
29
+
24
30
  ## Core Contracts
25
31
 
26
32
  - Plugin contributions: `src/shared/plugins/frontFactory.ts`
@@ -0,0 +1,633 @@
1
+ # Dedicated Full-Page Pane Route Spec
2
+
3
+ Last updated: 2026-05-27
4
+
5
+ ## Summary
6
+
7
+ Add one dedicated generic Workspace route for rendering an existing panel in a
8
+ new browser tab as a full-page surface.
9
+
10
+ This is intentionally the same simple mental model boring-macro used for decks
11
+ with `/present`, but generalized so any opted-in plugin panel can use it.
12
+
13
+ Primary use case now:
14
+
15
+ - `@hachej/boring-deck` should open the same deck panel in a new tab and let
16
+ that panel default into present/full-page behavior.
17
+
18
+ Secondary use cases this should unlock without feature-specific routes:
19
+
20
+ - HTML viewer open-in-new-tab
21
+ - report/artifact panels that benefit from more screen real estate
22
+ - future custom plugin panels that want a permalink/full-page view
23
+
24
+ The key design points are:
25
+
26
+ - one dedicated generic route
27
+ - reuse the same panel component
28
+ - avoid feature-specific page routes
29
+ - let the panel detect that it is being rendered full-page
30
+
31
+ ## Problem
32
+
33
+ Today there is no generic Workspace concept of:
34
+
35
+ - “open this registered panel in another browser tab”
36
+ - “render this panel full-page outside Dockview”
37
+ - “let a panel know it is in full-page mode”
38
+
39
+ `boring-macro` previously solved this for decks with an app-owned route:
40
+
41
+ - `/present?path=...`
42
+
43
+ That worked because macro owned a dedicated app route and the deck feature was
44
+ special-cased. It is not a good generic answer for Workspace because:
45
+
46
+ - generic plugins should not hardcode app routes
47
+ - every new artifact type would otherwise add its own custom route
48
+ - the Workspace package does not own the host app’s router/pathnames
49
+
50
+ ## Goals
51
+
52
+ - Reuse an existing registered panel component full-page in a new tab.
53
+ - Keep the capability generic across deck/html/report/custom artifact panels.
54
+ - Avoid feature-specific `/present`, `/html`, `/report`, etc. routes by
55
+ standardizing on one dedicated generic pane route.
56
+ - Let opted-in panels know they are being rendered full-page.
57
+ - Keep host apps in control of the actual route path they mount.
58
+ - Keep the v1 design small and reviewable.
59
+
60
+ ## Non-goals
61
+
62
+ - Making every panel full-page capable by default.
63
+ - Replacing Dockview or normal pane rendering.
64
+ - Adding server persistence/permalinks/history in v1.
65
+ - Solving cross-session/shareable public URLs in v1.
66
+ - Requiring Workspace core/shared layers to depend on a specific router.
67
+ - Inventing a deck-only route once the generic path exists.
68
+
69
+ ## Core decision
70
+
71
+ Use one dedicated generic full-page pane route.
72
+
73
+ Not:
74
+
75
+ - a deck-only route
76
+ - an HTML-only route
77
+ - a different route shape per artifact type
78
+
79
+ Yes:
80
+
81
+ - one Workspace-level full-page pane route
82
+ - panel id + params decide what renders there
83
+
84
+ This is deliberately the boring-macro `/present` idea transported upward into a
85
+ single reusable Workspace capability.
86
+
87
+ The generic capability should be split across two Workspace boundaries:
88
+
89
+ - **root package exports (`@hachej/boring-workspace`)** for plugin-safe front
90
+ helpers/hooks
91
+ - **app/front composition exports** for route/page helpers
92
+
93
+ Why this split:
94
+
95
+ - the Workspace package does not own the host router
96
+ - full-page rendering is app composition behavior
97
+ - plugin panels still need a safe place to read `dock` vs `full-page`
98
+ - base/shared code should stay router-agnostic
99
+
100
+ So Workspace should provide:
101
+
102
+ 1. a **full-page panel page component** in `app/front`
103
+ 2. a **root-exported href builder/hook** plus an `app/front` route parser
104
+ 3. an **opt-in panel capability flag** on the normal panel contract
105
+ 4. a **render-mode context/hook** on the root package export surface
106
+ 5. a small **provider-level route-base config seam** so plugins do not hardcode
107
+ pp paths
108
+
109
+ The host app still mounts the dedicated route wherever it wants, e.g.:
110
+
111
+ - `/full-page`
112
+ - `/panel`
113
+ - `/artifact`
114
+
115
+ ## Proposed API
116
+
117
+ ## 1) Plugin-facing panel contract change
118
+
119
+ The opt-in belongs on the existing plugin-facing panel contract:
120
+
121
+ - `PanelConfig`
122
+ - `definePanel(...)`
123
+ - declarative `definePlugin({ panels: [...] })`
124
+ - imperative `setup(api => api.registerPanel(...))`
125
+ - `BoringFrontPanelRegistration`
126
+ - captured/registered front panel metadata
127
+
128
+ Proposed addition:
129
+
130
+ ```ts
131
+ interface PanelConfig<T = unknown> {
132
+ id: string
133
+ title: string
134
+ component: ComponentType<PaneProps<T>> | LazyFactory<PaneProps<T>>
135
+ // ...existing fields...
136
+ supportsFullPage?: boolean
137
+ }
138
+ ```
139
+
140
+ And the mirrored front registration shape should carry the same field after
141
+ capture/bootstrap.
142
+
143
+ Rules:
144
+
145
+ - default `false`
146
+ - only `true` panels can be rendered by the dedicated generic full-page route
147
+ - if omitted, panel continues to work exactly as today
148
+
149
+ Opt-in usage:
150
+
151
+ ```ts
152
+ const deckPanel = definePanel<{ path?: string }>({
153
+ id: "deck",
154
+ title: "Deck",
155
+ component: DeckPane,
156
+ placement: "center",
157
+ supportsFullPage: true,
158
+ })
159
+ ```
160
+
161
+ Equivalent declarative plugin example:
162
+
163
+ ```ts
164
+ definePlugin({
165
+ id: "deck-plugin",
166
+ panels: [
167
+ {
168
+ id: "deck",
169
+ label: "Deck",
170
+ component: DeckPane,
171
+ placement: "center",
172
+ supportsFullPage: true,
173
+ },
174
+ ],
175
+ })
176
+ ```
177
+
178
+ Equivalent imperative plugin example:
179
+
180
+ ```ts
181
+ definePlugin({
182
+ id: "deck-plugin",
183
+ setup(api) {
184
+ api.registerPanel({
185
+ id: "deck",
186
+ label: "Deck",
187
+ component: DeckPane,
188
+ placement: "center",
189
+ supportsFullPage: true,
190
+ })
191
+ },
192
+ })
193
+ ```
194
+
195
+ Runtime behavior:
196
+
197
+ 1. route parses `component=<id>`
198
+ 2. full-page renderer resolves that registered panel component from the registry
199
+ 3. renderer checks `supportsFullPage`
200
+ 4. `true` => render panel full-page
201
+ 5. `false`/missing => show a not-supported error state
202
+
203
+ Why opt-in:
204
+
205
+ - many panels assume Dockview chrome/group/container behavior
206
+ - some panels are meaningless outside the workspace shell
207
+ - some panels may depend on `api`/`containerApi` methods that do not make
208
+ sense full-page
209
+ - plugin authors should opt in at the same place they already define panels,
210
+ not through an app-only API
211
+
212
+ ## 2) Full-page route params
213
+
214
+ Keep params tiny and explicit.
215
+
216
+ ```ts
217
+ interface FullPagePanelRouteState {
218
+ componentId: string
219
+ params?: Record<string, unknown>
220
+ }
221
+ ```
222
+
223
+ URL shape in v1:
224
+
225
+ - `?component=<panel-component-id>&params=<urlencoded-json>`
226
+
227
+ Examples:
228
+
229
+ - `/full-page?component=deck&params=%7B%22path%22%3A%22deck%2Fintro.md%22%7D`
230
+ - `/full-page?component=html-viewer&params=%7B%22path%22%3A%22reports%2Fplan.html%22%7D`
231
+
232
+ The path `/full-page` is just an example. The important part is that there is
233
+ one dedicated generic route, not one route per feature.
234
+
235
+ Why JSON-in-query for v1:
236
+
237
+ - generic across panel types
238
+ - avoids route-per-feature explosion
239
+ - easy to build and parse
240
+ - does not require every panel to flatten params into query keys
241
+
242
+ Guardrails:
243
+
244
+ - reject invalid JSON
245
+ - reject non-object params
246
+ - parser does **not** validate panel existence/capability; that belongs in the
247
+ renderer where the registry is available
248
+ - show a simple full-page error state instead of crashing
249
+
250
+ ## 3) URL helpers
251
+
252
+ Split the helpers by who needs them.
253
+
254
+ ### Provider-level route-base config
255
+
256
+ Host apps configure the mounted route path once at the provider/app-shell level.
257
+
258
+ ```ts
259
+ interface WorkspaceProviderProps {
260
+ fullPageBasePath?: string // e.g. "/full-page"
261
+ }
262
+ ```
263
+
264
+ This replaces feature-specific seams like deck's current `getPresentHref(path)`.
265
+ Plugins do not invent paths; the app declares one generic full-page route base.
266
+
267
+ ### Root-package helpers
268
+
269
+ Expose both a pure builder and a context-backed hook from the root package
270
+ export surface (`@hachej/boring-workspace`).
271
+
272
+ ```ts
273
+ interface BuildFullPagePanelHrefInput {
274
+ componentId: string
275
+ params?: Record<string, unknown>
276
+ basePath: string
277
+ }
278
+
279
+ function buildFullPagePanelHref(input: BuildFullPagePanelHrefInput): string
280
+
281
+ function useFullPagePanelHref(input: {
282
+ componentId: string
283
+ params?: Record<string, unknown>
284
+ }): string | null
285
+ ```
286
+
287
+ Behavior:
288
+
289
+ - `buildFullPagePanelHref(...)` is pure and explicit
290
+ - `useFullPagePanelHref(...)` reads `fullPageBasePath` from provider context
291
+ - if the host did not configure a full-page route, the hook returns `null`
292
+
293
+ ### App/front helper
294
+
295
+ Route parser exported from `@hachej/boring-workspace/app/front` for host route
296
+ handling.
297
+
298
+ ```ts
299
+ // Add one canonical app/front error-code module, e.g.
300
+ // packages/workspace/src/app/front/fullPageRouteErrors.ts
301
+ // exported from @hachej/boring-workspace/app/front as:
302
+ // - type WorkspaceFullPageRouteErrorCode = ...
303
+ // - FULL_PAGE_PANEL_MISSING_COMPONENT
304
+ // - FULL_PAGE_PANEL_INVALID_PARAMS_JSON
305
+ // - FULL_PAGE_PANEL_PARAMS_NOT_OBJECT
306
+ // - FULL_PAGE_PANEL_UNKNOWN_COMPONENT
307
+ // - FULL_PAGE_PANEL_NOT_SUPPORTED
308
+ // - FULL_PAGE_PANEL_RENDER_FAILED
309
+
310
+ function parseFullPagePanelLocation(search: string): {
311
+ componentId: string | null
312
+ params: Record<string, unknown>
313
+ error?: {
314
+ code: WorkspaceFullPageRouteErrorCode
315
+ message: string
316
+ }
317
+ }
318
+ ```
319
+
320
+ Host app still decides the pathname. Workspace only standardizes the query
321
+ payload.
322
+
323
+ ## 4) Full-page page component
324
+
325
+ Expose a route/page component from `@hachej/boring-workspace/app/front`.
326
+
327
+ This is an **app-shell-facing** API, distinct from the plugin-facing panel
328
+ contract above.
329
+
330
+ ```ts
331
+ interface WorkspaceFullPagePanelProps {
332
+ componentId: string
333
+ params?: Record<string, unknown>
334
+ notFoundFallback?: ReactNode
335
+ invalidRequestFallback?: ReactNode
336
+ }
337
+
338
+ function WorkspaceFullPagePanel(props: WorkspaceFullPagePanelProps): JSX.Element
339
+ ```
340
+
341
+ Responsibilities:
342
+
343
+ - consume existing `WorkspaceProvider` context already mounted by the host app
344
+ - resolve the registered panel from the panel registry
345
+ - verify `supportsFullPage === true`
346
+ - validate that `params` is URL-serializable object data already parsed from
347
+ the route
348
+ - preserve normal plugin safety expectations (lazy loading, suspense, and panel
349
+ error isolation equivalent to normal panel rendering)
350
+ - supply a full-page render-mode context
351
+ - render the panel outside Dockview with lightweight shims for `api` and
352
+ `containerApi`
353
+
354
+ Non-responsibilities:
355
+
356
+ - mounting `WorkspaceProvider`
357
+ - choosing the browser pathname
358
+ - owning a router implementation
359
+ - inventing feature-specific chrome
360
+
361
+ ## 5) Render-mode context
362
+
363
+ Do **not** widen every panel prop shape just to add `fullPage: boolean`.
364
+
365
+ `PaneProps` is currently the Dockview-owned contract. Changing that ripples into
366
+ many existing panels and tests. The smaller approach is a context hook.
367
+
368
+ This hook belongs on the **root package export surface**, not in `app/front`,
369
+ because plugin panels themselves need to consume it.
370
+
371
+ ```ts
372
+ type PanelRenderMode = "dock" | "full-page"
373
+
374
+ interface PanelRenderContextValue {
375
+ mode: PanelRenderMode
376
+ }
377
+
378
+ function usePanelRenderMode(): PanelRenderMode
379
+ function useIsFullPagePanel(): boolean
380
+ ```
381
+
382
+ Default outside the provider:
383
+
384
+ - `mode = "dock"`
385
+
386
+ Why context over prop in v1:
387
+
388
+ - no mass prop signature churn
389
+ - same panel component can opt in incrementally
390
+ - easy to use in deck/html without forcing all panels to care
391
+
392
+ ## 6) Full-page panel shims
393
+
394
+ A full-page render will not have real Dockview APIs. Provide narrow no-op/
395
+ minimal adapters.
396
+
397
+ Because `PaneProps` currently exposes raw `DockviewPanelApi` / `DockviewApi`
398
+ types, this will likely require a typed shim object plus a narrow cast/proxy at
399
+ the render boundary. Call that out explicitly so the implementation stays honest
400
+ about the cost.
401
+
402
+ ```ts
403
+ function createFullPagePanelApi(panelId: string): PaneProps["api"]
404
+ function createFullPageContainerApi(): PaneProps["containerApi"]
405
+ ```
406
+
407
+ Required minimum:
408
+
409
+ - `api.id`
410
+ - `api.setTitle()` should update document title or local page chrome title
411
+ - `api.close()` can call `window.close()` best-effort, or no-op if blocked
412
+ - other methods should be safe no-ops unless a better behavior is obvious
413
+
414
+ Important constraint:
415
+
416
+ - panels that truly require rich Dockview behavior should not opt in to
417
+ `supportsFullPage`
418
+
419
+ ## Deck behavior on top of this
420
+
421
+ Once the Workspace full-page capability exists, workspace-hosted deck panels
422
+ should use `useFullPagePanelHref(...)` against the host-configured generic
423
+ route.
424
+
425
+ Important scope note:
426
+
427
+ - this generic route primarily replaces the current workspace/plugin path
428
+ - standalone `DeckPane` / `StandaloneDeckRoute` consumers may still need an
429
+ explicit present-link seam temporarily until a separate standalone story is
430
+ finalized
431
+ - so v1 should remove `getPresentHref` from `CreateDeckPluginOptions` and stop
432
+ routing workspace-hosted deck links through that plugin option
433
+ - if standalone deck consumers still need a custom present link after that,
434
+ move the seam to standalone-only deck props instead of leaving it on the
435
+ workspace plugin builder
436
+
437
+ Deck panel behavior:
438
+
439
+ - dock mode:
440
+ - normal read/edit/present toggle
441
+ - full-page mode:
442
+ - default to present mode
443
+ - keep keyboard slide navigation
444
+ - keep the same parser/widgets/content logic
445
+ - optionally reduce non-essential chrome
446
+
447
+ This preserves the user’s original macro UX goal while keeping the solution
448
+ fully generic.
449
+
450
+ ## HTML viewer behavior on top of this
451
+
452
+ HTML viewer can opt into the same route later.
453
+
454
+ Expected behavior:
455
+
456
+ - same `HtmlViewerPane`
457
+ - same file/path params
458
+ - rendered full-page via the generic route
459
+ - no HTML-specific new-tab system needed
460
+
461
+ This is the main proof that the abstraction is not actually deck-specific.
462
+
463
+ ## Route ownership model
464
+
465
+ Workspace should provide the page component and helpers, but the host app should
466
+ still mount the dedicated route.
467
+
468
+ Important constraint: `WorkspaceAgentFront` is the **full shell** today. It does
469
+ not accept arbitrary children and always renders the normal top bar + chat +
470
+ dock layout. So the full-page route cannot simply nest `WorkspaceFullPagePanel`
471
+ inside `WorkspaceAgentFront`.
472
+
473
+ For v1, keep this simple: mount the dedicated full-page pane route under the
474
+ already-public `WorkspaceProvider` directly.
475
+
476
+ Example host wiring:
477
+
478
+ ```tsx
479
+ function App() {
480
+ if (window.location.pathname === "/full-page") {
481
+ const parsed = parseFullPagePanelLocation(window.location.search)
482
+ if (!parsed.componentId) return <InvalidRequest />
483
+
484
+ return (
485
+ <WorkspaceProvider {...sharedWorkspaceProviderProps}>
486
+ <WorkspaceFullPagePanel componentId={parsed.componentId} params={parsed.params} />
487
+ </WorkspaceProvider>
488
+ )
489
+ }
490
+
491
+ return <WorkspaceAgentFront {...sharedWorkspaceAgentFrontProps} />
492
+ }
493
+ ```
494
+
495
+ This keeps routing decisions in the app, keeps the first version small, and
496
+ reuses the existing provider/registry bootstrap that already exists.
497
+
498
+ ## Error handling
499
+
500
+ The full-page panel route must fail softly.
501
+
502
+ Cases:
503
+
504
+ - missing `component`
505
+ - malformed `params`
506
+ - unknown component id
507
+ - panel not opted into `supportsFullPage`
508
+ - panel render crash
509
+
510
+ Expected behavior:
511
+
512
+ - show a simple full-page `ErrorState`
513
+ - never crash the whole app shell
514
+ - route parser returns stable coded failure data instead of throwing raw JSON
515
+ parse errors into React
516
+
517
+ ## Security / trust boundaries
518
+
519
+ This route should not expand trust boundaries beyond what normal Workspace panes
520
+ already have.
521
+
522
+ Notes:
523
+
524
+ - params come from the URL, so panel code must still validate/normalize them
525
+ - file-backed panes should continue using existing path validation/storage APIs
526
+ - this route should not add a new arbitrary code-loading mechanism
527
+ - only already-registered panels can render
528
+
529
+ ## Implementation plan
530
+
531
+ ### Phase 1 — Workspace route contract
532
+
533
+ - add `supportsFullPage?: boolean` to `PanelConfig` / `definePanel` / captured
534
+ panel registrations
535
+ - add `fullPageBasePath?: string` to `WorkspaceProviderProps` (and pass-through
536
+ from `WorkspaceAgentFront`)
537
+ - add root-exported href builder + `useFullPagePanelHref(...)`
538
+ - add `app/front/fullPageRouteErrors.ts` and export stable full-page route
539
+ error codes
540
+ - add route parser in `app/front`
541
+ - add full-page render-mode context/hooks on the root package export surface
542
+ - add full-page panel component with panel lookup + shims + error states
543
+
544
+ ### Phase 2 — Deck migration
545
+
546
+ - mark deck panel as `supportsFullPage: true`
547
+ - switch workspace-hosted deck panel links to `useFullPagePanelHref({ componentId, params })`
548
+ - remove `getPresentHref` from `CreateDeckPluginOptions`
549
+ - if needed, add a standalone-only present-link prop on `DeckPane` /
550
+ `StandaloneDeckRoute` instead of keeping that seam on the plugin builder
551
+ - deck uses render-mode hook to default to present mode when full-page
552
+
553
+ ### Phase 3 — Playground proof
554
+
555
+ - mount one dedicated generic host route in `apps/workspace-playground`
556
+ - add “open in new tab” using that route
557
+ - verify real browser-tab behavior
558
+
559
+ ### Phase 4 — Optional second consumer
560
+
561
+ - opt HTML viewer into `supportsFullPage`
562
+ - prove the abstraction is not deck-only
563
+
564
+ ## Testing
565
+
566
+ ### Unit
567
+
568
+ - URL builder/parser round-trips
569
+ - invalid query shapes fail cleanly
570
+ - panel opt-in enforcement
571
+ - full-page render-mode hook defaults/overrides
572
+ - `api.setTitle()` updates page title in full-page mode
573
+
574
+ ### Integration
575
+
576
+ - `WorkspaceFullPagePanel` renders a registered opted-in test panel
577
+ - non-opted-in panel is rejected with a stable code
578
+ - unknown component is rejected with a stable code
579
+ - panel receives params intact
580
+ - render-mode hook reports `full-page`
581
+ - lazy panel rendering still works
582
+ - full-page panel crash is isolated to the page error state, not an app crash
583
+
584
+ ### Deck-specific
585
+
586
+ - deck defaults to present mode in full-page render mode
587
+ - keyboard nav still works in full-page deck mode
588
+ - edit mode remains normal in dock mode
589
+
590
+ ### Playground / e2e
591
+
592
+ - open deck in workspace
593
+ - click open-in-new-tab
594
+ - new tab opens generic full-page route
595
+ - same deck content renders there
596
+ - keyboard navigation works there
597
+ - original workspace tab remains stable
598
+
599
+ ## Migration / compatibility
600
+
601
+ This should be additive.
602
+
603
+ - existing panels continue unchanged
604
+ - existing app routes continue unchanged
605
+ - macro can keep `/present` temporarily until migrated
606
+ - deck can support both old seam and generic route briefly if needed, but the
607
+ desired end state is to remove the deck-specific route seam once the generic
608
+ route is proven
609
+
610
+ ## Locked decisions / follow-ups
611
+
612
+ 1. Public export ownership
613
+ - export `buildFullPagePanelHref`, `useFullPagePanelHref`,
614
+ `usePanelRenderMode`, and `useIsFullPagePanel` from the root package
615
+ (`@hachej/boring-workspace`)
616
+ - keep the route parser/page in `@hachej/boring-workspace/app/front`
617
+ - follow-up: update docs/examples to show the new imports clearly
618
+ 2. Should params be JSON-in-query or flat query keys?
619
+ - Recommendation: JSON-in-query in v1 for simplicity and genericity.
620
+ - Constraint: full-page-capable panels must treat params as URL-serializable
621
+ data, not callbacks/classes/functions.
622
+ 3. Should deck keep a custom label like “Present” in full-page mode?
623
+ - Recommendation: yes in its own panel UI, but the route stays generic.
624
+ 4. Do we need shareable/stable URLs across sessions right now?
625
+ - Recommendation: no. Keep this local/full-page only in v1.
626
+
627
+ ## Recommendation
628
+
629
+ Build the generic Workspace full-page panel route.
630
+
631
+ It is small, matches the desired UX, avoids deck-specific routing, and creates a
632
+ reusable capability for deck, HTML viewer, and future artifact panes without
633
+ pushing router ownership into the base Workspace package.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hachej/boring-workspace",
3
- "version": "0.1.23",
3
+ "version": "0.1.26",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Workspace UI, plugin, and bridge package for composing chat, files, catalogs, editors, and app-specific panes.",
@@ -130,8 +130,8 @@
130
130
  "tailwind-merge": "^2.0.0",
131
131
  "zod": "^3.23.0",
132
132
  "zustand": "^5.0.0",
133
- "@hachej/boring-agent": "0.1.23",
134
- "@hachej/boring-ui-kit": "0.1.23"
133
+ "@hachej/boring-agent": "0.1.26",
134
+ "@hachej/boring-ui-kit": "0.1.26"
135
135
  },
136
136
  "devDependencies": {
137
137
  "@tailwindcss/postcss": "^4.0.0",
@@ -159,9 +159,9 @@
159
159
  },
160
160
  "scripts": {
161
161
  "dev": "vite",
162
- "build": "pnpm --filter @hachej/boring-ui-kit build && tsup && vite build && node ./scripts/build-workspace-css.mjs && node ./scripts/assert-build-artifacts.mjs",
163
- "typecheck": "pnpm --filter @hachej/boring-ui-kit build && pnpm --filter @hachej/boring-agent build && tsc --noEmit -p tsconfig.front.json && tsc --noEmit -p tsconfig.server.json",
164
- "test": "pnpm --filter @hachej/boring-ui-cli build && vitest run",
162
+ "build": "tsup && vite build && node ./scripts/build-workspace-css.mjs && node ./scripts/assert-build-artifacts.mjs",
163
+ "typecheck": "tsc --noEmit -p tsconfig.front.json && tsc --noEmit -p tsconfig.server.json",
164
+ "test": "vitest run",
165
165
  "check:bundle-size": "node ./scripts/check-bundle-size.mjs",
166
166
  "lint:plugin-invariants": "node ./scripts/check-plugin-invariants.mjs",
167
167
  "lint": "pnpm run typecheck"