@makinbakin/sdk 0.0.1-rc.2 → 0.0.1-rc.20

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.
Files changed (42) hide show
  1. package/README.md +1 -0
  2. package/_internal/app/components/agent-select.d.ts +7 -2
  3. package/_internal/app/components/confirm-dialog.d.ts +33 -0
  4. package/_internal/app/components/empty-state.d.ts +14 -5
  5. package/_internal/app/components/ui/badge.d.ts +1 -1
  6. package/_internal/app/components/ui/button.d.ts +1 -1
  7. package/_internal/app/hooks/use-content-store.d.ts +0 -9
  8. package/_internal/app/hooks/use-horizontal-resize.d.ts +22 -0
  9. package/_internal/app/hooks/use-json-fetch.d.ts +21 -0
  10. package/_internal/app/hooks/use-nav-badge.d.ts +13 -0
  11. package/_internal/app/hooks/use-plugin-event.d.ts +19 -0
  12. package/_internal/app/hooks/use-resizable-pane.d.ts +35 -0
  13. package/_internal/app/hooks/use-schedule.d.ts +2 -1
  14. package/_internal/app/hooks/use-task-run-history.d.ts +26 -0
  15. package/_internal/app/hooks/use-vertical-resize.d.ts +6 -7
  16. package/_internal/app/types/index.d.ts +1 -105
  17. package/_internal/core/adapters/runtime/concepts.d.ts +141 -67
  18. package/_internal/core/adapters/runtime/errors.d.ts +86 -0
  19. package/_internal/core/adapters/runtime/index.d.ts +3 -1
  20. package/_internal/core/content-dir.d.ts +1 -0
  21. package/_internal/core/format.d.ts +9 -0
  22. package/_internal/core/plugin-types.d.ts +124 -470
  23. package/_internal/plugins/models/hooks/use-available-models.d.ts +5 -0
  24. package/_internal/plugins/team/types.d.ts +14 -4
  25. package/components/index.d.ts +40 -2
  26. package/components/index.js +15897 -1678
  27. package/hooks/index.d.ts +69 -8
  28. package/hooks/index.js +14589 -369
  29. package/index.d.ts +64 -2
  30. package/index.js +228 -7
  31. package/metadata/index.d.ts +14 -1
  32. package/package.json +1 -1
  33. package/register.d.ts +45 -9
  34. package/routing/index.d.ts +6 -1
  35. package/routing/index.js +13 -1
  36. package/slots/index.d.ts +16 -24
  37. package/slots/index.js +196 -30
  38. package/types/index.d.ts +15 -919
  39. package/ui/index.js +2 -1
  40. package/utils/index.d.ts +40 -3
  41. package/utils/index.js +57 -0
  42. package/_internal/app/hooks/use-assets.d.ts +0 -25
package/index.d.ts CHANGED
@@ -20,8 +20,70 @@
20
20
  * (emitted by Bakin) resolves those to the host's bundled copies so there
21
21
  * is a single React instance and a single SDK.
22
22
  */
23
+ /** Re-exports every plugin contract type. See `@makinbakin/sdk/types` for the full list. */
23
24
  export * from './types/index';
