@btst/stack 2.3.0 → 2.4.0
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/dist/packages/stack/src/client/components/compose.cjs +1 -2
- package/dist/packages/stack/src/client/components/compose.mjs +1 -2
- package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.cjs +71 -0
- package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.mjs +68 -0
- package/dist/packages/stack/src/plugins/ai-chat/api/plugin.cjs +54 -7
- package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +54 -7
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.cjs +2 -2
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.mjs +2 -2
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.cjs +89 -22
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.mjs +90 -23
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.cjs +110 -33
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.mjs +112 -35
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.cjs +1 -1
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.mjs +1 -1
- package/dist/packages/stack/src/plugins/ai-chat/schemas.cjs +17 -1
- package/dist/packages/stack/src/plugins/ai-chat/schemas.mjs +17 -1
- package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.cjs +15 -2
- package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.mjs +16 -3
- package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.cjs +24 -1
- package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.mjs +24 -1
- package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.cjs +26 -0
- package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.mjs +24 -0
- package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.cjs +30 -1
- package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.mjs +30 -1
- package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +18 -0
- package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +18 -0
- package/dist/packages/stack/src/plugins/cms/api/mutations.cjs +48 -0
- package/dist/packages/stack/src/plugins/cms/api/mutations.mjs +46 -0
- package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +7 -1
- package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +7 -1
- package/dist/packages/stack/src/plugins/kanban/api/mutations.cjs +91 -0
- package/dist/packages/stack/src/plugins/kanban/api/mutations.mjs +87 -0
- package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +6 -1
- package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +6 -1
- package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.cjs +7 -3
- package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.mjs +7 -3
- package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.cjs +89 -0
- package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.mjs +89 -0
- package/dist/plugins/ai-chat/api/index.d.cts +1 -1
- package/dist/plugins/ai-chat/api/index.d.mts +1 -1
- package/dist/plugins/ai-chat/api/index.d.ts +1 -1
- package/dist/plugins/ai-chat/client/components/index.d.cts +1 -1
- package/dist/plugins/ai-chat/client/components/index.d.mts +1 -1
- package/dist/plugins/ai-chat/client/components/index.d.ts +1 -1
- package/dist/plugins/ai-chat/client/context/page-ai-context.cjs +92 -0
- package/dist/plugins/ai-chat/client/context/page-ai-context.d.cts +84 -0
- package/dist/plugins/ai-chat/client/context/page-ai-context.d.mts +84 -0
- package/dist/plugins/ai-chat/client/context/page-ai-context.d.ts +84 -0
- package/dist/plugins/ai-chat/client/context/page-ai-context.mjs +88 -0
- package/dist/plugins/ai-chat/client/hooks/index.d.cts +1 -1
- package/dist/plugins/ai-chat/client/hooks/index.d.mts +1 -1
- package/dist/plugins/ai-chat/client/hooks/index.d.ts +1 -1
- package/dist/plugins/ai-chat/client/index.d.cts +2 -2
- package/dist/plugins/ai-chat/client/index.d.mts +2 -2
- package/dist/plugins/ai-chat/client/index.d.ts +2 -2
- package/dist/plugins/ai-chat/query-keys.d.cts +1 -1
- package/dist/plugins/ai-chat/query-keys.d.mts +1 -1
- package/dist/plugins/ai-chat/query-keys.d.ts +1 -1
- package/dist/plugins/blog/api/index.d.cts +2 -2
- package/dist/plugins/blog/api/index.d.mts +2 -2
- package/dist/plugins/blog/api/index.d.ts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
- package/dist/plugins/blog/client/index.d.cts +1 -1
- package/dist/plugins/blog/client/index.d.mts +1 -1
- package/dist/plugins/blog/client/index.d.ts +1 -1
- package/dist/plugins/blog/query-keys.d.cts +2 -2
- package/dist/plugins/blog/query-keys.d.mts +2 -2
- package/dist/plugins/blog/query-keys.d.ts +2 -2
- package/dist/plugins/cms/api/index.cjs +2 -0
- package/dist/plugins/cms/api/index.d.cts +1 -1
- package/dist/plugins/cms/api/index.d.mts +1 -1
- package/dist/plugins/cms/api/index.d.ts +1 -1
- package/dist/plugins/cms/api/index.mjs +1 -0
- package/dist/plugins/cms/query-keys.d.cts +1 -1
- package/dist/plugins/cms/query-keys.d.mts +1 -1
- package/dist/plugins/cms/query-keys.d.ts +1 -1
- package/dist/plugins/form-builder/api/index.d.cts +1 -1
- package/dist/plugins/form-builder/api/index.d.mts +1 -1
- package/dist/plugins/form-builder/api/index.d.ts +1 -1
- package/dist/plugins/form-builder/query-keys.d.cts +1 -1
- package/dist/plugins/form-builder/query-keys.d.mts +1 -1
- package/dist/plugins/form-builder/query-keys.d.ts +1 -1
- package/dist/plugins/kanban/api/index.cjs +4 -0
- package/dist/plugins/kanban/api/index.d.cts +1 -1
- package/dist/plugins/kanban/api/index.d.mts +1 -1
- package/dist/plugins/kanban/api/index.d.ts +1 -1
- package/dist/plugins/kanban/api/index.mjs +1 -0
- package/dist/plugins/kanban/query-keys.d.cts +1 -1
- package/dist/plugins/kanban/query-keys.d.mts +1 -1
- package/dist/plugins/kanban/query-keys.d.ts +1 -1
- package/dist/shared/{stack.BeSm90va.d.ts → stack.BEn34wW6.d.ts} +60 -2
- package/dist/shared/{stack.IdtKDRka.d.cts → stack.BUkC2EsZ.d.cts} +32 -2
- package/dist/shared/{stack.DaOcgmrM.d.ts → stack.BV9hnvu4.d.cts} +31 -7
- package/dist/shared/{stack.DaOcgmrM.d.cts → stack.BV9hnvu4.d.mts} +31 -7
- package/dist/shared/{stack.DaOcgmrM.d.mts → stack.BV9hnvu4.d.ts} +31 -7
- package/dist/shared/{stack.rTy7-wQU.d.mts → stack.BepFXT3w.d.mts} +70 -15
- package/dist/shared/{stack.BKfolAyK.d.ts → stack.CL8ts1Mu.d.ts} +3 -3
- package/dist/shared/{stack.CP68pFEH.d.mts → stack.CczspVn2.d.mts} +32 -2
- package/dist/shared/{stack.TIBF2AOx.d.ts → stack.CgWzG5jH.d.ts} +70 -15
- package/dist/shared/{stack.BpolpQpf.d.cts → stack.D3GB6wKv.d.cts} +70 -15
- package/dist/shared/{stack.B1EeBt1b.d.ts → stack.DASmUVjX.d.ts} +32 -2
- package/dist/shared/{stack.Dg09R0oB.d.mts → stack.DTDxgFj8.d.mts} +60 -2
- package/dist/shared/{stack.CMh_EdxW.d.cts → stack.DWoCZff7.d.cts} +60 -2
- package/dist/shared/{stack.snB1EDP7.d.cts → stack.Dk5r4W1F.d.mts} +3 -3
- package/dist/shared/{stack.BIXEI6v_.d.mts → stack.heOA9gzA.d.cts} +3 -3
- package/package.json +14 -1
- package/src/client/components/compose.tsx +7 -4
- package/src/plugins/ai-chat/api/page-tools.ts +111 -0
- package/src/plugins/ai-chat/api/plugin.ts +180 -9
- package/src/plugins/ai-chat/client/components/chat-input.tsx +2 -2
- package/src/plugins/ai-chat/client/components/chat-interface.tsx +154 -58
- package/src/plugins/ai-chat/client/components/chat-layout.tsx +166 -32
- package/src/plugins/ai-chat/client/components/chat-sidebar.tsx +1 -1
- package/src/plugins/ai-chat/client/context/page-ai-context.tsx +240 -0
- package/src/plugins/ai-chat/schemas.ts +16 -0
- package/src/plugins/blog/client/components/forms/post-forms.tsx +29 -2
- package/src/plugins/blog/client/components/pages/edit-post-page.internal.tsx +28 -0
- package/src/plugins/blog/client/components/pages/fill-blog-form-handler.ts +38 -0
- package/src/plugins/blog/client/components/pages/new-post-page.internal.tsx +33 -1
- package/src/plugins/blog/client/components/pages/post-page.internal.tsx +20 -0
- package/src/plugins/cms/api/index.ts +4 -0
- package/src/plugins/cms/api/mutations.ts +84 -0
- package/src/plugins/cms/api/plugin.ts +9 -0
- package/src/plugins/kanban/api/index.ts +6 -0
- package/src/plugins/kanban/api/mutations.ts +169 -0
- package/src/plugins/kanban/api/plugin.ts +12 -0
- package/src/plugins/kanban/client/hooks/kanban-hooks.tsx +4 -0
- package/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.tsx +132 -0
- package/dist/shared/{stack.C5dtIncc.d.mts → stack.B7ONvlD_.d.mts} +1 -1
- package/dist/shared/{stack.CBON0dWL.d.cts → stack.BQmuNl5p.d.cts} +2 -2
- package/dist/shared/{stack.CBON0dWL.d.mts → stack.BQmuNl5p.d.mts} +2 -2
- package/dist/shared/{stack.CBON0dWL.d.ts → stack.BQmuNl5p.d.ts} +2 -2
- package/dist/shared/{stack.CIP6QS9l.d.ts → stack.Kq2-QzOC.d.ts} +1 -1
- package/dist/shared/{stack.Dw0Ly2TM.d.cts → stack.kcdnD4gA.d.cts} +1 -1
|
@@ -78,6 +78,35 @@ declare function getContentItemById(adapter: Adapter, id: string): Promise<Seria
|
|
|
78
78
|
*/
|
|
79
79
|
declare function getContentItemBySlug(adapter: Adapter, contentTypeSlug: string, slug: string): Promise<SerializedContentItemWithType | null>;
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Input for creating a new CMS content item.
|
|
83
|
+
*/
|
|
84
|
+
interface CreateCMSContentItemInput {
|
|
85
|
+
/** URL-safe slug for the item */
|
|
86
|
+
slug: string;
|
|
87
|
+
/** Arbitrary data payload — should match the content type schema */
|
|
88
|
+
data: Record<string, unknown>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Create a new content item for a content type (looked up by slug).
|
|
92
|
+
*
|
|
93
|
+
* Bypasses Zod schema validation and relation processing — the caller is
|
|
94
|
+
* responsible for providing valid, relation-free data. For relation fields or
|
|
95
|
+
* schema validation, use the HTTP endpoint instead.
|
|
96
|
+
*
|
|
97
|
+
* Throws if the content type is not found or the slug is already taken within
|
|
98
|
+
* that content type.
|
|
99
|
+
*
|
|
100
|
+
* @remarks **Security:** No authorization hooks (`onBeforeCreate`, `onAfterCreate`)
|
|
101
|
+
* are called. The caller is responsible for any access-control checks before
|
|
102
|
+
* invoking this function.
|
|
103
|
+
*
|
|
104
|
+
* @param adapter - The database adapter
|
|
105
|
+
* @param contentTypeSlug - Slug of the target content type
|
|
106
|
+
* @param input - Item slug and data payload
|
|
107
|
+
*/
|
|
108
|
+
declare function createCMSContentItem(adapter: Adapter, contentTypeSlug: string, input: CreateCMSContentItemInput): Promise<SerializedContentItem>;
|
|
109
|
+
|
|
81
110
|
/**
|
|
82
111
|
* Route keys for the CMS plugin — matches the keys returned by
|
|
83
112
|
* `stackClient.router.getRoute(path).routeKey`.
|
|
@@ -257,6 +286,7 @@ declare const cmsBackendPlugin: (config: CMSBackendConfig) => _btst_stack_plugin
|
|
|
257
286
|
getContentItemBySlug: (contentTypeSlug: string, slug: string) => Promise<SerializedContentItemWithType<Record<string, unknown>> | null>;
|
|
258
287
|
getContentItemById: (id: string) => Promise<SerializedContentItemWithType<Record<string, unknown>> | null>;
|
|
259
288
|
prefetchForRoute: CMSPrefetchForRoute;
|
|
289
|
+
createContentItem: (typeSlug: string, input: Parameters<typeof createCMSContentItem>[2]) => Promise<SerializedContentItem>;
|
|
260
290
|
}>;
|
|
261
291
|
type CMSApiRouter = ReturnType<ReturnType<typeof cmsBackendPlugin>["routes"]>;
|
|
262
292
|
|
|
@@ -293,5 +323,5 @@ declare const CMS_QUERY_KEYS: {
|
|
|
293
323
|
contentDetail: (typeSlug: string, id: string) => readonly ["cmsContent", "detail", string, string];
|
|
294
324
|
};
|
|
295
325
|
|
|
296
|
-
export { cmsBackendPlugin as c, getAllContentItems as d, getContentItemBySlug as e, getContentItemById as f, getAllContentTypes as g, serializeContentItem as h, serializeContentItemWithType as i,
|
|
297
|
-
export type { CMSApiRouter as C, ContentListDiscriminator as a, CMSRouteKey as b };
|
|
326
|
+
export { cmsBackendPlugin as c, getAllContentItems as d, getContentItemBySlug as e, getContentItemById as f, getAllContentTypes as g, serializeContentItem as h, serializeContentItemWithType as i, createCMSContentItem as j, CMS_QUERY_KEYS as l, serializeContentType as s };
|
|
327
|
+
export type { CMSApiRouter as C, ContentListDiscriminator as a, CMSRouteKey as b, CreateCMSContentItemInput as k };
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
|
|
2
2
|
import * as better_call from 'better-call';
|
|
3
3
|
import { Adapter } from '@btst/db';
|
|
4
|
-
import { B as BoardWithColumns,
|
|
4
|
+
import { B as BoardWithColumns, P as Priority, T as Task, d as Board, e as Column, C as ColumnWithTasks } from './stack.DJaKVY7v.js';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { QueryClient } from '@tanstack/react-query';
|
|
7
7
|
|
|
8
8
|
declare const createBoardSchema: z.ZodObject<{
|
|
9
9
|
description: z.ZodOptional<z.ZodString>;
|
|
10
|
-
name: z.ZodString;
|
|
11
|
-
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
12
|
-
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
13
10
|
slug: z.ZodOptional<z.ZodString>;
|
|
14
11
|
ownerId: z.ZodOptional<z.ZodString>;
|
|
15
12
|
organizationId: z.ZodOptional<z.ZodString>;
|
|
13
|
+
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
14
|
+
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
15
|
+
name: z.ZodString;
|
|
16
16
|
}, z.core.$strip>;
|
|
17
17
|
declare const updateBoardSchema: z.ZodObject<{
|
|
18
18
|
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
@@ -28,8 +28,8 @@ declare const createColumnSchema: z.ZodObject<{
|
|
|
28
28
|
title: z.ZodString;
|
|
29
29
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
30
30
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
31
|
-
boardId: z.ZodString;
|
|
32
31
|
order: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
32
|
+
boardId: z.ZodString;
|
|
33
33
|
}, z.core.$strip>;
|
|
34
34
|
declare const updateColumnSchema: z.ZodObject<{
|
|
35
35
|
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
@@ -109,6 +109,58 @@ declare function getAllBoards(adapter: Adapter, params?: z.infer<typeof BoardLis
|
|
|
109
109
|
*/
|
|
110
110
|
declare function getBoardById(adapter: Adapter, id: string): Promise<BoardWithColumns | null>;
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Input for creating a new Kanban task.
|
|
114
|
+
*/
|
|
115
|
+
interface CreateKanbanTaskInput {
|
|
116
|
+
title: string;
|
|
117
|
+
columnId: string;
|
|
118
|
+
description?: string;
|
|
119
|
+
priority?: Priority;
|
|
120
|
+
assigneeId?: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create a new task in a Kanban column.
|
|
124
|
+
* Computes the next order value from existing tasks in the column.
|
|
125
|
+
*
|
|
126
|
+
* @remarks **Security:** No authorization hooks (onBeforeCreateTask) are called.
|
|
127
|
+
* The caller is responsible for any access-control checks before invoking this
|
|
128
|
+
* function.
|
|
129
|
+
*
|
|
130
|
+
* @param adapter - The database adapter
|
|
131
|
+
* @param input - Task creation input
|
|
132
|
+
*/
|
|
133
|
+
declare function createKanbanTask(adapter: Adapter, input: CreateKanbanTaskInput): Promise<Task>;
|
|
134
|
+
/**
|
|
135
|
+
* Find a board by slug, or create it with the given name and custom column titles.
|
|
136
|
+
*
|
|
137
|
+
* Concurrency-safe at two levels:
|
|
138
|
+
* - **Same process**: concurrent calls with the same slug share a single in-flight
|
|
139
|
+
* Promise (via `_pendingBoardCreations`), so only one DB write is attempted.
|
|
140
|
+
* - **Cross-instance**: the DB `unique` constraint on `slug` causes the losing
|
|
141
|
+
* write to throw; the catch block re-fetches and returns the winner's board.
|
|
142
|
+
*
|
|
143
|
+
* @remarks **Security:** No authorization hooks are called. The caller is
|
|
144
|
+
* responsible for any access-control checks before invoking this function.
|
|
145
|
+
*
|
|
146
|
+
* @param adapter - The database adapter
|
|
147
|
+
* @param slug - Unique URL-safe slug for the board
|
|
148
|
+
* @param name - Display name for the board (used only on creation)
|
|
149
|
+
* @param columnTitles - Ordered list of column names to create (used only on creation)
|
|
150
|
+
*/
|
|
151
|
+
declare function findOrCreateKanbanBoard(adapter: Adapter, slug: string, name: string, columnTitles: string[]): Promise<Board>;
|
|
152
|
+
/**
|
|
153
|
+
* Retrieve all columns for a given board, sorted by order.
|
|
154
|
+
* Co-located with mutations because it is primarily used alongside
|
|
155
|
+
* {@link createKanbanTask} to resolve column IDs before task creation.
|
|
156
|
+
*
|
|
157
|
+
* @remarks **Security:** No authorization hooks are called.
|
|
158
|
+
*
|
|
159
|
+
* @param adapter - The database adapter
|
|
160
|
+
* @param boardId - The board ID
|
|
161
|
+
*/
|
|
162
|
+
declare function getKanbanColumnsByBoardId(adapter: Adapter, boardId: string): Promise<Column[]>;
|
|
163
|
+
|
|
112
164
|
/**
|
|
113
165
|
* Route keys for the Kanban plugin — matches the keys returned by
|
|
114
166
|
* `stackClient.router.getRoute(path).routeKey`.
|
|
@@ -271,12 +323,12 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
271
323
|
method: "POST";
|
|
272
324
|
body: z.ZodObject<{
|
|
273
325
|
description: z.ZodOptional<z.ZodString>;
|
|
274
|
-
name: z.ZodString;
|
|
275
|
-
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
276
|
-
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
277
326
|
slug: z.ZodOptional<z.ZodString>;
|
|
278
327
|
ownerId: z.ZodOptional<z.ZodString>;
|
|
279
328
|
organizationId: z.ZodOptional<z.ZodString>;
|
|
329
|
+
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
330
|
+
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
331
|
+
name: z.ZodString;
|
|
280
332
|
}, z.core.$strip>;
|
|
281
333
|
}, {
|
|
282
334
|
columns: ColumnWithTasks[];
|
|
@@ -293,12 +345,12 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
293
345
|
method: "PUT";
|
|
294
346
|
body: z.ZodObject<{
|
|
295
347
|
description: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
296
|
-
name: z.ZodOptional<z.ZodString>;
|
|
297
|
-
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
298
|
-
updatedAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
299
348
|
slug: z.ZodOptional<z.ZodString>;
|
|
300
349
|
ownerId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
301
350
|
organizationId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
351
|
+
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
352
|
+
updatedAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
353
|
+
name: z.ZodOptional<z.ZodString>;
|
|
302
354
|
}, z.core.$strip>;
|
|
303
355
|
}, Board>;
|
|
304
356
|
readonly deleteBoard: better_call.StrictEndpoint<"/boards/:id", {
|
|
@@ -312,8 +364,8 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
312
364
|
title: z.ZodString;
|
|
313
365
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
314
366
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
315
|
-
boardId: z.ZodString;
|
|
316
367
|
order: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
368
|
+
boardId: z.ZodString;
|
|
317
369
|
}, z.core.$strip>;
|
|
318
370
|
}, Column>;
|
|
319
371
|
readonly updateColumn: better_call.StrictEndpoint<"/columns/:id", {
|
|
@@ -322,8 +374,8 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
322
374
|
title: z.ZodOptional<z.ZodString>;
|
|
323
375
|
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
324
376
|
updatedAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
325
|
-
boardId: z.ZodOptional<z.ZodString>;
|
|
326
377
|
order: z.ZodOptional<z.ZodDefault<z.ZodOptional<z.ZodNumber>>>;
|
|
378
|
+
boardId: z.ZodOptional<z.ZodString>;
|
|
327
379
|
}, z.core.$strip>;
|
|
328
380
|
}, Column>;
|
|
329
381
|
readonly deleteColumn: better_call.StrictEndpoint<"/columns/:id", {
|
|
@@ -406,6 +458,9 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
406
458
|
getAllBoards: (params?: Parameters<typeof getAllBoards>[1]) => Promise<BoardListResult>;
|
|
407
459
|
getBoardById: (id: string) => Promise<BoardWithColumns | null>;
|
|
408
460
|
prefetchForRoute: KanbanPrefetchForRoute;
|
|
461
|
+
createTask: (input: Parameters<typeof createKanbanTask>[1]) => Promise<Task>;
|
|
462
|
+
findOrCreateBoard: (slug: string, name: string, columnTitles: string[]) => Promise<Board>;
|
|
463
|
+
getColumnsByBoardId: (boardId: string) => Promise<Column[]>;
|
|
409
464
|
}>;
|
|
410
465
|
type KanbanApiRouter = ReturnType<ReturnType<typeof kanbanBackendPlugin>["routes"]>;
|
|
411
466
|
|
|
@@ -441,5 +496,5 @@ declare const KANBAN_QUERY_KEYS: {
|
|
|
441
496
|
boardDetail: (boardId: string) => readonly ["boards", "detail", string];
|
|
442
497
|
};
|
|
443
498
|
|
|
444
|
-
export { getBoardById as d,
|
|
445
|
-
export type { BoardListResult as B, KanbanApiRouter as K, KanbanRouteKey as a, KanbanApiContext as b, KanbanBackendHooks as c, BoardsListDiscriminator as
|
|
499
|
+
export { getBoardById as d, createKanbanTask as e, findOrCreateKanbanBoard as f, getAllBoards as g, getKanbanColumnsByBoardId as h, KANBAN_QUERY_KEYS as i, kanbanBackendPlugin as k };
|
|
500
|
+
export type { BoardListResult as B, CreateKanbanTaskInput as C, KanbanApiRouter as K, KanbanRouteKey as a, KanbanApiContext as b, KanbanBackendHooks as c, BoardsListDiscriminator as j };
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
|
|
2
2
|
import * as better_call from 'better-call';
|
|
3
3
|
import { Adapter } from '@btst/db';
|
|
4
|
-
import { B as BoardWithColumns,
|
|
4
|
+
import { B as BoardWithColumns, P as Priority, T as Task, d as Board, e as Column, C as ColumnWithTasks } from './stack.DJaKVY7v.cjs';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { QueryClient } from '@tanstack/react-query';
|
|
7
7
|
|
|
8
8
|
declare const createBoardSchema: z.ZodObject<{
|
|
9
9
|
description: z.ZodOptional<z.ZodString>;
|
|
10
|
-
name: z.ZodString;
|
|
11
|
-
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
12
|
-
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
13
10
|
slug: z.ZodOptional<z.ZodString>;
|
|
14
11
|
ownerId: z.ZodOptional<z.ZodString>;
|
|
15
12
|
organizationId: z.ZodOptional<z.ZodString>;
|
|
13
|
+
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
14
|
+
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
15
|
+
name: z.ZodString;
|
|
16
16
|
}, z.core.$strip>;
|
|
17
17
|
declare const updateBoardSchema: z.ZodObject<{
|
|
18
18
|
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
@@ -28,8 +28,8 @@ declare const createColumnSchema: z.ZodObject<{
|
|
|
28
28
|
title: z.ZodString;
|
|
29
29
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
30
30
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
31
|
-
boardId: z.ZodString;
|
|
32
31
|
order: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
32
|
+
boardId: z.ZodString;
|
|
33
33
|
}, z.core.$strip>;
|
|
34
34
|
declare const updateColumnSchema: z.ZodObject<{
|
|
35
35
|
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
@@ -109,6 +109,58 @@ declare function getAllBoards(adapter: Adapter, params?: z.infer<typeof BoardLis
|
|
|
109
109
|
*/
|
|
110
110
|
declare function getBoardById(adapter: Adapter, id: string): Promise<BoardWithColumns | null>;
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Input for creating a new Kanban task.
|
|
114
|
+
*/
|
|
115
|
+
interface CreateKanbanTaskInput {
|
|
116
|
+
title: string;
|
|
117
|
+
columnId: string;
|
|
118
|
+
description?: string;
|
|
119
|
+
priority?: Priority;
|
|
120
|
+
assigneeId?: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create a new task in a Kanban column.
|
|
124
|
+
* Computes the next order value from existing tasks in the column.
|
|
125
|
+
*
|
|
126
|
+
* @remarks **Security:** No authorization hooks (onBeforeCreateTask) are called.
|
|
127
|
+
* The caller is responsible for any access-control checks before invoking this
|
|
128
|
+
* function.
|
|
129
|
+
*
|
|
130
|
+
* @param adapter - The database adapter
|
|
131
|
+
* @param input - Task creation input
|
|
132
|
+
*/
|
|
133
|
+
declare function createKanbanTask(adapter: Adapter, input: CreateKanbanTaskInput): Promise<Task>;
|
|
134
|
+
/**
|
|
135
|
+
* Find a board by slug, or create it with the given name and custom column titles.
|
|
136
|
+
*
|
|
137
|
+
* Concurrency-safe at two levels:
|
|
138
|
+
* - **Same process**: concurrent calls with the same slug share a single in-flight
|
|
139
|
+
* Promise (via `_pendingBoardCreations`), so only one DB write is attempted.
|
|
140
|
+
* - **Cross-instance**: the DB `unique` constraint on `slug` causes the losing
|
|
141
|
+
* write to throw; the catch block re-fetches and returns the winner's board.
|
|
142
|
+
*
|
|
143
|
+
* @remarks **Security:** No authorization hooks are called. The caller is
|
|
144
|
+
* responsible for any access-control checks before invoking this function.
|
|
145
|
+
*
|
|
146
|
+
* @param adapter - The database adapter
|
|
147
|
+
* @param slug - Unique URL-safe slug for the board
|
|
148
|
+
* @param name - Display name for the board (used only on creation)
|
|
149
|
+
* @param columnTitles - Ordered list of column names to create (used only on creation)
|
|
150
|
+
*/
|
|
151
|
+
declare function findOrCreateKanbanBoard(adapter: Adapter, slug: string, name: string, columnTitles: string[]): Promise<Board>;
|
|
152
|
+
/**
|
|
153
|
+
* Retrieve all columns for a given board, sorted by order.
|
|
154
|
+
* Co-located with mutations because it is primarily used alongside
|
|
155
|
+
* {@link createKanbanTask} to resolve column IDs before task creation.
|
|
156
|
+
*
|
|
157
|
+
* @remarks **Security:** No authorization hooks are called.
|
|
158
|
+
*
|
|
159
|
+
* @param adapter - The database adapter
|
|
160
|
+
* @param boardId - The board ID
|
|
161
|
+
*/
|
|
162
|
+
declare function getKanbanColumnsByBoardId(adapter: Adapter, boardId: string): Promise<Column[]>;
|
|
163
|
+
|
|
112
164
|
/**
|
|
113
165
|
* Route keys for the Kanban plugin — matches the keys returned by
|
|
114
166
|
* `stackClient.router.getRoute(path).routeKey`.
|
|
@@ -271,12 +323,12 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
271
323
|
method: "POST";
|
|
272
324
|
body: z.ZodObject<{
|
|
273
325
|
description: z.ZodOptional<z.ZodString>;
|
|
274
|
-
name: z.ZodString;
|
|
275
|
-
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
276
|
-
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
277
326
|
slug: z.ZodOptional<z.ZodString>;
|
|
278
327
|
ownerId: z.ZodOptional<z.ZodString>;
|
|
279
328
|
organizationId: z.ZodOptional<z.ZodString>;
|
|
329
|
+
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
330
|
+
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
331
|
+
name: z.ZodString;
|
|
280
332
|
}, z.core.$strip>;
|
|
281
333
|
}, {
|
|
282
334
|
columns: ColumnWithTasks[];
|
|
@@ -293,12 +345,12 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
293
345
|
method: "PUT";
|
|
294
346
|
body: z.ZodObject<{
|
|
295
347
|
description: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
296
|
-
name: z.ZodOptional<z.ZodString>;
|
|
297
|
-
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
298
|
-
updatedAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
299
348
|
slug: z.ZodOptional<z.ZodString>;
|
|
300
349
|
ownerId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
301
350
|
organizationId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
351
|
+
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
352
|
+
updatedAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
353
|
+
name: z.ZodOptional<z.ZodString>;
|
|
302
354
|
}, z.core.$strip>;
|
|
303
355
|
}, Board>;
|
|
304
356
|
readonly deleteBoard: better_call.StrictEndpoint<"/boards/:id", {
|
|
@@ -312,8 +364,8 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
312
364
|
title: z.ZodString;
|
|
313
365
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
314
366
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
315
|
-
boardId: z.ZodString;
|
|
316
367
|
order: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
368
|
+
boardId: z.ZodString;
|
|
317
369
|
}, z.core.$strip>;
|
|
318
370
|
}, Column>;
|
|
319
371
|
readonly updateColumn: better_call.StrictEndpoint<"/columns/:id", {
|
|
@@ -322,8 +374,8 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
322
374
|
title: z.ZodOptional<z.ZodString>;
|
|
323
375
|
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
324
376
|
updatedAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
325
|
-
boardId: z.ZodOptional<z.ZodString>;
|
|
326
377
|
order: z.ZodOptional<z.ZodDefault<z.ZodOptional<z.ZodNumber>>>;
|
|
378
|
+
boardId: z.ZodOptional<z.ZodString>;
|
|
327
379
|
}, z.core.$strip>;
|
|
328
380
|
}, Column>;
|
|
329
381
|
readonly deleteColumn: better_call.StrictEndpoint<"/columns/:id", {
|
|
@@ -406,6 +458,9 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
406
458
|
getAllBoards: (params?: Parameters<typeof getAllBoards>[1]) => Promise<BoardListResult>;
|
|
407
459
|
getBoardById: (id: string) => Promise<BoardWithColumns | null>;
|
|
408
460
|
prefetchForRoute: KanbanPrefetchForRoute;
|
|
461
|
+
createTask: (input: Parameters<typeof createKanbanTask>[1]) => Promise<Task>;
|
|
462
|
+
findOrCreateBoard: (slug: string, name: string, columnTitles: string[]) => Promise<Board>;
|
|
463
|
+
getColumnsByBoardId: (boardId: string) => Promise<Column[]>;
|
|
409
464
|
}>;
|
|
410
465
|
type KanbanApiRouter = ReturnType<ReturnType<typeof kanbanBackendPlugin>["routes"]>;
|
|
411
466
|
|
|
@@ -441,5 +496,5 @@ declare const KANBAN_QUERY_KEYS: {
|
|
|
441
496
|
boardDetail: (boardId: string) => readonly ["boards", "detail", string];
|
|
442
497
|
};
|
|
443
498
|
|
|
444
|
-
export { getBoardById as d,
|
|
445
|
-
export type { BoardListResult as B, KanbanApiRouter as K, KanbanRouteKey as a, KanbanApiContext as b, KanbanBackendHooks as c, BoardsListDiscriminator as
|
|
499
|
+
export { getBoardById as d, createKanbanTask as e, findOrCreateKanbanBoard as f, getAllBoards as g, getKanbanColumnsByBoardId as h, KANBAN_QUERY_KEYS as i, kanbanBackendPlugin as k };
|
|
500
|
+
export type { BoardListResult as B, CreateKanbanTaskInput as C, KanbanApiRouter as K, KanbanRouteKey as a, KanbanApiContext as b, KanbanBackendHooks as c, BoardsListDiscriminator as j };
|
|
@@ -78,6 +78,35 @@ declare function getContentItemById(adapter: Adapter, id: string): Promise<Seria
|
|
|
78
78
|
*/
|
|
79
79
|
declare function getContentItemBySlug(adapter: Adapter, contentTypeSlug: string, slug: string): Promise<SerializedContentItemWithType | null>;
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Input for creating a new CMS content item.
|
|
83
|
+
*/
|
|
84
|
+
interface CreateCMSContentItemInput {
|
|
85
|
+
/** URL-safe slug for the item */
|
|
86
|
+
slug: string;
|
|
87
|
+
/** Arbitrary data payload — should match the content type schema */
|
|
88
|
+
data: Record<string, unknown>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Create a new content item for a content type (looked up by slug).
|
|
92
|
+
*
|
|
93
|
+
* Bypasses Zod schema validation and relation processing — the caller is
|
|
94
|
+
* responsible for providing valid, relation-free data. For relation fields or
|
|
95
|
+
* schema validation, use the HTTP endpoint instead.
|
|
96
|
+
*
|
|
97
|
+
* Throws if the content type is not found or the slug is already taken within
|
|
98
|
+
* that content type.
|
|
99
|
+
*
|
|
100
|
+
* @remarks **Security:** No authorization hooks (`onBeforeCreate`, `onAfterCreate`)
|
|
101
|
+
* are called. The caller is responsible for any access-control checks before
|
|
102
|
+
* invoking this function.
|
|
103
|
+
*
|
|
104
|
+
* @param adapter - The database adapter
|
|
105
|
+
* @param contentTypeSlug - Slug of the target content type
|
|
106
|
+
* @param input - Item slug and data payload
|
|
107
|
+
*/
|
|
108
|
+
declare function createCMSContentItem(adapter: Adapter, contentTypeSlug: string, input: CreateCMSContentItemInput): Promise<SerializedContentItem>;
|
|
109
|
+
|
|
81
110
|
/**
|
|
82
111
|
* Route keys for the CMS plugin — matches the keys returned by
|
|
83
112
|
* `stackClient.router.getRoute(path).routeKey`.
|
|
@@ -257,6 +286,7 @@ declare const cmsBackendPlugin: (config: CMSBackendConfig) => _btst_stack_plugin
|
|
|
257
286
|
getContentItemBySlug: (contentTypeSlug: string, slug: string) => Promise<SerializedContentItemWithType<Record<string, unknown>> | null>;
|
|
258
287
|
getContentItemById: (id: string) => Promise<SerializedContentItemWithType<Record<string, unknown>> | null>;
|
|
259
288
|
prefetchForRoute: CMSPrefetchForRoute;
|
|
289
|
+
createContentItem: (typeSlug: string, input: Parameters<typeof createCMSContentItem>[2]) => Promise<SerializedContentItem>;
|
|
260
290
|
}>;
|
|
261
291
|
type CMSApiRouter = ReturnType<ReturnType<typeof cmsBackendPlugin>["routes"]>;
|
|
262
292
|
|
|
@@ -293,5 +323,5 @@ declare const CMS_QUERY_KEYS: {
|
|
|
293
323
|
contentDetail: (typeSlug: string, id: string) => readonly ["cmsContent", "detail", string, string];
|
|
294
324
|
};
|
|
295
325
|
|
|
296
|
-
export { cmsBackendPlugin as c, getAllContentItems as d, getContentItemBySlug as e, getContentItemById as f, getAllContentTypes as g, serializeContentItem as h, serializeContentItemWithType as i,
|
|
297
|
-
export type { CMSApiRouter as C, ContentListDiscriminator as a, CMSRouteKey as b };
|
|
326
|
+
export { cmsBackendPlugin as c, getAllContentItems as d, getContentItemBySlug as e, getContentItemById as f, getAllContentTypes as g, serializeContentItem as h, serializeContentItemWithType as i, createCMSContentItem as j, CMS_QUERY_KEYS as l, serializeContentType as s };
|
|
327
|
+
export type { CMSApiRouter as C, ContentListDiscriminator as a, CMSRouteKey as b, CreateCMSContentItemInput as k };
|
|
@@ -5,7 +5,7 @@ import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
|
|
|
5
5
|
import * as better_call from 'better-call';
|
|
6
6
|
import * as zod_v4_core from 'zod/v4/core';
|
|
7
7
|
import * as zod from 'zod';
|
|
8
|
-
import {
|
|
8
|
+
import { Tool, LanguageModel } from 'ai';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Context passed to AI Chat API hooks
|
|
@@ -67,6 +67,18 @@ interface AiChatBackendHooks {
|
|
|
67
67
|
* @param context - Request context with headers, etc.
|
|
68
68
|
*/
|
|
69
69
|
onBeforeDeleteConversation?: (conversationId: string, context: ChatApiContext) => Promise<boolean> | boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Called after the structural routeName/allowlist validation, with the list
|
|
72
|
+
* of tool names that passed. Return a filtered subset to further restrict
|
|
73
|
+
* which tools the LLM sees, or return [] to suppress all page tools.
|
|
74
|
+
* Throw an Error to abort the entire chat request with a 403 response.
|
|
75
|
+
* Not called when no tools passed the structural validation step.
|
|
76
|
+
*
|
|
77
|
+
* @param toolNames - Names that passed the routeName allowlist check
|
|
78
|
+
* @param routeName - routeName claimed by the request (may be undefined)
|
|
79
|
+
* @param context - Full request context (headers, body, etc.)
|
|
80
|
+
*/
|
|
81
|
+
onBeforeToolsActivated?: (toolNames: string[], routeName: string | undefined, context: ChatApiContext) => Promise<string[]> | string[];
|
|
70
82
|
/**
|
|
71
83
|
* Called after a chat message is processed successfully
|
|
72
84
|
* @param conversationId - ID of the conversation
|
|
@@ -152,6 +164,23 @@ type AiChatMode = "authenticated" | "public";
|
|
|
152
164
|
/**
|
|
153
165
|
* Configuration for AI Chat backend plugin
|
|
154
166
|
*/
|
|
167
|
+
/**
|
|
168
|
+
* Extracts only the literal (non-index-signature) keys from a type.
|
|
169
|
+
* For `Record<string, T>` this resolves to `never`, so collision checks are
|
|
170
|
+
* skipped when the tools map is typed with a broad string index.
|
|
171
|
+
*/
|
|
172
|
+
type KnownKeys<T> = {
|
|
173
|
+
[K in keyof T]: string extends K ? never : K;
|
|
174
|
+
}[keyof T];
|
|
175
|
+
/**
|
|
176
|
+
* Ensures `TClientTools` has no keys that are also literal keys in `TTools`.
|
|
177
|
+
* Colliding keys are mapped to `never`, which produces a compile-time error
|
|
178
|
+
* at the point of the duplicate key. When `TTools` uses a string index
|
|
179
|
+
* signature the check is skipped to avoid false positives.
|
|
180
|
+
*/
|
|
181
|
+
type NoKeyCollision<TTools, TClientTools extends Record<string, Tool>> = KnownKeys<TTools> & keyof TClientTools extends never ? TClientTools : {
|
|
182
|
+
[K in keyof TClientTools]: K extends KnownKeys<TTools> ? never : TClientTools[K];
|
|
183
|
+
};
|
|
155
184
|
interface AiChatBackendConfig {
|
|
156
185
|
/**
|
|
157
186
|
* The language model to use for chat completions.
|
|
@@ -182,6 +211,29 @@ interface AiChatBackendConfig {
|
|
|
182
211
|
* @see https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling
|
|
183
212
|
*/
|
|
184
213
|
tools?: Record<string, Tool>;
|
|
214
|
+
/**
|
|
215
|
+
* Enable route-aware page tools.
|
|
216
|
+
* When true, the server will include tool schemas for client-side page tools
|
|
217
|
+
* (e.g. fillBlogForm, updatePageLayers) based on the availableTools list
|
|
218
|
+
* sent with each request.
|
|
219
|
+
* @default false
|
|
220
|
+
*/
|
|
221
|
+
enablePageTools?: boolean;
|
|
222
|
+
/**
|
|
223
|
+
* Custom client-side tool schemas for non-BTST pages.
|
|
224
|
+
* Merged with built-in page tool schemas (fillBlogForm, updatePageLayers).
|
|
225
|
+
* Only included when enablePageTools is true and the tool name appears in
|
|
226
|
+
* the availableTools list sent with the request.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* clientToolSchemas: {
|
|
230
|
+
* addToCart: tool({
|
|
231
|
+
* description: "Add current product to cart",
|
|
232
|
+
* parameters: z.object({ quantity: z.number().int().min(1) }),
|
|
233
|
+
* }),
|
|
234
|
+
* }
|
|
235
|
+
*/
|
|
236
|
+
clientToolSchemas?: Record<string, Tool>;
|
|
185
237
|
/**
|
|
186
238
|
* Optional hooks for customizing plugin behavior
|
|
187
239
|
*/
|
|
@@ -194,7 +246,10 @@ interface AiChatBackendConfig {
|
|
|
194
246
|
*
|
|
195
247
|
* @param config - Configuration including model, tools, and optional hooks
|
|
196
248
|
*/
|
|
197
|
-
declare const aiChatBackendPlugin: (config: AiChatBackendConfig
|
|
249
|
+
declare const aiChatBackendPlugin: <TTools extends Record<string, Tool> = Record<never, Tool>, TClientTools extends Record<string, Tool> = Record<never, Tool>>(config: Omit<AiChatBackendConfig, "tools" | "clientToolSchemas"> & {
|
|
250
|
+
tools?: TTools;
|
|
251
|
+
clientToolSchemas?: NoKeyCollision<TTools, TClientTools>;
|
|
252
|
+
}) => _btst_stack_plugins_api.BackendPlugin<{
|
|
198
253
|
chat: better_call.StrictEndpoint<"/chat", {
|
|
199
254
|
method: "POST";
|
|
200
255
|
body: zod.ZodObject<{
|
|
@@ -223,6 +278,9 @@ declare const aiChatBackendPlugin: (config: AiChatBackendConfig) => _btst_stack_
|
|
|
223
278
|
}, zod_v4_core.$strip>]>>;
|
|
224
279
|
conversationId: zod.ZodOptional<zod.ZodString>;
|
|
225
280
|
model: zod.ZodOptional<zod.ZodString>;
|
|
281
|
+
pageContext: zod.ZodOptional<zod.ZodString>;
|
|
282
|
+
availableTools: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
|
|
283
|
+
routeName: zod.ZodOptional<zod.ZodString>;
|
|
226
284
|
}, zod_v4_core.$strip>;
|
|
227
285
|
}, Response>;
|
|
228
286
|
createConversation: better_call.StrictEndpoint<"/chat/conversations", {
|
|
@@ -5,7 +5,7 @@ import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
|
|
|
5
5
|
import * as better_call from 'better-call';
|
|
6
6
|
import * as zod_v4_core from 'zod/v4/core';
|
|
7
7
|
import * as zod from 'zod';
|
|
8
|
-
import {
|
|
8
|
+
import { Tool, LanguageModel } from 'ai';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Context passed to AI Chat API hooks
|
|
@@ -67,6 +67,18 @@ interface AiChatBackendHooks {
|
|
|
67
67
|
* @param context - Request context with headers, etc.
|
|
68
68
|
*/
|
|
69
69
|
onBeforeDeleteConversation?: (conversationId: string, context: ChatApiContext) => Promise<boolean> | boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Called after the structural routeName/allowlist validation, with the list
|
|
72
|
+
* of tool names that passed. Return a filtered subset to further restrict
|
|
73
|
+
* which tools the LLM sees, or return [] to suppress all page tools.
|
|
74
|
+
* Throw an Error to abort the entire chat request with a 403 response.
|
|
75
|
+
* Not called when no tools passed the structural validation step.
|
|
76
|
+
*
|
|
77
|
+
* @param toolNames - Names that passed the routeName allowlist check
|
|
78
|
+
* @param routeName - routeName claimed by the request (may be undefined)
|
|
79
|
+
* @param context - Full request context (headers, body, etc.)
|
|
80
|
+
*/
|
|
81
|
+
onBeforeToolsActivated?: (toolNames: string[], routeName: string | undefined, context: ChatApiContext) => Promise<string[]> | string[];
|
|
70
82
|
/**
|
|
71
83
|
* Called after a chat message is processed successfully
|
|
72
84
|
* @param conversationId - ID of the conversation
|
|
@@ -152,6 +164,23 @@ type AiChatMode = "authenticated" | "public";
|
|
|
152
164
|
/**
|
|
153
165
|
* Configuration for AI Chat backend plugin
|
|
154
166
|
*/
|
|
167
|
+
/**
|
|
168
|
+
* Extracts only the literal (non-index-signature) keys from a type.
|
|
169
|
+
* For `Record<string, T>` this resolves to `never`, so collision checks are
|
|
170
|
+
* skipped when the tools map is typed with a broad string index.
|
|
171
|
+
*/
|
|
172
|
+
type KnownKeys<T> = {
|
|
173
|
+
[K in keyof T]: string extends K ? never : K;
|
|
174
|
+
}[keyof T];
|
|
175
|
+
/**
|
|
176
|
+
* Ensures `TClientTools` has no keys that are also literal keys in `TTools`.
|
|
177
|
+
* Colliding keys are mapped to `never`, which produces a compile-time error
|
|
178
|
+
* at the point of the duplicate key. When `TTools` uses a string index
|
|
179
|
+
* signature the check is skipped to avoid false positives.
|
|
180
|
+
*/
|
|
181
|
+
type NoKeyCollision<TTools, TClientTools extends Record<string, Tool>> = KnownKeys<TTools> & keyof TClientTools extends never ? TClientTools : {
|
|
182
|
+
[K in keyof TClientTools]: K extends KnownKeys<TTools> ? never : TClientTools[K];
|
|
183
|
+
};
|
|
155
184
|
interface AiChatBackendConfig {
|
|
156
185
|
/**
|
|
157
186
|
* The language model to use for chat completions.
|
|
@@ -182,6 +211,29 @@ interface AiChatBackendConfig {
|
|
|
182
211
|
* @see https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling
|
|
183
212
|
*/
|
|
184
213
|
tools?: Record<string, Tool>;
|
|
214
|
+
/**
|
|
215
|
+
* Enable route-aware page tools.
|
|
216
|
+
* When true, the server will include tool schemas for client-side page tools
|
|
217
|
+
* (e.g. fillBlogForm, updatePageLayers) based on the availableTools list
|
|
218
|
+
* sent with each request.
|
|
219
|
+
* @default false
|
|
220
|
+
*/
|
|
221
|
+
enablePageTools?: boolean;
|
|
222
|
+
/**
|
|
223
|
+
* Custom client-side tool schemas for non-BTST pages.
|
|
224
|
+
* Merged with built-in page tool schemas (fillBlogForm, updatePageLayers).
|
|
225
|
+
* Only included when enablePageTools is true and the tool name appears in
|
|
226
|
+
* the availableTools list sent with the request.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* clientToolSchemas: {
|
|
230
|
+
* addToCart: tool({
|
|
231
|
+
* description: "Add current product to cart",
|
|
232
|
+
* parameters: z.object({ quantity: z.number().int().min(1) }),
|
|
233
|
+
* }),
|
|
234
|
+
* }
|
|
235
|
+
*/
|
|
236
|
+
clientToolSchemas?: Record<string, Tool>;
|
|
185
237
|
/**
|
|
186
238
|
* Optional hooks for customizing plugin behavior
|
|
187
239
|
*/
|
|
@@ -194,7 +246,10 @@ interface AiChatBackendConfig {
|
|
|
194
246
|
*
|
|
195
247
|
* @param config - Configuration including model, tools, and optional hooks
|
|
196
248
|
*/
|
|
197
|
-
declare const aiChatBackendPlugin: (config: AiChatBackendConfig
|
|
249
|
+
declare const aiChatBackendPlugin: <TTools extends Record<string, Tool> = Record<never, Tool>, TClientTools extends Record<string, Tool> = Record<never, Tool>>(config: Omit<AiChatBackendConfig, "tools" | "clientToolSchemas"> & {
|
|
250
|
+
tools?: TTools;
|
|
251
|
+
clientToolSchemas?: NoKeyCollision<TTools, TClientTools>;
|
|
252
|
+
}) => _btst_stack_plugins_api.BackendPlugin<{
|
|
198
253
|
chat: better_call.StrictEndpoint<"/chat", {
|
|
199
254
|
method: "POST";
|
|
200
255
|
body: zod.ZodObject<{
|
|
@@ -223,6 +278,9 @@ declare const aiChatBackendPlugin: (config: AiChatBackendConfig) => _btst_stack_
|
|
|
223
278
|
}, zod_v4_core.$strip>]>>;
|
|
224
279
|
conversationId: zod.ZodOptional<zod.ZodString>;
|
|
225
280
|
model: zod.ZodOptional<zod.ZodString>;
|
|
281
|
+
pageContext: zod.ZodOptional<zod.ZodString>;
|
|
282
|
+
availableTools: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
|
|
283
|
+
routeName: zod.ZodOptional<zod.ZodString>;
|
|
226
284
|
}, zod_v4_core.$strip>;
|
|
227
285
|
}, Response>;
|
|
228
286
|
createConversation: better_call.StrictEndpoint<"/chat/conversations", {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
2
2
|
import { QueryClient } from '@tanstack/react-query';
|
|
3
3
|
import { createApiClient } from '@btst/stack/plugins/client';
|
|
4
|
-
import { P as Post, T as Tag, c as createPostSchema, u as updatePostSchema, S as SerializedPost, a as SerializedTag } from './stack.
|
|
4
|
+
import { P as Post, T as Tag, c as createPostSchema, u as updatePostSchema, S as SerializedPost, a as SerializedTag } from './stack.BQmuNl5p.mjs';
|
|
5
5
|
import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
|
|
6
6
|
import * as better_call from 'better-call';
|
|
7
7
|
import { Adapter } from '@btst/db';
|
|
@@ -218,11 +218,11 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
|
|
|
218
218
|
name: z.ZodString;
|
|
219
219
|
slug: z.ZodString;
|
|
220
220
|
}, z.core.$strip>]>>>>;
|
|
221
|
+
title: z.ZodString;
|
|
221
222
|
slug: z.ZodOptional<z.ZodString>;
|
|
222
|
-
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
223
223
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
224
224
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
225
|
-
|
|
225
|
+
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
226
226
|
content: z.ZodString;
|
|
227
227
|
excerpt: z.ZodString;
|
|
228
228
|
image: z.ZodOptional<z.ZodString>;
|