@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.
- package/README.md +21 -10
- package/_internal/app/components/agent-select.d.ts +7 -2
- package/_internal/app/components/integrated-brainstorm/activity.d.ts +23 -0
- package/_internal/app/components/integrated-brainstorm/index.d.ts +6 -1
- package/_internal/app/components/integrated-brainstorm/session.d.ts +16 -0
- package/_internal/app/components/integrated-brainstorm/sse.d.ts +8 -0
- package/_internal/app/components/integrated-brainstorm/types.d.ts +7 -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 +2 -0
- package/_internal/app/hooks/use-nav-badge.d.ts +13 -0
- package/_internal/app/types/index.d.ts +0 -42
- package/_internal/core/adapters/runtime/concepts.d.ts +119 -2
- package/_internal/core/adapters/runtime/index.d.ts +1 -1
- package/_internal/core/constants.d.ts +15 -0
- package/_internal/core/content-dir.d.ts +42 -0
- package/_internal/core/generated-version.d.ts +1 -0
- package/_internal/core/logger.d.ts +8 -0
- package/_internal/core/plugin-types.d.ts +168 -37
- package/_internal/core/routing/index.d.ts +1 -1
- package/_internal/plugins/team/types.d.ts +12 -2
- package/components/index.d.ts +39 -3
- package/components/index.js +16257 -1550
- package/hooks/index.d.ts +58 -9
- package/hooks/index.js +14414 -413
- package/index.d.ts +43 -10
- package/index.js +400 -1
- package/metadata/index.d.ts +16 -3
- package/package.json +2 -2
- package/register.d.ts +20 -9
- package/routing/index.d.ts +8 -3
- package/routing/index.js +327 -0
- package/slots/index.d.ts +1 -1
- package/slots/index.js +20 -1
- package/types/index.d.ts +431 -50
- package/ui/index.d.ts +2 -2
- package/ui/index.js +2 -1
- package/utils/index.d.ts +24 -2
- package/utils/index.js +269 -1
- package/_internal/app/hooks/use-assets.d.ts +0 -25
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@
|
|
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
|
-
* - `@
|
|
12
|
-
* - `@
|
|
13
|
-
* - `@
|
|
14
|
-
* - `@
|
|
15
|
-
* - `@
|
|
16
|
-
* - `@
|
|
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 `@
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
package/metadata/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@
|
|
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 `@
|
|
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@makinbakin/sdk",
|
|
3
|
-
"version": "0.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": "
|
|
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
|
-
|
|
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;
|
package/routing/index.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@
|
|
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 (`@
|
|
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
|
-
|
|
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';
|