24
- export { registerPlugin, unregisterPlugin, registerPluginCleanup, getRegistryVersion, subscribeRegistry, getAllNavItems, getNavItemsSnapshot, getPluginNavItems, getPluginRoute, getPluginRoutes, } from './register';
25
+ /** Register a plugin (single-call entry from a plugin's `client.tsx`). */
26
+ export { registerPlugin } from './register';
27
+ /** Tear down all registrations owned by a plugin (used during hot-swap). */
28
+ export { unregisterPlugin } from './register';
29
+ /** Register a cleanup callback fired when the plugin is unregistered. */
30
+ export { registerPluginCleanup } from './register';
31
+ /** Current registry version — bumps on every mutation (for useSyncExternalStore). */
32
+ export { getRegistryVersion } from './register';
33
+ /** Subscribe to registry-version changes. */
34
+ export { subscribeRegistry } from './register';
35
+ /** Get every registered nav item across all plugins. */
36
+ export { getAllNavItems } from './register';
37
+ /** Get a snapshot of the current nav items (non-subscribing). */
38
+ export { getNavItemsSnapshot } from './register';
39
+ /** Get nav items contributed by a specific plugin. */
40
+ export { getPluginNavItems } from './register';
41
+ /** Set or clear a runtime badge on a plugin-owned nav item. */
42
+ export { setNavBadge } from './register';
43
+ /** Read the current badge for a nav item, or undefined if none. */
44
+ export { getNavBadge } from './register';
45
+ /** Stable snapshot of every active nav badge keyed by navItemId. */
46
+ export { getNavBadgesSnapshot } from './register';
47
+ /** Subscribe to nav-badge mutations (separate channel from `subscribeRegistry`). */
48
+ export { subscribeNavBadges } from './register';
49
+ /** Look up a specific client route by plugin id + path. */
50
+ export { getPluginRoute } from './register';
51
+ /** Get all registered client routes (across all plugins). */
52
+ export { getPluginRoutes } from './register';
53
+ /** Seed a plugin's declarative nav from its manifest (host-side; survives unregisterPlugin). */
54
+ export { setManifestNav } from './register';
55
+ /** Read the manifest nav currently seeded for a plugin (drift validation). */
56
+ export { getManifestNav } from './register';
25
57
  export type { ClientRouteEntry, MatchedPluginRoute, NavItem, PluginRegistration } from './register';
26
- export { defineRoute, defineCoreRoute, definePlugin } from './routing/index';
58
+ /** Install the manifest-derived slot/route ownership index for lazy loading (host-side). */
59
+ export { configureLazyPlugins } from './lazy/index';
60
+ /** Install the demand loader that imports a plugin's client bundle (host-side). */
61
+ export { setLazyPluginLoader } from './lazy/index';
62
+ /** Report a plugin client's load progress: idle → loading → loaded | error (host-side). */
63
+ export { setPluginLoadState } from './lazy/index';
64
+ /** Current load state for a plugin client. Unknown plugins report 'idle'. */
65
+ export { getPluginLoadState } from './lazy/index';
66
+ /** Last load error message for a plugin whose state is 'error', if any. */
67
+ export { getPluginLoadError } from './lazy/index';
68
+ /** Plugins whose manifests declare the given slot in `contributes.slots`. */
69
+ export { getSlotOwners } from './lazy/index';
70
+ /** Plugins whose manifest `contributes.routes` patterns match a pathname. */
71
+ export { getRouteOwners } from './lazy/index';
72
+ /** Ask the host to lazy-load every idle plugin that fills the named slot. */
73
+ export { requestSlotPlugins } from './lazy/index';
74
+ /** Ask the host to lazy-load every idle plugin whose route patterns match the pathname. */
75
+ export { requestRoutePlugins } from './lazy/index';
76
+ /** Reset a failed plugin to idle and re-request its client bundle. */
77
+ export { retryPluginLoad } from './lazy/index';
78
+ /** Monotonic lazy-store version for useSyncExternalStore consumers. */
79
+ export { getLazyPluginsVersion } from './lazy/index';
80
+ /** Subscribe to lazy-plugin store mutations. Returns an unsubscribe fn. */
81
+ export { subscribeLazyPlugins } from './lazy/index';
82
+ export type { LazyPluginIndex, PluginLoadState } from './lazy/index';
83
+ /** Define a plugin HTTP route with typed input/output schemas. */
84
+ export { defineRoute } from './routing/index';
85
+ /** Define a core (non-plugin) HTTP route. */
86
+ export { defineCoreRoute } from './routing/index';
87
+ /** Compose a plugin's routes into a single definition for the server. */
88
+ export { definePlugin } from './routing/index';
27
89
  export type { APIRoute, HttpStatus, RouteContext, PluginContextLite, CoreContext, BodySpec, ResponseSpec, ParsedInput, } from './routing/index';
package/index.js CHANGED
@@ -13,10 +13,7 @@ var __export = (target, all) => {
13
13
  set: __exportSetter.bind(all, name)
14
14
  });
15
15
  };
