@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/slots/index.js
CHANGED
|
@@ -1,91 +1,257 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/sdk/src/slots/index.tsx
|
|
3
|
-
import { useSyncExternalStore } from "react";
|
|
3
|
+
import { Component, useEffect, useSyncExternalStore } from "react";
|
|
4
|
+
|
|
5
|
+
// packages/sdk/src/slots/registry.ts
|
|
6
|
+
function getRegistry() {
|
|
7
|
+
const g = globalThis;
|
|
8
|
+
if (!g.__bakinSlotRegistry) {
|
|
9
|
+
g.__bakinSlotRegistry = new Map;
|
|
10
|
+
}
|
|
11
|
+
return g.__bakinSlotRegistry;
|
|
12
|
+
}
|
|
13
|
+
function registerSlot(name, component, order = 100, owner) {
|
|
14
|
+
const reg = getRegistry();
|
|
15
|
+
const entries = reg.get(name) ?? [];
|
|
16
|
+
entries.push({ component, order, owner });
|
|
17
|
+
entries.sort((a, b) => a.order - b.order);
|
|
18
|
+
reg.set(name, entries);
|
|
19
|
+
}
|
|
20
|
+
function getSlotEntries(name) {
|
|
21
|
+
return getRegistry().get(name) ?? [];
|
|
22
|
+
}
|
|
23
|
+
function getSlotNamesOwnedBy(pluginId) {
|
|
24
|
+
const names = [];
|
|
25
|
+
for (const [name, entries] of getRegistry().entries()) {
|
|
26
|
+
if (entries.some((e) => e.owner === pluginId))
|
|
27
|
+
names.push(name);
|
|
28
|
+
}
|
|
29
|
+
return names;
|
|
30
|
+
}
|
|
31
|
+
function clearSlotsOwnedBy(pluginId) {
|
|
32
|
+
const reg = getRegistry();
|
|
33
|
+
for (const [name, entries] of reg.entries()) {
|
|
34
|
+
const filtered = entries.filter((e) => e.owner !== pluginId);
|
|
35
|
+
if (filtered.length === 0)
|
|
36
|
+
reg.delete(name);
|
|
37
|
+
else
|
|
38
|
+
reg.set(name, filtered);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
4
41
|
|
|
5
42
|
// packages/sdk/src/register.ts
|
|
6
43
|
"use client";
|
|
7
44
|
function buildNavItemsSnapshot(registry) {
|
|
8
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
|
+
}
|
|
9
51
|
for (const navItems of registry.navByPlugin.values()) {
|
|
10
52
|
items.push(...navItems);
|
|
11
53
|
}
|
|
12
54
|
return items.sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
|
|
13
55
|
}
|
|
14
|
-
function
|
|
56
|
+
function getRegistry2() {
|
|
15
57
|
const g = globalThis;
|
|
16
58
|
if (!g.__bakinClientRegistry) {
|
|
17
59
|
g.__bakinClientRegistry = {
|
|
18
60
|
navByPlugin: new Map,
|
|
61
|
+
manifestNavByPlugin: new Map,
|
|
19
62
|
routesByPlugin: new Map,
|
|
20
63
|
cleanupByPlugin: new Map,
|
|
21
64
|
navItemsSnapshot: [],
|
|
22
65
|
version: 0,
|
|
23
|
-
listeners: new Set
|
|
66
|
+
listeners: new Set,
|
|
67
|
+
badgesByPlugin: new Map,
|
|
68
|
+
badgesSnapshot: new Map,
|
|
69
|
+
badgeListeners: new Set
|
|
24
70
|
};
|
|
25
71
|
}
|
|
26
72
|
const registry = g.__bakinClientRegistry;
|
|
73
|
+
if (!registry.manifestNavByPlugin)
|
|
74
|
+
registry.manifestNavByPlugin = new Map;
|
|
27
75
|
if (!Array.isArray(registry.navItemsSnapshot)) {
|
|
28
76
|
registry.navItemsSnapshot = buildNavItemsSnapshot(registry);
|
|
29
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;
|
|
30
84
|
return registry;
|
|
31
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
|
+
}
|
|
32
96
|
function getRegistryVersion() {
|
|
33
|
-
return
|
|
97
|
+
return getRegistry2().version;
|
|
34
98
|
}
|
|
35
99
|
function subscribeRegistry(listener) {
|
|
36
|
-
const registry =
|
|
100
|
+
const registry = getRegistry2();
|
|
37
101
|
registry.listeners.add(listener);
|
|
38
102
|
return () => {
|
|
39
103
|
registry.listeners.delete(listener);
|
|
40
104
|
};
|
|
41
105
|
}
|
|
42
106
|
|
|
43
|
-
// packages/sdk/src/
|
|
44
|
-
import { jsxDEV, Fragment } from "react/jsx-dev-runtime";
|
|
107
|
+
// packages/sdk/src/lazy.ts
|
|
45
108
|
"use client";
|
|
46
|
-
function
|
|
109
|
+
function getStore() {
|
|
47
110
|
const g = globalThis;
|
|
48
|
-
if (!g.
|
|
49
|
-
g.
|
|
111
|
+
if (!g.__bakinLazyPluginStore) {
|
|
112
|
+
g.__bakinLazyPluginStore = {
|
|
113
|
+
ownersBySlot: new Map,
|
|
114
|
+
routeOwners: [],
|
|
115
|
+
states: new Map,
|
|
116
|
+
errors: new Map,
|
|
117
|
+
loader: null,
|
|
118
|
+
version: 0,
|
|
119
|
+
listeners: new Set
|
|
120
|
+
};
|
|
50
121
|
}
|
|
51
|
-
return g.
|
|
122
|
+
return g.__bakinLazyPluginStore;
|
|
52
123
|
}
|
|
53
|
-
function
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
124
|
+
function bump() {
|
|
125
|
+
const store = getStore();
|
|
126
|
+
store.version++;
|
|
127
|
+
for (const l of store.listeners) {
|
|
128
|
+
try {
|
|
129
|
+
l();
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.error("[bakin] lazy-plugin listener threw:", err);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
59
134
|
}
|
|
60
|
-
function
|
|
61
|
-
return
|
|
135
|
+
function getPluginLoadState(pluginId) {
|
|
136
|
+
return getStore().states.get(pluginId) ?? "idle";
|
|
62
137
|
}
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
138
|
+
function getPluginLoadError(pluginId) {
|
|
139
|
+
return getStore().errors.get(pluginId);
|
|
140
|
+
}
|
|
141
|
+
function getSlotOwners(name) {
|
|
142
|
+
return getStore().ownersBySlot.get(name) ?? [];
|
|
143
|
+
}
|
|
144
|
+
function demand(pluginIds) {
|
|
145
|
+
const store = getStore();
|
|
146
|
+
if (!store.loader)
|
|
147
|
+
return;
|
|
148
|
+
for (const pluginId of pluginIds) {
|
|
149
|
+
if ((store.states.get(pluginId) ?? "idle") !== "idle")
|
|
150
|
+
continue;
|
|
151
|
+
store.loader(pluginId);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function requestSlotPlugins(name) {
|
|
155
|
+
demand(getSlotOwners(name));
|
|
156
|
+
}
|
|
157
|
+
function retryPluginLoad(pluginId) {
|
|
158
|
+
const store = getStore();
|
|
159
|
+
if (store.states.get(pluginId) !== "error")
|
|
160
|
+
return;
|
|
161
|
+
store.states.set(pluginId, "idle");
|
|
162
|
+
store.errors.delete(pluginId);
|
|
163
|
+
bump();
|
|
164
|
+
demand([pluginId]);
|
|
165
|
+
}
|
|
166
|
+
function getLazyPluginsVersion() {
|
|
167
|
+
return getStore().version;
|
|
168
|
+
}
|
|
169
|
+
function subscribeLazyPlugins(listener) {
|
|
170
|
+
const store = getStore();
|
|
171
|
+
store.listeners.add(listener);
|
|
172
|
+
return () => {
|
|
173
|
+
store.listeners.delete(listener);
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
// packages/sdk/src/slots/index.tsx
|
|
177
|
+
import { jsxDEV, Fragment } from "react/jsx-dev-runtime";
|
|
178
|
+
"use client";
|
|
179
|
+
|
|
180
|
+
class SlotEntryBoundary extends Component {
|
|
181
|
+
state = { error: null };
|
|
182
|
+
static getDerivedStateFromError(error) {
|
|
183
|
+
return { error };
|
|
184
|
+
}
|
|
185
|
+
componentDidCatch(error) {
|
|
186
|
+
console.error(`[bakin] slot "${this.props.slotName}" entry${this.props.owner ? ` from plugin "${this.props.owner}"` : ""} crashed:`, error);
|
|
187
|
+
}
|
|
188
|
+
render() {
|
|
189
|
+
if (this.state.error) {
|
|
190
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
191
|
+
className: "rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",
|
|
192
|
+
role: "alert",
|
|
193
|
+
children: [
|
|
194
|
+
this.props.owner ? `Plugin "${this.props.owner}"` : "A plugin",
|
|
195
|
+
" failed to render this section."
|
|
196
|
+
]
|
|
197
|
+
}, undefined, true, undefined, this);
|
|
198
|
+
}
|
|
199
|
+
return this.props.children;
|
|
71
200
|
}
|
|
72
201
|
}
|
|
202
|
+
function SlotLoadError({ slotName, pluginIds }) {
|
|
203
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
204
|
+
className: "flex flex-col items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive",
|
|
205
|
+
role: "alert",
|
|
206
|
+
children: [
|
|
207
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
208
|
+
children: [
|
|
209
|
+
pluginIds.length === 1 ? `Plugin "${pluginIds[0]}" failed to load` : `Plugins ${pluginIds.map((id) => `"${id}"`).join(", ")} failed to load`,
|
|
210
|
+
getPluginLoadError(pluginIds[0]) ? ` \u2014 ${getPluginLoadError(pluginIds[0])}` : ""
|
|
211
|
+
]
|
|
212
|
+
}, undefined, true, undefined, this),
|
|
213
|
+
/* @__PURE__ */ jsxDEV("button", {
|
|
214
|
+
type: "button",
|
|
215
|
+
className: "rounded border border-destructive/40 px-2 py-1 text-xs hover:bg-destructive/20",
|
|
216
|
+
onClick: () => pluginIds.forEach(retryPluginLoad),
|
|
217
|
+
"aria-label": `Retry loading ${slotName}`,
|
|
218
|
+
children: "Retry"
|
|
219
|
+
}, undefined, false, undefined, this)
|
|
220
|
+
]
|
|
221
|
+
}, undefined, true, undefined, this);
|
|
222
|
+
}
|
|
73
223
|
function Slot({ name, ...props }) {
|
|
74
224
|
useSyncExternalStore(subscribeRegistry, getRegistryVersion, getRegistryVersion);
|
|
225
|
+
useSyncExternalStore(subscribeLazyPlugins, getLazyPluginsVersion, getLazyPluginsVersion);
|
|
226
|
+
useEffect(() => {
|
|
227
|
+
requestSlotPlugins(name);
|
|
228
|
+
}, [name]);
|
|
75
229
|
const entries = getSlotEntries(name);
|
|
76
|
-
if (entries.length === 0)
|
|
230
|
+
if (entries.length === 0) {
|
|
231
|
+
const failed = getSlotOwners(name).filter((id) => getPluginLoadState(id) === "error");
|
|
232
|
+
if (failed.length > 0)
|
|
233
|
+
return /* @__PURE__ */ jsxDEV(SlotLoadError, {
|
|
234
|
+
slotName: name,
|
|
235
|
+
pluginIds: [...failed]
|
|
236
|
+
}, undefined, false, undefined, this);
|
|
77
237
|
return null;
|
|
238
|
+
}
|
|
78
239
|
return /* @__PURE__ */ jsxDEV(Fragment, {
|
|
79
240
|
children: entries.map((entry, i) => {
|
|
80
241
|
const C = entry.component;
|
|
81
|
-
return /* @__PURE__ */ jsxDEV(
|
|
82
|
-
|
|
242
|
+
return /* @__PURE__ */ jsxDEV(SlotEntryBoundary, {
|
|
243
|
+
owner: entry.owner,
|
|
244
|
+
slotName: name,
|
|
245
|
+
children: /* @__PURE__ */ jsxDEV(C, {
|
|
246
|
+
...props
|
|
247
|
+
}, undefined, false, undefined, this)
|
|
83
248
|
}, `${name}-${i}`, false, undefined, this);
|
|
84
249
|
})
|
|
85
250
|
}, undefined, false, undefined, this);
|
|
86
251
|
}
|
|
87
252
|
export {
|
|
88
253
|
registerSlot,
|
|
254
|
+
getSlotNamesOwnedBy,
|
|
89
255
|
getSlotEntries,
|
|
90
256
|
clearSlotsOwnedBy,
|
|
91
257
|
Slot
|