elowen-plugin-ui-kit 0.12.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -11,7 +11,7 @@ import type { ComponentType } from 'react';
11
11
  * Deliberately a LITERAL type: the web app re-declares the value and annotates it with
12
12
  * `typeof PLUGIN_UI_API_VERSION`, so a kit bump that forgets the host fails the web typecheck instead
13
13
  * of drifting silently. */
14
- export declare const PLUGIN_UI_API_VERSION: 17;
14
+ export declare const PLUGIN_UI_API_VERSION: 18;
15
15
 
16
16
  /** Public props of `ElowenUiRuntime.components.Slider`. */
17
17
  export interface SliderProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'min' | 'max' | 'step' | 'type'> {
@@ -64,6 +64,7 @@ export interface PluginConfigField {
64
64
  browse?: 'directory';
65
65
  default?: string | number | boolean | string[];
66
66
  providerType?: string | string[];
67
+ modelKind?: 'image';
67
68
  options?: { value: string; label: string }[];
68
69
  language?: string;
69
70
  help?: string;
@@ -192,8 +193,56 @@ export interface PluginUiProject {
192
193
  path: string;
193
194
  notes: string;
194
195
  icon?: string;
196
+ executionKind?: 'host' | 'managed';
197
+ guestRoot?: string;
195
198
  }
196
199
 
200
+ /** One plugin-owned action on a core Project register card. */
201
+ export interface PluginProjectRowAction {
202
+ id: string;
203
+ label: string;
204
+ icon?: string;
205
+ disabled?: boolean;
206
+ tone?: 'danger';
207
+ onSelect: () => void;
208
+ }
209
+
210
+ /** One plugin-owned resource status on a core Project register card. */
211
+ export interface PluginProjectRowStatus {
212
+ label: string;
213
+ icon?: string;
214
+ tone?: 'muted' | 'accent' | 'success' | 'warning' | 'danger';
215
+ busy?: boolean;
216
+ }
217
+
218
+ /** One plugin-owned resource metric. Percent is valid only for a real configured ceiling. */
219
+ export interface PluginProjectRowMetric {
220
+ id: string;
221
+ label: string;
222
+ value: string;
223
+ valueText?: string;
224
+ description?: string;
225
+ percent?: number;
226
+ state: 'ready' | 'absolute' | 'unknown' | 'stopped' | 'unavailable';
227
+ }
228
+
229
+ /** A plugin's contribution to the Project register. Core owns the rows and only renders these optional
230
+ * projections and the plugin-owned overlay. */
231
+ export interface PluginProjectRowContribution {
232
+ status?: Record<number, PluginProjectRowStatus>;
233
+ metrics?: Record<number, {
234
+ label: string;
235
+ items: PluginProjectRowMetric[];
236
+ refreshing?: boolean;
237
+ stale?: boolean;
238
+ staleLabel?: string;
239
+ }>;
240
+ actions?: Record<number, PluginProjectRowAction[]>;
241
+ overlay?: React.ReactNode;
242
+ }
243
+
244
+ export type PluginProjectRowsHook = (input: { projects: PluginUiProject[] }) => PluginProjectRowContribution;
245
+
197
246
  /** The selected core User DTO exposed only to administrator user-detail panels. Compatibility fields stay
198
247
  * present because plugins receive the same object as the host Users screen, not a second partial identity. */
199
248
  export interface PluginUiUser {
@@ -318,11 +367,91 @@ export interface PluginChatArtifactProps {
318
367
  narration?: string;
319
368
  }
320
369
 
370
+ /** Dashboard metric input shared by plugin metric tiles. */
371
+ export interface DashboardMetricProps {
372
+ now: number;
373
+ locale: string;
374
+ monthCostUsd: number | null;
375
+ monthTokens: number;
376
+ }
377
+
378
+ /** A generic card emitted by a plugin tool. The host keeps this wire shape opaque to slot renderers. */
379
+ export interface BrainCard {
380
+ id: string;
381
+ title?: string;
382
+ items?: readonly {
383
+ text: string;
384
+ status?: 'pending' | 'in_progress' | 'completed';
385
+ startedAt?: number;
386
+ id?: string;
387
+ label?: string;
388
+ owner?: string;
389
+ blockedBy?: readonly string[];
390
+ }[];
391
+ body?: string;
392
+ pinned?: boolean;
393
+ }
394
+
395
+ /** The core conversation row handed to a history branch renderer. */
396
+ export interface ConversationRow {
397
+ id: string;
398
+ title: string;
399
+ model: string;
400
+ updated_at: string;
401
+ running: boolean;
402
+ kind: 'conversation' | 'channel' | 'task';
403
+ tokens?: number;
404
+ ownerId?: number;
405
+ ownerLabel?: string;
406
+ platform?: string | null;
407
+ direct?: boolean;
408
+ lastWriterId?: number | null;
409
+ lastWriterLabel?: string | null;
410
+ parentSessionId?: string | null;
411
+ }
412
+
413
+ export interface PluginChatPickerProps {
414
+ plugin: string;
415
+ command: string;
416
+ sessionId: string | null;
417
+ argument?: string;
418
+ send: (text: string) => void;
419
+ close: () => void;
420
+ }
421
+
422
+ export interface PluginChatCardProps {
423
+ card: BrainCard;
424
+ sessionId: string | null;
425
+ live: boolean;
426
+ open: (command?: string) => void;
427
+ }
428
+
429
+ export interface PluginChatRailSectionProps {
430
+ variant: 'expanded' | 'compact';
431
+ sessionId: string | null;
432
+ data: unknown;
433
+ open: (target: string) => void;
434
+ closeMobile?: () => void;
435
+ }
436
+
437
+ export interface PluginHistoryBranchProps {
438
+ parent: ConversationRow;
439
+ items: readonly unknown[];
440
+ expanded: boolean;
441
+ toggle: () => void;
442
+ open: (target: string) => void;
443
+ }
444
+
321
445
  /** What a bundle hands to window.__elowenRegisterPluginUi. Routes are `/`-joined segment patterns
322
446
  * (`''` = the root page, `detail/:id` captures params). Contextual component maps are keyed by their
323
447
  * matching manifest panel ids and mount only in the corresponding host surface. */
324
448
  export interface PluginUiRegistration {
325
449
  requiresApiVersion: number;
450
+ dashboardMetrics?: Record<string, ComponentType<DashboardMetricProps>>;
451
+ chatPickers?: Record<string, ComponentType<PluginChatPickerProps>>;
452
+ chatCards?: Record<string, ComponentType<PluginChatCardProps>>;
453
+ chatRailSections?: Record<string, ComponentType<PluginChatRailSectionProps>>;
454
+ historyBranches?: Record<string, ComponentType<PluginHistoryBranchProps>>;
326
455
  pages?: Record<string, ComponentType<PluginPageProps>>;
327
456
  account?: Record<string, ComponentType<PluginPageProps>>;
328
457
  /** For an `account` entry placed as `linkedAccount`: its one-line claim in the CLOSED Linked accounts
@@ -333,6 +462,8 @@ export interface PluginUiRegistration {
333
462
  accountChip?: Record<string, ComponentType<PluginPageProps>>;
334
463
  user?: Record<string, ComponentType<PluginUserPanelProps>>;
335
464
  project?: Record<string, ComponentType<PluginProjectPanelProps>>;
465
+ /** Actions and overlays contributed to the core Projects register. */
466
+ projectRows?: PluginProjectRowsHook;
336
467
  /** Inline chat views keyed by the artifact `view` selected by the publishing plugin. */
337
468
  chatArtifacts?: Record<string, ComponentType<PluginChatArtifactProps>>;
338
469
  settings?: Record<string, ComponentType<PluginPageProps>>;
@@ -352,6 +483,43 @@ export interface PluginUiRegistration {
352
483
  ownsPageFrame?: string[];
353
484
  }
354
485
 
486
+ /** Every component name `window.ElowenUiRuntime.components` actually carries.
487
+ *
488
+ * This used to be `Record<string, …>`, and an open record is how `C.Progress` reached production: the
489
+ * todo rail asked for a primitive the host had never published, the bundle's own typecheck was happy
490
+ * because any string is a key of an open record, and React was handed `undefined` at render time —
491
+ * which the chat rail shows as "the plugin interface hit an error", naming nothing. The host asserts
492
+ * itself against this union (`web/lib/pluginUi.tsx`), so publishing a primitive without listing it
493
+ * here, or listing one the host does not publish, is a type error on the host side rather than a
494
+ * crash on a user's screen.
495
+ *
496
+ * A bundle that declares its own narrowed view of the runtime — which is the recommended shape, since
497
+ * the runtime cannot publish prop types — runs its key names through `AssertPublished` to get the same
498
+ * check in its own repository. */
499
+ export type PluginUiComponentName =
500
+ | 'ActionMenu' | 'AutoSaveStatus' | 'Avatar' | 'BackendPicker' | 'Badge' | 'BrainModelField'
501
+ | 'Button' | 'Calendar' | 'ChangeStrip' | 'Checkbox' | 'ChoiceField' | 'CompactWorkspaceHeader'
502
+ | 'ConfirmDialog' | 'ContextMenu' | 'ControlSurfaceDocument' | 'ControlSurfaceRegister'
503
+ | 'ControlSurfaceState' | 'ControlSurfaceToolbar' | 'DataTable' | 'DataTableCell'
504
+ | 'DataTableChevronCell' | 'DataTableRow' | 'DataTableSelectCell' | 'DateRangeFilter'
505
+ | 'DetailBlock' | 'DirectoryPicker' | 'EmptyState' | 'EntityList' | 'EntityRow' | 'ErrorState'
506
+ | 'ExecutorPicker' | 'Field' | 'HelpTip' | 'IconButton' | 'Input' | 'LinkedAccountRow' | 'LiveTail'
507
+ | 'LoadingLine' | 'LoadingState' | 'ManageSelectionModal' | 'MarkdownAssetEditor' | 'Modal'
508
+ | 'ModalBody' | 'ModalFooter' | 'ModelCatalogField' | 'ModelIcon' | 'ModuleHeader' | 'MotionLayout'
509
+ | 'MotionLayoutItem' | 'MotionPresence' | 'OperationProgressDialog' | 'OutcomeBadge' | 'PageFilters'
510
+ | 'PageToolbar' | 'Pager' | 'PatchView' | 'PluginConfigEditor' | 'PluginPageFrame'
511
+ | 'PluginPageHeader' | 'PluginSection' | 'Progress' | 'ProgressRibbon' | 'ProjectFilterPills'
512
+ | 'ProjectIcon' | 'ProjectPill' | 'RailSectionHead' | 'ProviderLogo' | 'ProviderPicker' | 'RegisterSearch' | 'Segmented'
513
+ | 'SelectMenu' | 'SelectionSummary' | 'SettingsDocument' | 'SettingsGroup' | 'SettingsRow' | 'Slider'
514
+ | 'SpatialIdentity' | 'SpatialWorkspaceLayout' | 'Spinner' | 'SummaryChip' | 'TimeSeriesChart'
515
+ | 'Toggle' | 'WorkspaceDetailRail' | 'WorkspaceHero' | 'WorkspaceMetric' | 'WorkspacePage'
516
+ | 'WorkspaceShell' | 'WorkspaceTakeover';
517
+
518
+ /** Fails the bundle's own typecheck when it names a component the host does not publish. Used as
519
+ * `export type ComponentName = AssertPublished<keyof Components>` beside a bundle's narrowed runtime
520
+ * declaration, where `Components` carries the real prop types the bundle passes. */
521
+ export type AssertPublished<N extends PluginUiComponentName> = N;
522
+
355
523
  /** The host API surface a bundle finds on `window.ElowenUiRuntime`: the HOST's React instance (a
356
524
  * bundle must never ship its own — the build aliases `react` imports here), a curated set of the
357
525
  * app's UI components, an authenticated same-origin `api` fetch, and SPA navigation. */
@@ -360,7 +528,7 @@ export interface ElowenUiRuntime {
360
528
  react: typeof React;
361
529
  reactDom: typeof ReactDom;
362
530
  jsxRuntime: typeof JsxRuntime;
363
- components: Record<string, ComponentType<never>> & {
531
+ components: Record<PluginUiComponentName, ComponentType<never>> & {
364
532
  AutoSaveStatus: ComponentType<AutoSaveStatusProps>;
365
533
  ProjectIcon: ComponentType<ProjectIconProps>;
366
534
  };
package/index.js CHANGED
@@ -2,4 +2,4 @@
2
2
  * `window.ElowenUiRuntime` stamped with this number; a bundle whose `requiresApiVersion` is NEWER
3
3
  * renders a placeholder instead of executing against a contract it was not built for. Bump whenever
4
4
  * a released bundle requires a newly published `ElowenUiRuntime` contract (see index.d.ts). */
5
- export const PLUGIN_UI_API_VERSION = 17;
5
+ export const PLUGIN_UI_API_VERSION = 18;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elowen-plugin-ui-kit",
3
- "version": "0.12.0",
3
+ "version": "0.13.2",
4
4
  "description": "Contract types and esbuild toolchain for building Elowen plugin browser-UI bundles.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/theme.css CHANGED
@@ -124,7 +124,7 @@
124
124
  --color-success: #32c986;
125
125
  --color-success-foreground: var(--color-primary-foreground);
126
126
  /* Toasts are outcome banners, not tiny status marks. GitHub's Primer success green gives them the
127
- saturated diff/merge signal Filip expects while keeping white body text above AA contrast. */
127
+ saturated diff/merge signal the owner expects while keeping white body text above AA contrast. */
128
128
  --color-toast-success: #1f883d;
129
129
  --color-toast-success-foreground: #ffffff;
130
130
  --color-warning: #edae49;