@makinbakin/sdk 0.0.0-bootstrap.0 → 0.0.1-rc.10

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 (40) hide show
  1. package/README.md +21 -10
  2. package/_internal/app/components/agent-select.d.ts +7 -2
  3. package/_internal/app/components/integrated-brainstorm/activity.d.ts +23 -0
  4. package/_internal/app/components/integrated-brainstorm/index.d.ts +6 -1
  5. package/_internal/app/components/integrated-brainstorm/session.d.ts +16 -0
  6. package/_internal/app/components/integrated-brainstorm/sse.d.ts +8 -0
  7. package/_internal/app/components/integrated-brainstorm/types.d.ts +7 -5
  8. package/_internal/app/components/ui/badge.d.ts +1 -1
  9. package/_internal/app/components/ui/button.d.ts +1 -1
  10. package/_internal/app/hooks/use-content-store.d.ts +2 -0
  11. package/_internal/app/hooks/use-nav-badge.d.ts +13 -0
  12. package/_internal/app/types/index.d.ts +0 -42
  13. package/_internal/core/adapters/runtime/concepts.d.ts +119 -2
  14. package/_internal/core/adapters/runtime/index.d.ts +1 -1
  15. package/_internal/core/constants.d.ts +15 -0
  16. package/_internal/core/content-dir.d.ts +42 -0
  17. package/_internal/core/generated-version.d.ts +1 -0
  18. package/_internal/core/logger.d.ts +8 -0
  19. package/_internal/core/plugin-types.d.ts +168 -37
  20. package/_internal/core/routing/index.d.ts +1 -1
  21. package/_internal/plugins/team/types.d.ts +12 -2
  22. package/components/index.d.ts +39 -3
  23. package/components/index.js +16257 -1550
  24. package/hooks/index.d.ts +58 -9
  25. package/hooks/index.js +14414 -413
  26. package/index.d.ts +43 -10
  27. package/index.js +400 -1
  28. package/metadata/index.d.ts +16 -3
  29. package/package.json +2 -2
  30. package/register.d.ts +20 -9
  31. package/routing/index.d.ts +8 -3
  32. package/routing/index.js +327 -0
  33. package/slots/index.d.ts +1 -1
  34. package/slots/index.js +20 -1
  35. package/types/index.d.ts +431 -50
  36. package/ui/index.d.ts +2 -2
  37. package/ui/index.js +2 -1
  38. package/utils/index.d.ts +24 -2
  39. package/utils/index.js +269 -1
  40. package/_internal/app/hooks/use-assets.d.ts +0 -25
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `@bakin/sdk` — plugin author SDK.
2
+ * `@makinbakin/sdk` — plugin author SDK.
3
3
  *
4
4
  * The main entry re-exports types + the single-call `registerPlugin` helper
5
5
  * so plugin authors can write `import { registerPlugin } from '@makinbakin/sdk'`
@@ -8,20 +8,53 @@
8
8
  * `/slots`) to keep the top-level namespace from exploding.
9
9
  *
10
10
  * Sub-paths:
11
- * - `@bakin/sdk/ui` — shadcn UI primitives (Button, Card, Dialog, ...)
12
- * - `@bakin/sdk/hooks` — React hooks (useAgent, useSSE, useSearch, ...)
13
- * - `@bakin/sdk/components` — shared components (PluginHeader, FacetFilter, ...)
14
- * - `@bakin/sdk/slots` — Slot + registerSlot primitive
15
- * - `@bakin/sdk/types` — full type re-exports
16
- * - `@bakin/sdk/metadata` — docs-aware contract helpers
11
+ * - `@makinbakin/sdk/ui` — shadcn UI primitives (Button, Card, Dialog, ...)
12
+ * - `@makinbakin/sdk/hooks` — React hooks (useAgent, useSSE, useSearch, ...)
13
+ * - `@makinbakin/sdk/components` — shared components (PluginHeader, FacetFilter, ...)
14
+ * - `@makinbakin/sdk/slots` — Slot + registerSlot primitive
15
+ * - `@makinbakin/sdk/types` — full type re-exports
16
+ * - `@makinbakin/sdk/metadata` — docs-aware contract helpers
17
17
  *
