@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.
- package/README.md +1 -0
- package/_internal/app/components/agent-select.d.ts +7 -2
- package/_internal/app/components/confirm-dialog.d.ts +33 -0
- package/_internal/app/components/empty-state.d.ts +14 -5
- package/_internal/app/components/ui/badge.d.ts +1 -1
- package/_internal/app/components/ui/button.d.ts +1 -1
- package/_internal/app/hooks/use-content-store.d.ts +0 -9
- package/_internal/app/hooks/use-horizontal-resize.d.ts +22 -0
- package/_internal/app/hooks/use-json-fetch.d.ts +21 -0
- package/_internal/app/hooks/use-nav-badge.d.ts +13 -0
- package/_internal/app/hooks/use-plugin-event.d.ts +19 -0
- package/_internal/app/hooks/use-resizable-pane.d.ts +35 -0
- package/_internal/app/hooks/use-schedule.d.ts +2 -1
- package/_internal/app/hooks/use-task-run-history.d.ts +26 -0
- package/_internal/app/hooks/use-vertical-resize.d.ts +6 -7
- package/_internal/app/types/index.d.ts +1 -105
- package/_internal/core/adapters/runtime/concepts.d.ts +141 -67
- package/_internal/core/adapters/runtime/errors.d.ts +86 -0
- package/_internal/core/adapters/runtime/index.d.ts +3 -1
- package/_internal/core/content-dir.d.ts +1 -0
- package/_internal/core/format.d.ts +9 -0
- package/_internal/core/plugin-types.d.ts +124 -470
- package/_internal/plugins/models/hooks/use-available-models.d.ts +5 -0
- package/_internal/plugins/team/types.d.ts +14 -4
- package/components/index.d.ts +40 -2
- package/components/index.js +15897 -1678
- package/hooks/index.d.ts +69 -8
- package/hooks/index.js +14589 -369
- package/index.d.ts +64 -2
- package/index.js +228 -7
- package/metadata/index.d.ts +14 -1
- package/package.json +1 -1
- package/register.d.ts +45 -9
- package/routing/index.d.ts +6 -1
- package/routing/index.js +13 -1
- package/slots/index.d.ts +16 -24
- package/slots/index.js +196 -30
- package/types/index.d.ts +15 -919
- package/ui/index.js +2 -1
- package/utils/index.d.ts +40 -3
- package/utils/index.js +57 -0
- 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
|
-
|
|
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
|
-
|
|
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/
|
|
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
|
};
|
package/metadata/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
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
|
-
|
|
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;
|
package/routing/index.d.ts
CHANGED
|
@@ -7,5 +7,10 @@
|
|
|
7
7
|
* two parallel `APIRoute<...>` definitions in sync is a debt we are
|
|
8
8
|
* deliberately avoiding.
|
|
9
9
|
*/
|
|
10
|
-
|
|
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
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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 {};
|