16
- // packages/sdk/src/slots/index.tsx
17
- import { useSyncExternalStore } from "react";
18
- import { jsxDEV, Fragment } from "react/jsx-dev-runtime";
19
- "use client";
16
+ // packages/sdk/src/slots/registry.ts
20
17
  function getRegistry() {
21
18
  const g = globalThis;
22
19
  if (!g.__bakinSlotRegistry) {
@@ -46,6 +43,11 @@ function clearSlotsOwnedBy(pluginId) {
46
43
  "use client";
47
44
  function buildNavItemsSnapshot(registry) {
48
45
  const items = [];
46
+ for (const [pluginId, navItems] of registry.manifestNavByPlugin.entries()) {
47
+ if (registry.navByPlugin.has(pluginId))
48
+ continue;
49
+ items.push(...navItems);
50
+ }
49
51
  for (const navItems of registry.navByPlugin.values()) {
50
52
  items.push(...navItems);
51
53
  }
@@ -56,19 +58,52 @@ function getRegistry2() {
56
58
  if (!g.__bakinClientRegistry) {
57
59
  g.__bakinClientRegistry = {
58
60
  navByPlugin: new Map,
61
+ manifestNavByPlugin: new Map,
59
62
  routesByPlugin: new Map,
60
63
  cleanupByPlugin: new Map,
61
64
  navItemsSnapshot: [],
62
65
  version: 0,
63
- listeners: new Set
66
+ listeners: new Set,
67
+ badgesByPlugin: new Map,
68
+ badgesSnapshot: new Map,
69
+ badgeListeners: new Set
64
70
  };
65
71
  }
66
72
  const registry = g.__bakinClientRegistry;
73
+ if (!registry.manifestNavByPlugin)
74
+ registry.manifestNavByPlugin = new Map;
67
75
  if (!Array.isArray(registry.navItemsSnapshot)) {
68
76
  registry.navItemsSnapshot = buildNavItemsSnapshot(registry);
69
77
  }
78
+ if (!registry.badgesByPlugin)
79
+ registry.badgesByPlugin = new Map;
80
+ if (!registry.badgesSnapshot)
81
+ registry.badgesSnapshot = buildBadgesSnapshot(registry);
82
+ if (!registry.badgeListeners)
83
+ registry.badgeListeners = new Set;
70
84
  return registry;
71
85
  }
86
+ function buildBadgesSnapshot(registry) {
87
+ const snapshot = new Map;
88
+ for (const byNavItemId of registry.badgesByPlugin.values()) {
89
+ for (const [navItemId, badge] of byNavItemId) {
90
+ if (!snapshot.has(navItemId))
91
+ snapshot.set(navItemId, badge);
92
+ }
93
+ }
94
+ return snapshot;
95
+ }
96
+ function bumpBadges() {
97
+ const registry = getRegistry2();
98
+ registry.badgesSnapshot = buildBadgesSnapshot(registry);
99
+ for (const l of registry.badgeListeners) {
100
+ try {
101
+ l();
102
+ } catch (err) {
103
+ console.error("[bakin] badge listener threw:", err);
104
+ }
105
+ }
106
+ }
72
107
  function bumpVersion() {
73
108
  const registry = getRegistry2();
74
109
  registry.navItemsSnapshot = buildNavItemsSnapshot(registry);
@@ -116,7 +151,10 @@ function unregisterPlugin(id) {
116
151
  registry.navByPlugin.delete(id);
117
152
  registry.routesByPlugin.delete(id);
118
153
  clearSlotsOwnedBy(id);
154
+ const hadBadges = registry.badgesByPlugin.delete(id);
119
155
  bumpVersion();
156
+ if (hadBadges)
157
+ bumpBadges();
120
158
  }
121
159
  function registerPluginCleanup(id, fn) {
122
160
  const registry = getRegistry2();
@@ -124,6 +162,23 @@ function registerPluginCleanup(id, fn) {
124
162
  list.push(fn);
125
163
  registry.cleanupByPlugin.set(id, list);
126
164
  }
165
+ function setManifestNav(pluginId, navItems) {
166
+ const registry = getRegistry2();
167
+ if (!navItems || navItems.length === 0) {
168
+ if (!registry.manifestNavByPlugin.delete(pluginId))
169
+ return;
170
+ bumpVersion();
171
+ return;
172
+ }
173
+ const prev = registry.manifestNavByPlugin.get(pluginId);
174
+ if (prev && JSON.stringify(prev) === JSON.stringify(navItems))
175
+ return;
176
+ registry.manifestNavByPlugin.set(pluginId, navItems);
177
+ bumpVersion();
178
+ }
179
+ function getManifestNav(pluginId) {
180
+ return getRegistry2().manifestNavByPlugin.get(pluginId) ?? [];
181
+ }
127
182
  function getRegistryVersion() {
128
183
  return getRegistry2().version;
129
184
  }
@@ -143,6 +198,41 @@ function getNavItemsSnapshot() {
143
198
  function getPluginNavItems(pluginId) {
144
199
  return getRegistry2().navByPlugin.get(pluginId) ?? [];
145
200
  }
201
+ function setNavBadge(pluginId, navItemId, badge) {
202
+ const registry = getRegistry2();
203
+ let plugin = registry.badgesByPlugin.get(pluginId);
204
+ if (badge === null) {
205
+ if (!plugin?.has(navItemId))
206
+ return;
207
+ plugin.delete(navItemId);
208
+ if (plugin.size === 0)
209
+ registry.badgesByPlugin.delete(pluginId);
210
+ bumpBadges();
211
+ return;
212
+ }
213
+ const prev = plugin?.get(navItemId);
214
+ if (prev && prev.count === badge.count && prev.tone === badge.tone)
215
+ return;
216
+ if (!plugin) {
217
+ plugin = new Map;
218
+ registry.badgesByPlugin.set(pluginId, plugin);
219
+ }
220
+ plugin.set(navItemId, { count: badge.count, tone: badge.tone });
221
+ bumpBadges();
222
+ }
223
+ function getNavBadge(navItemId) {
224
+ return getRegistry2().badgesSnapshot.get(navItemId);
225
+ }
226
+ function getNavBadgesSnapshot() {
227
+ return getRegistry2().badgesSnapshot;
228
+ }
229
+ function subscribeNavBadges(listener) {
230
+ const registry = getRegistry2();
231
+ registry.badgeListeners.add(listener);
232
+ return () => {
233
+ registry.badgeListeners.delete(listener);
234
+ };
235
+ }
146
236
  function normalizePattern(pattern) {
147
237
  return pattern.split("/").filter(Boolean);
148
238
  }
@@ -200,6 +290,107 @@ function getPluginRoutes(pluginId) {
200
290
  return registry.routesByPlugin.get(pluginId) ?? [];
201
291
  return [...registry.routesByPlugin.values()].flat();
202
292
  }
293
+ // packages/sdk/src/lazy.ts
294
+ "use client";
295
+ function getStore() {
296
+ const g = globalThis;
297
+ if (!g.__bakinLazyPluginStore) {
298
+ g.__bakinLazyPluginStore = {
299
+ ownersBySlot: new Map,
300
+ routeOwners: [],
301
+ states: new Map,
302
+ errors: new Map,
303
+ loader: null,
304
+ version: 0,
305
+ listeners: new Set
306
+ };
307
+ }
308
+ return g.__bakinLazyPluginStore;
309
+ }
310
+ function bump() {
311
+ const store = getStore();
312
+ store.version++;
313
+ for (const l of store.listeners) {
314
+ try {
315
+ l();
316
+ } catch (err) {
317
+ console.error("[bakin] lazy-plugin listener threw:", err);
318
+ }
319
+ }
320
+ }
321
+ function configureLazyPlugins(index) {
322
+ const store = getStore();
323
+ store.ownersBySlot = new Map(index.slotOwners);
324
+ store.routeOwners = [...index.routeOwners];
325
+ bump();
326
+ }
327
+ function setLazyPluginLoader(loader) {
328
+ getStore().loader = loader;
329
+ }
330
+ function setPluginLoadState(pluginId, state, error) {
331
+ const store = getStore();
332
+ if (store.states.get(pluginId) === state && store.errors.get(pluginId) === error)
333
+ return;
334
+ store.states.set(pluginId, state);
335
+ if (state === "error" && error)
336
+ store.errors.set(pluginId, error);
337
+ else
338
+ store.errors.delete(pluginId);
339
+ bump();
340
+ }
341
+ function getPluginLoadState(pluginId) {
342
+ return getStore().states.get(pluginId) ?? "idle";
343
+ }
344
+ function getPluginLoadError(pluginId) {
345
+ return getStore().errors.get(pluginId);
346
+ }
347
+ function getSlotOwners(name) {
348
+ return getStore().ownersBySlot.get(name) ?? [];
349
+ }
350
+ function getRouteOwners(pathname) {
351
+ const owners = [];
352
+ for (const { pattern, pluginId } of getStore().routeOwners) {
353
+ if (matchRoutePattern(pattern, pathname) && !owners.includes(pluginId)) {
354
+ owners.push(pluginId);
355
+ }
356
+ }
357
+ return owners;
358
+ }
359
+ function demand(pluginIds) {
360
+ const store = getStore();
361
+ if (!store.loader)
362
+ return;
363
+ for (const pluginId of pluginIds) {
364
+ if ((store.states.get(pluginId) ?? "idle") !== "idle")
365
+ continue;
366
+ store.loader(pluginId);
367
+ }
368
+ }
369
+ function requestSlotPlugins(name) {
370
+ demand(getSlotOwners(name));
371
+ }
372
+ function requestRoutePlugins(pathname) {
373
+ demand(getRouteOwners(pathname));
374
+ }
375
+ function retryPluginLoad(pluginId) {
376
+ const store = getStore();
377
+ if (store.states.get(pluginId) !== "error")
378
+ return;
379
+ store.states.set(pluginId, "idle");
380
+ store.errors.delete(pluginId);
381
+ bump();
382
+ demand([pluginId]);
383
+ }
384
+ function getLazyPluginsVersion() {
385
+ return getStore().version;
386
+ }
387
+ function subscribeLazyPlugins(listener) {
388
+ const store = getStore();
389
+ store.listeners.add(listener);
390
+ return () => {
391
+ store.listeners.delete(listener);
392
+ };
393
+ }
203
394
  // packages/core/src/routing/define.ts
204
395
  function defineRoute(route) {
205
396
  return route;
@@ -13947,7 +14138,8 @@ function getBakinPaths() {
13947
14138
  tasks: join(home, "tasks"),
13948
14139
  workflows: join(home, "workflows"),
13949
14140
  settings: join(home, "settings.json"),
13950
- logs: join(home, "logs")
14141
+ logs: join(home, "logs"),
14142
+ db: join(home, "bakin.db")
13951
14143
  };
13952
14144
  }
13953
14145
 
@@ -14111,11 +14303,22 @@ function suppressPrettyInfo(entry) {
14111
14303
  }
14112
14304
  return [
14113
14305
  "search-registry",
14306
+ "search-registry-core",
14307
+ "search-plugin-api",
14308
+ "search-reindex",
14309
+ "search-query",
14114
14310
  "search-reconcile",
14115
14311
  "search-cleanup",
14312
+ "search-startup",
14116
14313
  "hot-reload-coordinator",
14117
14314
  "mcporter",
14118
14315
  "dispatch",
14316
+ "dispatch-state",
14317
+ "dispatch-turns",
14318
+ "dispatch-session-death",
14319
+ "dispatch-workflow",
14320
+ "dispatch-cycle",
14321
+ "dispatch-single",
14119
14322
  "watchdog",
14120
14323
  "doctor",
14121
14324
  "lifecycle"
@@ -14230,15 +14433,33 @@ var errorResponse = exports_external.object({ error: exports_external.string() }
14230
14433
  export {
14231
14434
  unregisterPlugin,
14232
14435
  subscribeRegistry,
14436
+ subscribeNavBadges,
14437
+ subscribeLazyPlugins,
14438
+ setPluginLoadState,
14439
+ setNavBadge,
14440
+ setManifestNav,
14441
+ setLazyPluginLoader,
14442
+ retryPluginLoad,
14443
+ requestSlotPlugins,
14444
+ requestRoutePlugins,
14233
14445
  registerPluginCleanup,
14234
14446
  registerPlugin,
14447
+ getSlotOwners,
14448
+ getRouteOwners,
14235
14449
  getRegistryVersion,
14236
14450
  getPluginRoutes,
14237
14451
  getPluginRoute,
14238
14452
  getPluginNavItems,
14453
+ getPluginLoadState,
14454
+ getPluginLoadError,
14239
14455
  getNavItemsSnapshot,
14456
+ getNavBadgesSnapshot,
14457
+ getNavBadge,
14458
+ getManifestNav,
14459
+ getLazyPluginsVersion,
14240
14460
  getAllNavItems,
14241
14461
  defineRoute,
14242
14462
  definePlugin,
14243
- defineCoreRoute
14463
+ defineCoreRoute,
14464
+ configureLazyPlugins
14244
14465
  };
@@ -13,4 +13,17 @@
13
13
  * from `@makinbakin/sdk/routing` (the typed declarative shape).
14
14
  */
15
15
  export type { ContractMetadata, ContractStability, ContractVisibility, CliCommandContract, DocsAwareAPIRoute, DocsExample, ExecToolContract, HookContract, HookKind, PublicContract, RouteContract, SchemaLike, SlotContract, SourceLocation, } from '../_internal/core/docs';
16
- export { defineApiRoute, defineCliCommandContract, defineExecToolContract, defineHookContract, definePluginRoute, defineRouteContract, defineSlotContract, } from '../_internal/core/docs';
16
+ /** Legacy: declare an API route with docs metadata. Prefer `defineRoute` from `/routing`. */
17
+ export { defineApiRoute } from '../_internal/core/docs';
18
+ /** Define a CLI command contract for documentation. */
19
+ export { defineCliCommandContract } from '../_internal/core/docs';
20
+ /** Define an MCP exec tool contract for documentation. */
21
+ export { defineExecToolContract } from '../_internal/core/docs';
22
+ /** Define a cross-plugin hook contract for documentation. */
23
+ export { defineHookContract } from '../_internal/core/docs';
24
+ /** Legacy: declare a plugin route with docs metadata. Prefer `defineRoute` from `/routing`. */
25
+ export { definePluginRoute } from '../_internal/core/docs';
26
+ /** Define a generic route contract (shared shape for API + plugin routes). */
27
+ export { defineRouteContract } from '../_internal/core/docs';
28
+ /** Define a UI slot contract for documentation. */
29
+ export { defineSlotContract } from '../_internal/core/docs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makinbakin/sdk",
3
- "version": "0.0.1-rc.2",
3
+ "version": "0.0.1-rc.20",
4
4
  "description": "SDK for building Bakin plugins — UI components, slot types, hooks, and the runtime registerPlugin helper.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
package/register.d.ts CHANGED
@@ -17,15 +17,7 @@
17
17
  * nav + slot trees re-render when plugins come or go at runtime.
18
18
  */
19
19
  import type { ComponentType } from 'react';
20
- interface NavItem {
21
- id: string;
22
- label: string;
23
- icon?: string;
24
- href?: string;
25
- order?: number;
26
- alwaysExpanded?: boolean;
27
- children?: NavItem[];
28
- }
20
+ import type { NavBadge, NavItem } from './types/index';
29
21
  interface PluginRegistration {
30
22
  id: string;
31
23
  navItems?: NavItem[];
@@ -68,6 +60,23 @@ export declare function unregisterPlugin(id: string): void;
68
60
  * use this to hook into the unified teardown path.
69
61
  */
70
62
  export declare function registerPluginCleanup(id: string, fn: () => void): void;
63
+ /**
64
+ * Seed (or replace) a plugin's declarative nav from its manifest
65
+ * `contributes.nav`. Called by the host's PluginHost after every manifest
66
+ * fetch — including hot-swap refreshes — so the sidebar renders before any
67
+ * client bundle loads. Pass `null` (or an empty array) to clear.
68
+ *
69
+ * Manifest nav lives on its own map: `unregisterPlugin` never touches it,
70
+ * and a plugin that registers `navItems` at runtime overrides its manifest
71
+ * nav while registered (the conditional-nav escape hatch).
72
+ */
73
+ export declare function setManifestNav(pluginId: string, navItems: NavItem[] | null): void;
74
+ /**
75
+ * The declarative manifest nav currently seeded for a plugin (empty if none).
76
+ * Used by the drift validation check to compare manifest nav against what a
77
+ * loaded client registered at runtime.
78
+ */
79
+ export declare function getManifestNav(pluginId: string): ReadonlyArray<NavItem>;
71
80
  /**
72
81
  * Monotonic counter bumped on every register / unregister. Used with
73
82
  * React's `useSyncExternalStore` (via `subscribeRegistry`) so the shell
@@ -92,6 +101,33 @@ export declare function getNavItemsSnapshot(): readonly NavItem[];
92
101
  * Nav items for a specific plugin. Returned as a readonly copy.
93
102
  */
94
103
  export declare function getPluginNavItems(pluginId: string): ReadonlyArray<NavItem>;
104
+ /**
105
+ * Set or clear the badge for a nav item owned by a plugin. Pass `null` to
106
+ * clear. Safe to call before the nav item itself is registered — the badge
107
+ * survives in the registry until the owning plugin is unregistered.
108
+ */
109
+ export declare function setNavBadge(pluginId: string, navItemId: string, badge: NavBadge | null): void;
110
+ /** Read the current badge for a nav item, or undefined if none. */
111
+ export declare function getNavBadge(navItemId: string): NavBadge | undefined;
112
+ /**
113
+ * Stable snapshot of every active badge keyed by navItemId. The identity
114
+ * of the returned Map only changes when a badge is set, cleared, or its
115
+ * owning plugin is unregistered — safe for React's `useSyncExternalStore`.
116
+ */
117
+ export declare function getNavBadgesSnapshot(): ReadonlyMap<string, NavBadge>;
118
+ /**
119
+ * Subscribe to badge mutations on a channel separate from `subscribeRegistry`
120
+ * so high-frequency badge ticks don't force the whole nav to re-render.
121
+ */
122
+ export declare function subscribeNavBadges(listener: () => void): () => void;
123
+ /**
124
+ * Match a route pattern (`/projects/[id]`, `/x/:id`, `/y/$id`) against a
125
+ * concrete pathname. Internal SDK helper shared with the lazy-loading index.
126
+ */
127
+ export declare function matchRoutePattern(pattern: string, pathname: string): {
128
+ params: Record<string, string>;
129
+ score: number;
130
+ } | null;
95
131
  export interface MatchedPluginRoute {
96
132
  pluginId: string;
97
133
  path: string;
@@ -7,5 +7,10 @@
7
7
  * two parallel `APIRoute<...>` definitions in sync is a debt we are
8
8
  * deliberately avoiding.
9
9
  */
10
- export { defineRoute, defineCoreRoute, definePlugin, } from '../_internal/core/routing';
10
+ /** Define a plugin HTTP route with typed input/output and handler. */
11
+ export { defineRoute } from '../_internal/core/routing';
12
+ /** Define a core (non-plugin) HTTP route. */
13
+ export { defineCoreRoute } from '../_internal/core/routing';
14
+ /** Compose a plugin's routes into a single definition for the server. */
15
+ export { definePlugin } from '../_internal/core/routing';
11
16
  export type { HttpMethod, HttpStatus, RouteContext, PluginContextLite, CoreContext, JsonBodySpec, MultipartBodySpec, RawBodySpec, NoBodySpec, BodySpec, JsonResponseSpec, NoContentResponseSpec, NonJsonResponseSpec, ResponseSpec, ParsedInput, APIRoute, PluginWithRoutes, DefinePluginInput, } from '../_internal/core/routing';
package/routing/index.js CHANGED
@@ -13761,7 +13761,8 @@ function getBakinPaths() {
13761
13761
  tasks: join(home, "tasks"),
13762
13762
  workflows: join(home, "workflows"),
13763
13763
  settings: join(home, "settings.json"),
13764
- logs: join(home, "logs")
13764
+ logs: join(home, "logs"),
13765
+ db: join(home, "bakin.db")
13765
13766
  };
13766
13767
  }
13767
13768
 
@@ -13925,11 +13926,22 @@ function suppressPrettyInfo(entry) {
13925
13926
  }
13926
13927
  return [
13927
13928
  "search-registry",
13929
+ "search-registry-core",
13930
+ "search-plugin-api",
13931
+ "search-reindex",
13932
+ "search-query",
13928
13933
  "search-reconcile",
13929
13934
  "search-cleanup",
13935
+ "search-startup",
13930
13936
  "hot-reload-coordinator",
13931
13937
  "mcporter",
13932
13938
  "dispatch",
13939
+ "dispatch-state",
13940
+ "dispatch-turns",
13941
+ "dispatch-session-death",
13942
+ "dispatch-workflow",
13943
+ "dispatch-cycle",
13944
+ "dispatch-single",
13933
13945
  "watchdog",
13934
13946
  "doctor",
13935
13947
  "lifecycle"
package/slots/index.d.ts CHANGED
@@ -19,29 +19,15 @@
19
19
  * Registration happens at plugin client-module load time (import side effect).
20
20
  * Test-only helpers are not exported — tests use the public unregister path.
21
21
  */
22
- import { type ComponentType, type JSX } from 'react';
23
- interface SlotEntry {
24
- component: ComponentType<Record<string, unknown>>;
25
- order: number;
26
- owner?: string;
27
- }
28
- /**
29
- * Register a component for a named slot. Lower `order` renders first; entries
30
- * with the same order render in registration order. Default `order` is 100.
31
- * `owner` is the pluginId for teardown-on-hot-swap; omit in test setups.
32
- */
33
- export declare function registerSlot<TProps>(name: string, component: ComponentType<TProps>, order?: number, owner?: string): void;
34
- /**
35
- * Read the registered entries for a slot. Exported for tooling / tests.
36
- */
37
- export declare function getSlotEntries(name: string): ReadonlyArray<SlotEntry>;
38
- /**
39
- * Remove every slot entry owned by the given plugin. Used by
40
- * `unregisterPlugin` during v2 hot-swap. Entries without an `owner`
41
- * (test registrations, pre-v2 legacy registrations) survive — callers
42
- * that want to wipe unowned entries should re-register them after.
43
- */
44
- export declare function clearSlotsOwnedBy(pluginId: string): void;
22
+ import { type JSX } from 'react';
23
+ /** Register a component for a named slot. Lower `order` renders first; default `order` is 100. */
24
+ export { registerSlot } from './registry/index';
25
+ /** Read the registered entries for a slot. Exported for tooling / tests. */
26
+ export { getSlotEntries } from './registry/index';
27
+ /** Slot names with at least one entry owned by the given plugin (manifest drift checks). */
28
+ export { getSlotNamesOwnedBy } from './registry/index';
29
+ /** Remove every slot entry owned by the given plugin (hot-swap teardown). */
30
+ export { clearSlotsOwnedBy } from './registry/index';
45
31
  interface SlotProps {
46
32
  name: string;
47
33
  [key: string]: unknown;
@@ -50,6 +36,12 @@ interface SlotProps {
50
36
  * Render all components registered for the named slot, in order. Extra props
51
37
  * are passed through to every registered component unchanged. Returns `null`
52
38
  * if nothing is registered.
39
+ *
40
+ * Lazy loading: rendering a slot is a demand signal — if a manifest declares
41
+ * an owner for this slot whose client bundle hasn't loaded yet, the host's
42
+ * loader fires and the slot re-renders once `registerPlugin` runs. While an
43
+ * owner is loading the slot renders nothing (page slots resolve in one
44
+ * paint on the LAN); if an owner's bundle failed to import, an inline error
45
+ * with a retry button renders instead of silent emptiness.
53
46
  */
54
47
  export declare function Slot({ name, ...props }: SlotProps): JSX.Element | null;
55
- export {};