18
- * Plugin authors: at build time, mark `@bakin/sdk`, `@bakin/sdk/*`, and
18
+ * Plugin authors: at build time, mark `@makinbakin/sdk`, `@makinbakin/sdk/*`, and
19
19
  * `react`/`react-dom` as externals. At runtime the browser's import map
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';
25
53
  export type { ClientRouteEntry, MatchedPluginRoute, NavItem, PluginRegistration } from './register';
26
- export { defineRoute, defineCoreRoute, definePlugin } from './routing/index';
54
+ /** Define a plugin HTTP route with typed input/output schemas. */
55
+ export { defineRoute } from './routing/index';
56
+ /** Define a core (non-plugin) HTTP route. */
57
+ export { defineCoreRoute } from './routing/index';
58
+ /** Compose a plugin's routes into a single definition for the server. */
59
+ export { definePlugin } from './routing/index';
27
60
  export type { APIRoute, HttpStatus, RouteContext, PluginContextLite, CoreContext, BodySpec, ResponseSpec, ParsedInput, } from './routing/index';
package/index.js CHANGED
@@ -60,15 +60,45 @@ function getRegistry2() {
60
60
  cleanupByPlugin: new Map,
61
61
  navItemsSnapshot: [],
62
62
  version: 0,
63
- listeners: new Set
63
+ listeners: new Set,
64
+ badgesByPlugin: new Map,
65
+ badgesSnapshot: new Map,
66
+ badgeListeners: new Set
64
67
  };
65
68
  }
66
69
  const registry = g.__bakinClientRegistry;
67
70
  if (!Array.isArray(registry.navItemsSnapshot)) {
68
71
  registry.navItemsSnapshot = buildNavItemsSnapshot(registry);
69
72
  }
73
+ if (!registry.badgesByPlugin)
74
+ registry.badgesByPlugin = new Map;
75
+ if (!registry.badgesSnapshot)
76
+ registry.badgesSnapshot = buildBadgesSnapshot(registry);
77
+ if (!registry.badgeListeners)
78
+ registry.badgeListeners = new Set;
70
79
  return registry;
71
80
  }
