@makinbakin/sdk 0.0.1-rc.20 → 0.0.1-rc.21
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/_internal/app/components/agent-select.d.ts +10 -1
- package/_internal/app/components/asset-picker.d.ts +25 -0
- package/_internal/app/components/charts/bar-chart.d.ts +16 -0
- package/_internal/app/components/charts/chart-data-table.d.ts +31 -0
- package/_internal/app/components/charts/chart-explainer.d.ts +9 -0
- package/_internal/app/components/charts/chart-tooltip.d.ts +8 -0
- package/_internal/app/components/charts/line-chart.d.ts +13 -0
- package/_internal/app/components/charts/palette.d.ts +24 -0
- package/_internal/app/components/charts/sparkline.d.ts +12 -0
- package/_internal/app/components/charts/stacked-column-chart.d.ts +40 -0
- package/_internal/app/components/confirm-dialog.d.ts +23 -2
- package/_internal/app/components/conversation/activity-group.d.ts +15 -0
- package/_internal/app/components/conversation/agent-turn.d.ts +36 -0
- package/_internal/app/components/conversation/attention.d.ts +56 -0
- package/_internal/app/components/conversation/composer.d.ts +35 -0
- package/_internal/app/components/conversation/conversation-empty-state.d.ts +8 -0
- package/_internal/app/components/conversation/conversation-panel.d.ts +33 -0
- package/_internal/app/components/conversation/conversation.d.ts +14 -0
- package/_internal/app/components/conversation/fold.d.ts +129 -0
- package/_internal/app/components/conversation/notification-sound.d.ts +8 -0
- package/_internal/app/components/conversation/relative-time.d.ts +8 -0
- package/_internal/app/components/conversation/reply-toast.d.ts +15 -0
- package/_internal/app/components/conversation/thread-id.d.ts +8 -0
- package/_internal/app/components/conversation/tool-call-drawer.d.ts +7 -0
- package/_internal/app/components/conversation/turn-recorder.d.ts +37 -0
- package/_internal/app/components/conversation/use-conversation-attention.d.ts +64 -0
- package/_internal/app/components/conversation/use-conversation-thread.d.ts +55 -0
- package/_internal/app/components/conversation/user-message.d.ts +11 -0
- package/_internal/app/components/danger-zone.d.ts +28 -0
- package/_internal/app/components/empty-state.d.ts +5 -2
- package/_internal/app/components/plugin-header.d.ts +4 -3
- package/_internal/app/components/save-bar.d.ts +32 -0
- package/_internal/app/components/score-overlay.d.ts +33 -0
- package/_internal/app/components/search-degraded-chip.d.ts +4 -0
- package/_internal/app/components/search-partial-chip.d.ts +13 -0
- package/_internal/app/components/search-unavailable.d.ts +12 -0
- package/_internal/app/components/section-card.d.ts +22 -0
- package/_internal/app/components/segmented-control.d.ts +28 -0
- package/_internal/app/components/stat-tile.d.ts +26 -0
- package/_internal/app/components/status-badge.d.ts +19 -0
- package/_internal/app/components/turn-output-view.d.ts +57 -0
- package/_internal/app/components/ui/button.d.ts +1 -1
- package/_internal/app/components/underline-tabs.d.ts +6 -2
- package/_internal/app/components/unsaved-changes-guard.d.ts +34 -0
- package/_internal/app/core/conversation-turns.d.ts +148 -0
- package/_internal/app/core/logger.d.ts +1 -0
- package/_internal/app/hooks/use-file-drop.d.ts +25 -0
- package/_internal/app/hooks/use-history-back.d.ts +1 -0
- package/_internal/app/hooks/use-json-fetch.d.ts +5 -0
- package/_internal/app/hooks/use-query-state.d.ts +2 -0
- package/_internal/app/hooks/use-schedule.d.ts +45 -0
- package/_internal/app/hooks/use-search.d.ts +27 -8
- package/_internal/app/hooks/use-toast.d.ts +3 -3
- package/_internal/app/lib/browser-notify.d.ts +12 -1
- package/_internal/core/adapters/runtime/concepts.d.ts +547 -49
- package/_internal/core/adapters/runtime/errors.d.ts +13 -1
- package/_internal/core/adapters/runtime/helpers.d.ts +19 -0
- package/_internal/core/adapters/runtime/index.d.ts +5 -2
- package/_internal/core/adapters/runtime/testing.d.ts +79 -0
- package/_internal/core/adapters/runtime/turn-activity.d.ts +23 -0
- package/_internal/core/adapters/shared.d.ts +122 -12
- package/_internal/core/content-dir.d.ts +8 -0
- package/_internal/core/docs/route.d.ts +1 -1
- package/_internal/core/format/structured.d.ts +44 -0
- package/_internal/core/format.d.ts +5 -1
- package/_internal/core/media/downscale.d.ts +18 -0
- package/_internal/core/media/sharp-loader.d.ts +36 -0
- package/_internal/core/plugin-types.d.ts +102 -39
- package/_internal/core/routing/define.d.ts +26 -3
- package/_internal/core/routing/dispatcher.d.ts +15 -6
- package/_internal/core/routing/index.d.ts +1 -1
- package/_internal/core/routing/types.d.ts +13 -70
- package/_internal/core/storage/atomic-write.d.ts +11 -0
- package/_internal/core/tasks/store.d.ts +129 -0
- package/_internal/core/tasks/testing.d.ts +2 -0
- package/_internal/{plugins/workflows/lib → core/workflows}/notification-channel-registry.d.ts +1 -1
- package/_internal/plugins/team/types.d.ts +47 -0
- package/_internal/plugins/workflows/hooks/use-notification-channels.d.ts +1 -1
- package/components/index.d.ts +87 -19
- package/components/index.js +32904 -15368
- package/hooks/index.d.ts +24 -4
- package/hooks/index.js +837 -561
- package/hooks/router.d.ts +20 -4
- package/index.d.ts +5 -50
- package/index.js +223 -406
- package/internal/index.d.ts +70 -0
- package/internal/index.js +409 -0
- package/package.json +9 -2
- package/register.d.ts +19 -1
- package/routing/index.js +175 -147
- package/slots/index.js +20 -1
- package/testing/index.d.ts +122 -0
- package/testing/index.js +21874 -0
- package/types/index.d.ts +4 -0
- package/types/index.js +16 -0
- package/utils/index.d.ts +28 -25
- package/utils/index.js +279 -263
- package/_internal/app/components/integrated-brainstorm/activity.d.ts +0 -23
- package/_internal/app/components/integrated-brainstorm/collapsed-header.d.ts +0 -14
- package/_internal/app/components/integrated-brainstorm/empty-state.d.ts +0 -5
- package/_internal/app/components/integrated-brainstorm/index.d.ts +0 -8
- package/_internal/app/components/integrated-brainstorm/input-row.d.ts +0 -16
- package/_internal/app/components/integrated-brainstorm/message-list.d.ts +0 -8
- package/_internal/app/components/integrated-brainstorm/session.d.ts +0 -16
- package/_internal/app/components/integrated-brainstorm/sse.d.ts +0 -8
- package/_internal/app/components/integrated-brainstorm/thinking-indicator.d.ts +0 -19
- package/_internal/app/components/integrated-brainstorm/types.d.ts +0 -63
- package/_internal/app/components/integrated-brainstorm/use-auto-grow.d.ts +0 -6
- package/_internal/app/components/integrated-brainstorm/use-brainstorm-state.d.ts +0 -21
- /package/_internal/{plugins/models → app}/hooks/use-available-models.d.ts +0 -0
package/routing/index.js
CHANGED
|
@@ -14,151 +14,6 @@ var __export = (target, all) => {
|
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
// packages/core/src/routing/define.ts
|
|
18
|
-
function defineRoute(route) {
|
|
19
|
-
return route;
|
|
20
|
-
}
|
|
21
|
-
function defineCoreRoute(route) {
|
|
22
|
-
return route;
|
|
23
|
-
}
|
|
24
|
-
function definePlugin(plugin) {
|
|
25
|
-
return plugin;
|
|
26
|
-
}
|
|
27
|
-
// packages/core/src/routing/operation-id.ts
|
|
28
|
-
function operationIdFor(scope, method, path) {
|
|
29
|
-
return `${scope}.${method.toLowerCase()}.${slugifyPath(path)}`;
|
|
30
|
-
}
|
|
31
|
-
function slugifyPath(path) {
|
|
32
|
-
const trimmed = path.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
33
|
-
if (trimmed === "")
|
|
34
|
-
return "root";
|
|
35
|
-
const segments = trimmed.split("/").map((seg) => {
|
|
36
|
-
if (seg.startsWith(":"))
|
|
37
|
-
return camelToKebab(seg.slice(1));
|
|
38
|
-
if (seg.startsWith("{") && seg.endsWith("}"))
|
|
39
|
-
return camelToKebab(seg.slice(1, -1));
|
|
40
|
-
return camelToKebab(seg);
|
|
41
|
-
}).filter(Boolean);
|
|
42
|
-
return segments.join("-");
|
|
43
|
-
}
|
|
44
|
-
function camelToKebab(input) {
|
|
45
|
-
return input.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").toLowerCase();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// packages/core/src/routing/registry.ts
|
|
49
|
-
function parseSegments(path) {
|
|
50
|
-
return path.split("/").filter(Boolean).map((seg) => {
|
|
51
|
-
if (seg === "*" || seg.startsWith("..."))
|
|
52
|
-
return { kind: "wildcard" };
|
|
53
|
-
if (seg.startsWith(":"))
|
|
54
|
-
return { kind: "param", name: seg.slice(1) };
|
|
55
|
-
if (seg.startsWith("{") && seg.endsWith("}")) {
|
|
56
|
-
return { kind: "param", name: seg.slice(1, -1) };
|
|
57
|
-
}
|
|
58
|
-
return { kind: "literal", value: seg };
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
function specificityScore(segments) {
|
|
62
|
-
let score = 0;
|
|
63
|
-
for (const seg of segments) {
|
|
64
|
-
if (seg.kind === "literal")
|
|
65
|
-
score += 2;
|
|
66
|
-
else if (seg.kind === "param")
|
|
67
|
-
score += 1;
|
|
68
|
-
}
|
|
69
|
-
return score;
|
|
70
|
-
}
|
|
71
|
-
function matchSegments(pathSegments, routeSegments) {
|
|
72
|
-
const lastIsWildcard = routeSegments.length > 0 && routeSegments[routeSegments.length - 1].kind === "wildcard";
|
|
73
|
-
if (!lastIsWildcard && pathSegments.length !== routeSegments.length)
|
|
74
|
-
return null;
|
|
75
|
-
if (lastIsWildcard && pathSegments.length < routeSegments.length - 1)
|
|
76
|
-
return null;
|
|
77
|
-
const params = {};
|
|
78
|
-
for (let i = 0;i < routeSegments.length; i++) {
|
|
79
|
-
const rseg = routeSegments[i];
|
|
80
|
-
if (rseg.kind === "wildcard")
|
|
81
|
-
return params;
|
|
82
|
-
const pseg = pathSegments[i];
|
|
83
|
-
if (rseg.kind === "literal") {
|
|
84
|
-
if (rseg.value !== pseg)
|
|
85
|
-
return null;
|
|
86
|
-
} else {
|
|
87
|
-
params[rseg.name] = pseg;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return params;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
class RouteRegistry {
|
|
94
|
-
byMethod = new Map;
|
|
95
|
-
operationIds = new Set;
|
|
96
|
-
fullPaths = new Set;
|
|
97
|
-
register(input) {
|
|
98
|
-
const { route } = input;
|
|
99
|
-
const pluginId = input.scope === "plugin" ? input.pluginId : null;
|
|
100
|
-
const fullPath = pluginId !== null ? `/api/plugins/${pluginId}${route.path}` : route.path;
|
|
101
|
-
const operationId = route.operationId ?? operationIdFor(pluginId ?? "core", route.method, route.path);
|
|
102
|
-
const dupKey = `${route.method} ${fullPath}`;
|
|
103
|
-
if (this.fullPaths.has(dupKey)) {
|
|
104
|
-
throw new Error(`duplicate route registration: ${dupKey}`);
|
|
105
|
-
}
|
|
106
|
-
if (this.operationIds.has(operationId)) {
|
|
107
|
-
throw new Error(`duplicate operationId: ${operationId} (route: ${dupKey})`);
|
|
108
|
-
}
|
|
109
|
-
this.fullPaths.add(dupKey);
|
|
110
|
-
this.operationIds.add(operationId);
|
|
111
|
-
const segments = parseSegments(fullPath);
|
|
112
|
-
const indexed = {
|
|
113
|
-
registered: {
|
|
114
|
-
route,
|
|
115
|
-
scope: pluginId ?? "core",
|
|
116
|
-
fullPath,
|
|
117
|
-
operationId
|
|
118
|
-
},
|
|
119
|
-
segments,
|
|
120
|
-
score: specificityScore(segments)
|
|
121
|
-
};
|
|
122
|
-
let bucket = this.byMethod.get(route.method);
|
|
123
|
-
if (!bucket) {
|
|
124
|
-
bucket = [];
|
|
125
|
-
this.byMethod.set(route.method, bucket);
|
|
126
|
-
}
|
|
127
|
-
bucket.push(indexed);
|
|
128
|
-
bucket.sort((a, b) => b.score - a.score);
|
|
129
|
-
return indexed.registered;
|
|
130
|
-
}
|
|
131
|
-
match(method, path) {
|
|
132
|
-
const bucket = this.byMethod.get(method);
|
|
133
|
-
if (!bucket)
|
|
134
|
-
return null;
|
|
135
|
-
const normalized = path.replace(/\/+$/, "") || "/";
|
|
136
|
-
const pathSegments = normalized.split("/").filter(Boolean);
|
|
137
|
-
for (const indexed of bucket) {
|
|
138
|
-
const params = matchSegments(pathSegments, indexed.segments);
|
|
139
|
-
if (params !== null) {
|
|
140
|
-
return {
|
|
141
|
-
...indexed.registered,
|
|
142
|
-
params
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
all() {
|
|
149
|
-
const out = [];
|
|
150
|
-
for (const bucket of this.byMethod.values()) {
|
|
151
|
-
for (const entry of bucket)
|
|
152
|
-
out.push(entry.registered);
|
|
153
|
-
}
|
|
154
|
-
return out;
|
|
155
|
-
}
|
|
156
|
-
clear() {
|
|
157
|
-
this.byMethod.clear();
|
|
158
|
-
this.operationIds.clear();
|
|
159
|
-
this.fullPaths.clear();
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
17
|
// node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
163
18
|
var exports_external = {};
|
|
164
19
|
__export(exports_external, {
|
|
@@ -13760,9 +13615,13 @@ function getBakinPaths() {
|
|
|
13760
13615
|
inbox: join(home, "inbox"),
|
|
13761
13616
|
tasks: join(home, "tasks"),
|
|
13762
13617
|
workflows: join(home, "workflows"),
|
|
13618
|
+
brands: join(home, "brands"),
|
|
13619
|
+
chat: join(home, "chat"),
|
|
13763
13620
|
settings: join(home, "settings.json"),
|
|
13764
13621
|
logs: join(home, "logs"),
|
|
13765
|
-
|
|
13622
|
+
antfly: join(home, "antfly"),
|
|
13623
|
+
db: join(home, "bakin.db"),
|
|
13624
|
+
bin: join(home, "bin")
|
|
13766
13625
|
};
|
|
13767
13626
|
}
|
|
13768
13627
|
|
|
@@ -13934,7 +13793,6 @@ function suppressPrettyInfo(entry) {
|
|
|
13934
13793
|
"search-cleanup",
|
|
13935
13794
|
"search-startup",
|
|
13936
13795
|
"hot-reload-coordinator",
|
|
13937
|
-
"mcporter",
|
|
13938
13796
|
"dispatch",
|
|
13939
13797
|
"dispatch-state",
|
|
13940
13798
|
"dispatch-turns",
|
|
@@ -14035,6 +13893,176 @@ function createLogger(module) {
|
|
|
14035
13893
|
|
|
14036
13894
|
// packages/core/src/routing/dispatcher.ts
|
|
14037
13895
|
var log = createLogger("dispatcher");
|
|
13896
|
+
var VALID_BODY_CONTENT_TYPES = ["application/json", "multipart/form-data", "*/*", "none"];
|
|
13897
|
+
function assertValidBodySpec(body, label) {
|
|
13898
|
+
if (body === undefined || body === null)
|
|
13899
|
+
return;
|
|
13900
|
+
if (isZodType(body))
|
|
13901
|
+
return;
|
|
13902
|
+
if (typeof body !== "object" || !("contentType" in body)) {
|
|
13903
|
+
throw new Error(`route ${label}: body spec must be a zod schema or declare a contentType (got ${JSON.stringify(body)})`);
|
|
13904
|
+
}
|
|
13905
|
+
const ct = body.contentType;
|
|
13906
|
+
if (!VALID_BODY_CONTENT_TYPES.includes(ct)) {
|
|
13907
|
+
throw new Error(`route ${label}: unknown body contentType '${String(ct)}' \u2014 valid values: ${VALID_BODY_CONTENT_TYPES.join(", ")}`);
|
|
13908
|
+
}
|
|
13909
|
+
if (ct === "application/json" && !isZodType(body.schema)) {
|
|
13910
|
+
throw new Error(`route ${label}: contentType 'application/json' requires a zod schema`);
|
|
13911
|
+
}
|
|
13912
|
+
}
|
|
13913
|
+
function isZodType(value) {
|
|
13914
|
+
if (!value || typeof value !== "object")
|
|
13915
|
+
return false;
|
|
13916
|
+
return value instanceof exports_external.ZodType || typeof value._zod === "object" && value._zod !== null;
|
|
13917
|
+
}
|
|
13918
|
+
|
|
13919
|
+
// packages/core/src/routing/define.ts
|
|
13920
|
+
function defineRoute(route) {
|
|
13921
|
+
assertValidBodySpec(route.body, `${route.method} ${route.path}`);
|
|
13922
|
+
return route;
|
|
13923
|
+
}
|
|
13924
|
+
function defineCoreRoute(route) {
|
|
13925
|
+
assertValidBodySpec(route.body, `${route.method} ${route.path}`);
|
|
13926
|
+
return route;
|
|
13927
|
+
}
|
|
13928
|
+
function definePlugin(plugin) {
|
|
13929
|
+
return plugin;
|
|
13930
|
+
}
|
|
13931
|
+
// packages/core/src/routing/operation-id.ts
|
|
13932
|
+
function operationIdFor(scope, method, path) {
|
|
13933
|
+
return `${scope}.${method.toLowerCase()}.${slugifyPath(path)}`;
|
|
13934
|
+
}
|
|
13935
|
+
function slugifyPath(path) {
|
|
13936
|
+
const trimmed = path.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
13937
|
+
if (trimmed === "")
|
|
13938
|
+
return "root";
|
|
13939
|
+
const segments = trimmed.split("/").map((seg) => {
|
|
13940
|
+
if (seg.startsWith(":"))
|
|
13941
|
+
return camelToKebab(seg.slice(1));
|
|
13942
|
+
if (seg.startsWith("{") && seg.endsWith("}"))
|
|
13943
|
+
return camelToKebab(seg.slice(1, -1));
|
|
13944
|
+
return camelToKebab(seg);
|
|
13945
|
+
}).filter(Boolean);
|
|
13946
|
+
return segments.join("-");
|
|
13947
|
+
}
|
|
13948
|
+
function camelToKebab(input) {
|
|
13949
|
+
return input.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").toLowerCase();
|
|
13950
|
+
}
|
|
13951
|
+
|
|
13952
|
+
// packages/core/src/routing/registry.ts
|
|
13953
|
+
function parseSegments(path) {
|
|
13954
|
+
return path.split("/").filter(Boolean).map((seg) => {
|
|
13955
|
+
if (seg === "*" || seg.startsWith("..."))
|
|
13956
|
+
return { kind: "wildcard" };
|
|
13957
|
+
if (seg.startsWith(":"))
|
|
13958
|
+
return { kind: "param", name: seg.slice(1) };
|
|
13959
|
+
if (seg.startsWith("{") && seg.endsWith("}")) {
|
|
13960
|
+
return { kind: "param", name: seg.slice(1, -1) };
|
|
13961
|
+
}
|
|
13962
|
+
return { kind: "literal", value: seg };
|
|
13963
|
+
});
|
|
13964
|
+
}
|
|
13965
|
+
function specificityScore(segments) {
|
|
13966
|
+
let score = 0;
|
|
13967
|
+
for (const seg of segments) {
|
|
13968
|
+
if (seg.kind === "literal")
|
|
13969
|
+
score += 2;
|
|
13970
|
+
else if (seg.kind === "param")
|
|
13971
|
+
score += 1;
|
|
13972
|
+
}
|
|
13973
|
+
return score;
|
|
13974
|
+
}
|
|
13975
|
+
function matchSegments(pathSegments, routeSegments) {
|
|
13976
|
+
const lastIsWildcard = routeSegments.length > 0 && routeSegments[routeSegments.length - 1].kind === "wildcard";
|
|
13977
|
+
if (!lastIsWildcard && pathSegments.length !== routeSegments.length)
|
|
13978
|
+
return null;
|
|
13979
|
+
if (lastIsWildcard && pathSegments.length < routeSegments.length - 1)
|
|
13980
|
+
return null;
|
|
13981
|
+
const params = {};
|
|
13982
|
+
for (let i = 0;i < routeSegments.length; i++) {
|
|
13983
|
+
const rseg = routeSegments[i];
|
|
13984
|
+
if (rseg.kind === "wildcard")
|
|
13985
|
+
return params;
|
|
13986
|
+
const pseg = pathSegments[i];
|
|
13987
|
+
if (rseg.kind === "literal") {
|
|
13988
|
+
if (rseg.value !== pseg)
|
|
13989
|
+
return null;
|
|
13990
|
+
} else {
|
|
13991
|
+
params[rseg.name] = pseg;
|
|
13992
|
+
}
|
|
13993
|
+
}
|
|
13994
|
+
return params;
|
|
13995
|
+
}
|
|
13996
|
+
|
|
13997
|
+
class RouteRegistry {
|
|
13998
|
+
byMethod = new Map;
|
|
13999
|
+
operationIds = new Set;
|
|
14000
|
+
fullPaths = new Set;
|
|
14001
|
+
register(input) {
|
|
14002
|
+
const { route } = input;
|
|
14003
|
+
const pluginId = input.scope === "plugin" ? input.pluginId : null;
|
|
14004
|
+
const fullPath = pluginId !== null ? `/api/plugins/${pluginId}${route.path}` : route.path;
|
|
14005
|
+
const operationId = route.operationId ?? operationIdFor(pluginId ?? "core", route.method, route.path);
|
|
14006
|
+
const dupKey = `${route.method} ${fullPath}`;
|
|
14007
|
+
if (this.fullPaths.has(dupKey)) {
|
|
14008
|
+
throw new Error(`duplicate route registration: ${dupKey}`);
|
|
14009
|
+
}
|
|
14010
|
+
if (this.operationIds.has(operationId)) {
|
|
14011
|
+
throw new Error(`duplicate operationId: ${operationId} (route: ${dupKey})`);
|
|
14012
|
+
}
|
|
14013
|
+
this.fullPaths.add(dupKey);
|
|
14014
|
+
this.operationIds.add(operationId);
|
|
14015
|
+
const segments = parseSegments(fullPath);
|
|
14016
|
+
const indexed = {
|
|
14017
|
+
registered: {
|
|
14018
|
+
route,
|
|
14019
|
+
scope: pluginId ?? "core",
|
|
14020
|
+
fullPath,
|
|
14021
|
+
operationId
|
|
14022
|
+
},
|
|
14023
|
+
segments,
|
|
14024
|
+
score: specificityScore(segments)
|
|
14025
|
+
};
|
|
14026
|
+
let bucket = this.byMethod.get(route.method);
|
|
14027
|
+
if (!bucket) {
|
|
14028
|
+
bucket = [];
|
|
14029
|
+
this.byMethod.set(route.method, bucket);
|
|
14030
|
+
}
|
|
14031
|
+
bucket.push(indexed);
|
|
14032
|
+
bucket.sort((a, b) => b.score - a.score);
|
|
14033
|
+
return indexed.registered;
|
|
14034
|
+
}
|
|
14035
|
+
match(method, path) {
|
|
14036
|
+
const bucket = this.byMethod.get(method);
|
|
14037
|
+
if (!bucket)
|
|
14038
|
+
return null;
|
|
14039
|
+
const normalized = path.replace(/\/+$/, "") || "/";
|
|
14040
|
+
const pathSegments = normalized.split("/").filter(Boolean);
|
|
14041
|
+
for (const indexed of bucket) {
|
|
14042
|
+
const params = matchSegments(pathSegments, indexed.segments);
|
|
14043
|
+
if (params !== null) {
|
|
14044
|
+
return {
|
|
14045
|
+
...indexed.registered,
|
|
14046
|
+
params
|
|
14047
|
+
};
|
|
14048
|
+
}
|
|
14049
|
+
}
|
|
14050
|
+
return null;
|
|
14051
|
+
}
|
|
14052
|
+
all() {
|
|
14053
|
+
const out = [];
|
|
14054
|
+
for (const bucket of this.byMethod.values()) {
|
|
14055
|
+
for (const entry of bucket)
|
|
14056
|
+
out.push(entry.registered);
|
|
14057
|
+
}
|
|
14058
|
+
return out;
|
|
14059
|
+
}
|
|
14060
|
+
clear() {
|
|
14061
|
+
this.byMethod.clear();
|
|
14062
|
+
this.operationIds.clear();
|
|
14063
|
+
this.fullPaths.clear();
|
|
14064
|
+
}
|
|
14065
|
+
}
|
|
14038
14066
|
// packages/core/src/routing/search-route.ts
|
|
14039
14067
|
var searchQuery = exports_external.object({
|
|
14040
14068
|
q: exports_external.string().min(1),
|
package/slots/index.js
CHANGED
|
@@ -66,7 +66,10 @@ function getRegistry2() {
|
|
|
66
66
|
listeners: new Set,
|
|
67
67
|
badgesByPlugin: new Map,
|
|
68
68
|
badgesSnapshot: new Map,
|
|
69
|
-
badgeListeners: new Set
|
|
69
|
+
badgeListeners: new Set,
|
|
70
|
+
hitRenderersByPlugin: new Map,
|
|
71
|
+
hitRenderersSnapshot: new Map,
|
|
72
|
+
hitRendererListeners: new Set
|
|
70
73
|
};
|
|
71
74
|
}
|
|
72
75
|
const registry = g.__bakinClientRegistry;
|
|
@@ -81,8 +84,24 @@ function getRegistry2() {
|
|
|
81
84
|
registry.badgesSnapshot = buildBadgesSnapshot(registry);
|
|
82
85
|
if (!registry.badgeListeners)
|
|
83
86
|
registry.badgeListeners = new Set;
|
|
87
|
+
if (!registry.hitRenderersByPlugin)
|
|
88
|
+
registry.hitRenderersByPlugin = new Map;
|
|
89
|
+
if (!registry.hitRenderersSnapshot)
|
|
90
|
+
registry.hitRenderersSnapshot = buildHitRenderersSnapshot(registry);
|
|
91
|
+
if (!registry.hitRendererListeners)
|
|
92
|
+
registry.hitRendererListeners = new Set;
|
|
84
93
|
return registry;
|
|
85
94
|
}
|
|
95
|
+
function buildHitRenderersSnapshot(registry) {
|
|
96
|
+
const snapshot = new Map;
|
|
97
|
+
for (const byType of registry.hitRenderersByPlugin.values()) {
|
|
98
|
+
for (const [type, renderer] of byType) {
|
|
99
|
+
if (!snapshot.has(type))
|
|
100
|
+
snapshot.set(type, renderer);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return snapshot;
|
|
104
|
+
}
|
|
86
105
|
function buildBadgesSnapshot(registry) {
|
|
87
106
|
const snapshot = new Map;
|
|
88
107
|
for (const byNavItemId of registry.badgesByPlugin.values()) {
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { BakinPlugin, ExecToolDefinition, ExecToolResult, HealthCheckRegistrationInput, HealthRepairActionDefinition, NavItem, PluginContext, PluginNodeTypeInput, PluginNotificationChannelInput, PluginToolContext, SearchResponse, SearchResult, SkillDefinition, UISlotRegistration, WorkflowDefinitionInput } from '../types/index';
|
|
2
|
+
import type { APIRoute } from '../routing/index';
|
|
3
|
+
/** One captured `ctx.log` line. */
|
|
4
|
+
export interface CapturedLog {
|
|
5
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
6
|
+
message: string;
|
|
7
|
+
data?: unknown;
|
|
8
|
+
}
|
|
9
|
+
/** One captured `ctx.activity.log` / `ctx.activity.audit` call. */
|
|
10
|
+
export interface CapturedActivity {
|
|
11
|
+
kind: 'log' | 'audit';
|
|
12
|
+
agent: string;
|
|
13
|
+
message: string;
|
|
14
|
+
data?: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The harness returned by {@link createTestContext} / {@link activatePlugin}.
|
|
18
|
+
* Everything the plugin registered is captured on plain arrays so tests can
|
|
19
|
+
* assert on it directly.
|
|
20
|
+
*/
|
|
21
|
+
export interface PluginTestContext {
|
|
22
|
+
/** The isolated context — pass to `callRoute`, or to the plugin directly. */
|
|
23
|
+
ctx: PluginContext;
|
|
24
|
+
/** All routes: declarative `plugin.routes` + the auto-wired search route. */
|
|
25
|
+
routes: APIRoute[];
|
|
26
|
+
/** Exec tools registered via `ctx.registerExecTool`. */
|
|
27
|
+
execTools: ExecToolDefinition[];
|
|
28
|
+
/** Nav items registered via `ctx.registerNav`. */
|
|
29
|
+
navItems: NavItem[];
|
|
30
|
+
/** Slot registrations via `ctx.registerSlot`. */
|
|
31
|
+
slots: UISlotRegistration[];
|
|
32
|
+
/** Workflows registered via `ctx.registerWorkflow`. */
|
|
33
|
+
workflows: WorkflowDefinitionInput[];
|
|
34
|
+
/** Node types registered via `ctx.registerNodeType`. */
|
|
35
|
+
nodeTypes: PluginNodeTypeInput<unknown>[];
|
|
36
|
+
/** Notification channels registered via `ctx.registerNotificationChannel`. */
|
|
37
|
+
notificationChannels: PluginNotificationChannelInput[];
|
|
38
|
+
/** Health checks registered via `ctx.registerHealthCheck`. */
|
|
39
|
+
healthChecks: HealthCheckRegistrationInput[];
|
|
40
|
+
/** Repair actions registered via `ctx.registerHealthRepairAction`. */
|
|
41
|
+
healthRepairActions: HealthRepairActionDefinition[];
|
|
42
|
+
/** Runtime skills registered via `ctx.registerSkill`. */
|
|
43
|
+
skills: SkillDefinition[];
|
|
44
|
+
/** File-watch patterns passed to `ctx.watchFiles`. */
|
|
45
|
+
watchedPatterns: string[];
|
|
46
|
+
/** Everything logged through `ctx.log`. */
|
|
47
|
+
logs: CapturedLog[];
|
|
48
|
+
/** Everything sent to `ctx.activity`. */
|
|
49
|
+
activity: CapturedActivity[];
|
|
50
|
+
/** Absolute path of the temp directory backing `ctx.storage`. */
|
|
51
|
+
dir: string;
|
|
52
|
+
/**
|
|
53
|
+
* Seed `ctx.search.query()` responses. All subsequent queries return these
|
|
54
|
+
* results until re-seeded.
|
|
55
|
+
*/
|
|
56
|
+
seedSearchResults(results: SearchResult[], aggregations?: SearchResponse['aggregations']): void;
|
|
57
|
+
/** Build the `PluginToolContext` an exec tool receives as its third arg. */
|
|
58
|
+
toolContext(): PluginToolContext;
|
|
59
|
+
/** Delete the temp directory. Call from `afterAll`. Safe to call twice. */
|
|
60
|
+
dispose(): void;
|
|
61
|
+
}
|
|
62
|
+
export interface CreateTestContextOptions {
|
|
63
|
+
/** Initial `ctx.getSettings()` value. `ctx.updateSettings` patches it. */
|
|
64
|
+
settings?: Record<string, unknown>;
|
|
65
|
+
/**
|
|
66
|
+
* Use this directory instead of a fresh temp dir. The harness will NOT
|
|
67
|
+
* delete a caller-provided directory on `dispose()`.
|
|
68
|
+
*/
|
|
69
|
+
dir?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create an isolated `PluginContext` for `pluginId`.
|
|
73
|
+
*
|
|
74
|
+
* Storage is a real filesystem adapter rooted at a fresh temp directory;
|
|
75
|
+
* events are a real in-process bus; hooks are a local registry (the plugin
|
|
76
|
+
* can invoke its own hooks); runtime/tasks are the SDK mock implementations;
|
|
77
|
+
* search is seedable via `seedSearchResults`. Registration calls are
|
|
78
|
+
* captured, never applied to any global registry.
|
|
79
|
+
*/
|
|
80
|
+
export declare function createTestContext(pluginId: string, options?: CreateTestContextOptions): PluginTestContext;
|
|
81
|
+
/**
|
|
82
|
+
* Activate a plugin against a fresh test context. Declarative `plugin.routes`
|
|
83
|
+
* are collected first (as the host does), then `activate(ctx)` runs and its
|
|
84
|
+
* registrations land on the same arrays.
|
|
85
|
+
*/
|
|
86
|
+
export declare function activatePlugin(plugin: BakinPlugin, options?: CreateTestContextOptions): Promise<PluginTestContext>;
|
|
87
|
+
/** Find a route by method and declared path (`'GET', '/items/:id'`). */
|
|
88
|
+
export declare function findRoute(routes: APIRoute[], method: string, path: string): APIRoute | undefined;
|
|
89
|
+
/** Find an exec tool by name. */
|
|
90
|
+
export declare function findTool(tools: ExecToolDefinition[], name: string): ExecToolDefinition | undefined;
|
|
91
|
+
/** Build a `Request` the way the host's router would. */
|
|
92
|
+
export declare function makeRequest(path: string, opts?: {
|
|
93
|
+
method?: string;
|
|
94
|
+
body?: unknown;
|
|
95
|
+
searchParams?: Record<string, string>;
|
|
96
|
+
}): Request;
|
|
97
|
+
/**
|
|
98
|
+
* Call a route handler and return `{ status, body, response }`.
|
|
99
|
+
*
|
|
100
|
+
* Routes that declare typed contracts (`params`/`query`/`body`/`responses`)
|
|
101
|
+
* dispatch through the same router the host uses, so schema validation and
|
|
102
|
+
* the `(req, ctx, parsed)` handler signature behave exactly as in
|
|
103
|
+
* production. Path params resolve from `opts.path` (`'/abc-1/move'` binds
|
|
104
|
+
* `:taskId` for a route at `'/:taskId/move'`) or from `opts.searchParams`
|
|
105
|
+
* entries matching placeholder names.
|
|
106
|
+
*/
|
|
107
|
+
export declare function callRoute(route: APIRoute, ctx: PluginContext, opts?: {
|
|
108
|
+
path?: string;
|
|
109
|
+
body?: unknown;
|
|
110
|
+
searchParams?: Record<string, string>;
|
|
111
|
+
rawResponse?: boolean;
|
|
112
|
+
}): Promise<{
|
|
113
|
+
status: number;
|
|
114
|
+
body: Record<string, unknown>;
|
|
115
|
+
response: Response;
|
|
116
|
+
}>;
|
|
117
|
+
/**
|
|
118
|
+
* Call an exec tool handler. Pass `toolCtx` (from `harness.toolContext()`)
|
|
119
|
+
* when the tool uses its third argument — scaffold-style tools that persist
|
|
120
|
+
* via `toolCtx.storage` need it.
|
|
121
|
+
*/
|
|
122
|
+
export declare function callTool(tool: ExecToolDefinition, params: Record<string, unknown>, agent?: string, toolCtx?: PluginToolContext): Promise<ExecToolResult>;
|