81
+ function buildBadgesSnapshot(registry) {
82
+ const snapshot = new Map;
83
+ for (const byNavItemId of registry.badgesByPlugin.values()) {
84
+ for (const [navItemId, badge] of byNavItemId) {
85
+ if (!snapshot.has(navItemId))
86
+ snapshot.set(navItemId, badge);
87
+ }
88
+ }
89
+ return snapshot;
90
+ }
91
+ function bumpBadges() {
92
+ const registry = getRegistry2();
93
+ registry.badgesSnapshot = buildBadgesSnapshot(registry);
94
+ for (const l of registry.badgeListeners) {
95
+ try {
96
+ l();
97
+ } catch (err) {
98
+ console.error("[bakin] badge listener threw:", err);
99
+ }
100
+ }
101
+ }
72
102
  function bumpVersion() {
73
103
  const registry = getRegistry2();
74
104
  registry.navItemsSnapshot = buildNavItemsSnapshot(registry);
@@ -116,7 +146,10 @@ function unregisterPlugin(id) {
116
146
  registry.navByPlugin.delete(id);
117
147
  registry.routesByPlugin.delete(id);
118
148
  clearSlotsOwnedBy(id);
149
+ const hadBadges = registry.badgesByPlugin.delete(id);
119
150
  bumpVersion();
151
+ if (hadBadges)
152
+ bumpBadges();
120
153
  }
121
154
  function registerPluginCleanup(id, fn) {
122
155
  const registry = getRegistry2();
@@ -143,6 +176,41 @@ function getNavItemsSnapshot() {
143
176
  function getPluginNavItems(pluginId) {
144
177
  return getRegistry2().navByPlugin.get(pluginId) ?? [];
145
178
  }
179
+ function setNavBadge(pluginId, navItemId, badge) {
180
+ const registry = getRegistry2();
181
+ let plugin = registry.badgesByPlugin.get(pluginId);
182
+ if (badge === null) {
183
+ if (!plugin?.has(navItemId))
184
+ return;
185
+ plugin.delete(navItemId);
186
+ if (plugin.size === 0)
187
+ registry.badgesByPlugin.delete(pluginId);
188
+ bumpBadges();
189
+ return;
190
+ }
191
+ const prev = plugin?.get(navItemId);
192
+ if (prev && prev.count === badge.count && prev.tone === badge.tone)
193
+ return;
194
+ if (!plugin) {
195
+ plugin = new Map;
196
+ registry.badgesByPlugin.set(pluginId, plugin);
197
+ }
198
+ plugin.set(navItemId, { count: badge.count, tone: badge.tone });
199
+ bumpBadges();
200
+ }
201
+ function getNavBadge(navItemId) {
202
+ return getRegistry2().badgesSnapshot.get(navItemId);
203
+ }
204
+ function getNavBadgesSnapshot() {
205
+ return getRegistry2().badgesSnapshot;
206
+ }
207
+ function subscribeNavBadges(listener) {
208
+ const registry = getRegistry2();
209
+ registry.badgeListeners.add(listener);
210
+ return () => {
211
+ registry.badgeListeners.delete(listener);
212
+ };
213
+ }
146
214
  function normalizePattern(pattern) {
147
215
  return pattern.split("/").filter(Boolean);
148
216
  }
@@ -13882,6 +13950,333 @@ var errorEnvelope = exports_external.object({
13882
13950
  error: exports_external.string(),
13883
13951
  issues: exports_external.array(exports_external.unknown()).optional()
13884
13952
  });
13953
+
13954
+ // packages/core/src/logger.ts
13955
+ import { createWriteStream, existsSync, mkdirSync, renameSync, statSync } from "fs";
13956
+ import { join as join2 } from "path";
13957
+
13958
+ // packages/core/src/content-dir.ts
13959
+ import { join } from "path";
13960
+ import { homedir } from "os";
13961
+ // packages/core/src/constants.ts
13962
+ var APP_SLUG = "bakin";
13963
+
13964
+ // packages/core/src/content-dir.ts
13965
+ function bakinHomeDefault() {
13966
+ return join(homedir(), `.${APP_SLUG}`);
13967
+ }
13968
+ var resolvedContentDir = null;
13969
+ function isTestEnv() {
13970
+ return process.env.VITEST === "true" || !!process.env.VITEST;
13971
+ }
13972
+ function realBakinHome() {
13973
+ const realHome = process.env.HOME || process.env.USERPROFILE || "";
13974
+ if (!realHome)
13975
+ return "";
13976
+ return join(realHome, `.${APP_SLUG}`);
13977
+ }
13978
+ function assertSafeForTest(path) {
13979
+ if (!isTestEnv())
13980
+ return;
13981
+ const real = realBakinHome();
13982
+ if (real && path === real) {
13983
+ throw new Error(`[bakin] getContentDir() resolved to the real Bakin home (${real}) ` + `during a test run. This would write test data to your production instance. ` + `Fix: mock src/core/content-dir in this test, or set BAKIN_HOME to a temp ` + `directory before importing any Bakin module. See CLAUDE.md \xA7 Testing Rules.`);
13984
+ }
13985
+ }
13986
+ function getContentDir() {
13987
+ if (resolvedContentDir)
13988
+ return resolvedContentDir;
13989
+ const resolved = resolveContentDirInner();
13990
+ assertSafeForTest(resolved);
13991
+ resolvedContentDir = resolved;
13992
+ return resolvedContentDir;
13993
+ }
13994
+ function resolveContentDirInner() {
13995
+ if (process.env.BAKIN_HOME)
13996
+ return process.env.BAKIN_HOME;
13997
+ return bakinHomeDefault();
13998
+ }
13999
+ function getBakinPaths() {
14000
+ const home = getContentDir();
14001
+ const assets = join(home, "assets");
14002
+ return {
14003
+ home,
14004
+ memoryLog: join(home, "MEMORY-LOG.md"),
14005
+ audit: join(home, "audit.jsonl"),
14006
+ assets,
14007
+ "assets.store": join(assets, "store"),
14008
+ "assets.inbox": join(assets, "inbox"),
14009
+ "assets.trash": join(assets, ".trash"),
14010
+ agents: join(home, "agents"),
14011
+ personas: join(home, "team", "personas"),
14012
+ team: join(home, "team"),
14013
+ heartbeats: join(home, "heartbeats"),
14014
+ inbox: join(home, "inbox"),
14015
+ tasks: join(home, "tasks"),
14016
+ workflows: join(home, "workflows"),
14017
+ settings: join(home, "settings.json"),
14018
+ logs: join(home, "logs")
14019
+ };
14020
+ }
14021
+
14022
+ // packages/core/src/logger.ts
14023
+ var MAX_LOG_BYTES = 10 * 1024 * 1024;
14024
+ var LEVEL_RANK = {
14025
+ debug: 10,
14026
+ info: 20,
14027
+ warn: 30,
14028
+ error: 40
14029
+ };
14030
+ var COLOR_RESET = "\x1B[0m";
14031
+ var COLORS = {
14032
+ dim: "\x1B[2m",
14033
+ blue: "\x1B[34m",
14034
+ cyan: "\x1B[36m",
14035
+ green: "\x1B[32m",
14036
+ magenta: "\x1B[35m",
14037
+ red: "\x1B[31m",
14038
+ yellow: "\x1B[33m"
14039
+ };
14040
+ var fileStream = null;
14041
+ var fileTransportInitialized = false;
14042
+ var fileTransportDisabled = false;
14043
+ function fileTransportEnabled() {
14044
+ if (fileTransportDisabled)
14045
+ return false;
14046
+ if (false)
14047
+ ;
14048
+ if (process.env.VITEST)
14049
+ return false;
14050
+ if (process.env.BAKIN_DISABLE_FILE_LOG === "1")
14051
+ return false;
14052
+ return true;
14053
+ }
14054
+ function ensureFileStream() {
14055
+ if (fileTransportInitialized)
14056
+ return fileStream;
14057
+ fileTransportInitialized = true;
14058
+ if (!fileTransportEnabled())
14059
+ return null;
14060
+ try {
14061
+ const logsDir = getBakinPaths().logs;
14062
+ if (!existsSync(logsDir))
14063
+ mkdirSync(logsDir, { recursive: true });
14064
+ const logPath = join2(logsDir, "server.log");
14065
+ if (existsSync(logPath)) {
14066
+ try {
14067
+ const size = statSync(logPath).size;
14068
+ if (size > MAX_LOG_BYTES) {
14069
+ const rotated = join2(logsDir, "server.log.1");
14070
+ renameSync(logPath, rotated);
14071
+ }
14072
+ } catch {}
14073
+ }
14074
+ fileStream = createWriteStream(logPath, { flags: "a" });
14075
+ fileStream.on("error", () => {
14076
+ fileTransportDisabled = true;
14077
+ fileStream = null;
14078
+ });
14079
+ } catch {
14080
+ fileTransportDisabled = true;
14081
+ fileStream = null;
14082
+ }
14083
+ return fileStream;
14084
+ }
14085
+ function formatEntry(entry) {
14086
+ const parts = [`[${entry.ts}] [${entry.level.toUpperCase()}] [${entry.module}] ${entry.message}`];
14087
+ if (entry.error)
14088
+ parts.push(` error: ${entry.error}`);
14089
+ if (entry.data)
14090
+ parts.push(` data: ${JSON.stringify(entry.data)}`);
14091
+ return parts.join(`
14092
+ `);
14093
+ }
14094
+ function consoleFormat() {
14095
+ const configured = process.env.BAKIN_CONSOLE_FORMAT;
14096
+ if (configured === "pretty" || configured === "verbose" || configured === "plain" || configured === "silent") {
14097
+ return configured;
14098
+ }
14099
+ return process.stdout.isTTY === true ? "pretty" : "plain";
14100
+ }
14101
+ function consoleMinLevel(format) {
14102
+ const configured = process.env.BAKIN_LOG_LEVEL;
14103
+ if (configured === "debug" || configured === "info" || configured === "warn" || configured === "error") {
14104
+ return configured;
14105
+ }
14106
+ if (format === "verbose")
14107
+ return "debug";
14108
+ if (format === "silent")
14109
+ return "error";
14110
+ if (format === "pretty")
14111
+ return "info";
14112
+ return "debug";
14113
+ }
14114
+ function colorEnabled(format) {
14115
+ if (format === "plain")
14116
+ return false;
14117
+ if (process.env.NO_COLOR || process.env.BAKIN_NO_COLOR === "1")
14118
+ return false;
14119
+ return process.stdout.isTTY === true;
14120
+ }
14121
+ function colorize(text, color, enabled) {
14122
+ return enabled ? `${COLORS[color]}${text}${COLOR_RESET}` : text;
14123
+ }
14124
+ function sourceLabel(entry) {
14125
+ const data = entry.data;
14126
+ const explicitSource = typeof data?.source === "string" ? data.source : undefined;
14127
+ const pluginId = typeof data?.pluginId === "string" ? data.pluginId : undefined;
14128
+ if (explicitSource === "antfly")
14129
+ return "antfly";
14130
+ if (explicitSource === "dev")
14131
+ return "dev";
14132
+ if (explicitSource === "plugin" && pluginId)
14133
+ return `plugin:${pluginId}`;
14134
+ if (entry.module === "plugin-registry" && pluginId)
14135
+ return `plugin:${pluginId}`;
14136
+ if (entry.module.startsWith("api:"))
14137
+ return "api";
14138
+ return entry.module;
14139
+ }
14140
+ function sourceColor(source) {
14141
+ if (source === "dev")
14142
+ return "cyan";
14143
+ if (source === "server")
14144
+ return "blue";
14145
+ if (source === "antfly")
14146
+ return "magenta";
14147
+ if (source.startsWith("plugin:"))
14148
+ return "green";
14149
+ if (source.includes("search"))
14150
+ return "cyan";
14151
+ if (source.includes("runtime"))
14152
+ return "magenta";
14153
+ return "dim";
14154
+ }
14155
+ function levelColor(level) {
14156
+ if (level === "debug")
14157
+ return "dim";
14158
+ if (level === "warn")
14159
+ return "yellow";
14160
+ if (level === "error")
14161
+ return "red";
14162
+ return "blue";
14163
+ }
14164
+ function isImportantAntflyInfo(entry) {
14165
+ return [
14166
+ "Metadata API server is ready",
14167
+ "Store HTTP server is ready",
14168
+ "Swarm mode: all servers are ready",
14169
+ "Termite's api server starting"
14170
+ ].some((message) => entry.message.includes(message));
14171
+ }
14172
+ function suppressPrettyInfo(entry) {
14173
+ if (entry.level !== "info")
14174
+ return false;
14175
+ if (entry.data?.source === "antfly")
14176
+ return !isImportantAntflyInfo(entry);
14177
+ if (entry.module === "plugin-registry") {
14178
+ return entry.message === "plugin activated" || entry.message.startsWith("Auto-registered ") || entry.message.startsWith("Plugin activation order:");
14179
+ }
14180
+ return [
14181
+ "search-registry",
14182
+ "search-reconcile",
14183
+ "search-cleanup",
14184
+ "hot-reload-coordinator",
14185
+ "mcporter",
14186
+ "dispatch",
14187
+ "watchdog",
14188
+ "doctor",
14189
+ "lifecycle"
14190
+ ].includes(entry.module);
14191
+ }
14192
+ function shouldWriteConsole(entry, format) {
14193
+ if (format === "silent")
14194
+ return false;
14195
+ const minLevel = consoleMinLevel(format);
14196
+ if (LEVEL_RANK[entry.level] < LEVEL_RANK[minLevel])
14197
+ return false;
14198
+ if (format === "pretty" && suppressPrettyInfo(entry))
14199
+ return false;
14200
+ return true;
14201
+ }
14202
+ function formatPrettyEntry(entry, format) {
14203
+ const colors = colorEnabled(format);
14204
+ const time3 = new Date(entry.ts).toTimeString().slice(0, 8);
14205
+ const level = entry.level.padEnd(5);
14206
+ const source = sourceLabel(entry);
14207
+ const label = source.padEnd(18);
14208
+ const levelPart = colorize(level, levelColor(entry.level), colors);
14209
+ const sourcePart = colorize(label, sourceColor(source), colors);
14210
+ const messagePart = entry.level === "error" ? colorize(entry.message, "red", colors) : entry.message;
14211
+ const parts = [`${colorize(time3, "dim", colors)} ${levelPart} ${sourcePart} ${messagePart}`];
14212
+ if (entry.error)
14213
+ parts[0] += ` - ${entry.error}`;
14214
+ if (format === "verbose" && entry.data) {
14215
+ parts.push(` data: ${JSON.stringify(entry.data)}`);
14216
+ }
14217
+ return parts.join(`
14218
+ `);
14219
+ }
14220
+ function formatConsoleEntry(entry) {
14221
+ const format = consoleFormat();
14222
+ if (format === "plain")
14223
+ return formatEntry(entry);
14224
+ if (format === "silent")
14225
+ return "";
14226
+ return formatPrettyEntry(entry, format);
14227
+ }
14228
+ function writeToFile(entry) {
14229
+ const stream = ensureFileStream();
14230
+ if (!stream)
14231
+ return;
14232
+ try {
14233
+ stream.write(JSON.stringify(entry) + `
14234
+ `);
14235
+ } catch {
14236
+ fileTransportDisabled = true;
14237
+ fileStream = null;
14238
+ }
14239
+ }
14240
+ function createLogger(module) {
14241
+ function log(level, message, errorOrData, data) {
14242
+ const entry = {
14243
+ ts: new Date().toISOString(),
14244
+ level,
14245
+ module,
14246
+ message
14247
+ };
14248
+ if (errorOrData instanceof Error) {
14249
+ entry.error = errorOrData.message;
14250
+ entry.data = data ? { ...data, stack: errorOrData.stack } : { stack: errorOrData.stack };
14251
+ } else if (typeof errorOrData === "string") {
14252
+ entry.error = errorOrData;
14253
+ entry.data = data;
14254
+ } else if (errorOrData && typeof errorOrData === "object") {
14255
+ entry.data = errorOrData;
14256
+ }
14257
+ const format = consoleFormat();
14258
+ if (shouldWriteConsole(entry, format)) {
14259
+ const formatted = formatConsoleEntry(entry);
14260
+ if (level === "error") {
14261
+ console.error(formatted);
14262
+ } else if (level === "warn") {
14263
+ console.warn(formatted);
14264
+ } else {
14265
+ console.log(formatted);
14266
+ }
14267
+ }
14268
+ writeToFile(entry);
14269
+ }
14270
+ return {
14271
+ debug: (message, data) => log("debug", message, data),
14272
+ info: (message, data) => log("info", message, data),
14273
+ warn: (message, errorOrData, data) => log("warn", message, errorOrData, data),
14274
+ error: (message, errorOrData, data) => log("error", message, errorOrData, data)
14275
+ };
14276
+ }
14277
+
14278
+ // packages/core/src/routing/dispatcher.ts
14279
+ var log = createLogger("dispatcher");
13885
14280
  // packages/core/src/routing/search-route.ts
13886
14281
  var searchQuery = exports_external.object({
13887
14282
  q: exports_external.string().min(1),
@@ -13903,6 +14298,8 @@ var errorResponse = exports_external.object({ error: exports_external.string() }
13903
14298
  export {
13904
14299
  unregisterPlugin,
13905
14300
  subscribeRegistry,
14301
+ subscribeNavBadges,
14302
+ setNavBadge,
13906
14303
  registerPluginCleanup,
13907
14304
  registerPlugin,
13908
14305
  getRegistryVersion,
@@ -13910,6 +14307,8 @@ export {
13910
14307
  getPluginRoute,
13911
14308
  getPluginNavItems,
13912
14309
  getNavItemsSnapshot,
14310
+ getNavBadgesSnapshot,
14311
+ getNavBadge,
13913
14312
  getAllNavItems,
13914
14313
  defineRoute,
13915
14314
  definePlugin,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `@bakin/sdk/metadata` — docs-aware contract helpers.
2
+ * `@makinbakin/sdk/metadata` — docs-aware contract helpers.
3
3
  *
4
4
  * Re-exports the canonical `RouteContract`, `CliCommandContract`,
5
5
  * `HookContract`, `SlotContract`, `ExecToolContract`, and the corresponding
@@ -10,7 +10,20 @@
10
10
  *
11
11
  * `defineApiRoute` / `definePluginRoute` are kept as re-exports for backward
12
12
  * compatibility with existing call sites; new code should use `defineRoute`
13
- * from `@bakin/sdk/routing` (the typed declarative shape).
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.0-bootstrap.0",
3
+ "version": "0.0.1-rc.10",
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,
@@ -73,7 +73,7 @@
73
73
  "url": "https://github.com/markhayden/bakin/issues"
74
74
  },
75
75
  "author": "markhayden",
76
- "license": "MIT",
76
+ "license": "Apache-2.0",
77
77
  "keywords": [
78
78
  "bakin",
79
79
  "plugin",
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[];
@@ -92,6 +84,25 @@ export declare function getNavItemsSnapshot(): readonly NavItem[];
92
84
  * Nav items for a specific plugin. Returned as a readonly copy.
93
85
  */
94
86
  export declare function getPluginNavItems(pluginId: string): ReadonlyArray<NavItem>;
87
+ /**
88
+ * Set or clear the badge for a nav item owned by a plugin. Pass `null` to
89
+ * clear. Safe to call before the nav item itself is registered — the badge
90
+ * survives in the registry until the owning plugin is unregistered.
91
+ */
92
+ export declare function setNavBadge(pluginId: string, navItemId: string, badge: NavBadge | null): void;
93
+ /** Read the current badge for a nav item, or undefined if none. */
94
+ export declare function getNavBadge(navItemId: string): NavBadge | undefined;
95
+ /**
96
+ * Stable snapshot of every active badge keyed by navItemId. The identity
97
+ * of the returned Map only changes when a badge is set, cleared, or its
98
+ * owning plugin is unregistered — safe for React's `useSyncExternalStore`.
99
+ */
100
+ export declare function getNavBadgesSnapshot(): ReadonlyMap<string, NavBadge>;
101
+ /**
102
+ * Subscribe to badge mutations on a channel separate from `subscribeRegistry`
103
+ * so high-frequency badge ticks don't force the whole nav to re-render.
104
+ */
105
+ export declare function subscribeNavBadges(listener: () => void): () => void;
95
106
  export interface MatchedPluginRoute {
96
107
  pluginId: string;
97
108
  path: string;
@@ -1,11 +1,16 @@
1
1
  /**
2
- * `@bakin/sdk/routing` — typed route contracts for plugin authors.
2
+ * `@makinbakin/sdk/routing` — typed route contracts for plugin authors.
3
3
  *
4
4
  * Re-exports from `@bakin/core/routing` for a single source of truth. The
5
- * SDK's general type module (`@bakin/sdk/types`) keeps duplicated primitives
5
+ * SDK's general type module (`@makinbakin/sdk/types`) keeps duplicated primitives
6
6
  * for self-containment, but the routing surface re-exports because keeping
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';