@softr/sdk 0.0.81 → 0.0.83-alpha.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/action.d.ts +21 -18
- package/dist/action.js +12 -26
- package/dist/client.d.ts +1 -2
- package/dist/client.js +1 -2
- package/dist/core/ai.d.ts +76 -0
- package/dist/core/ai.js +64 -0
- package/dist/core/file-upload.d.ts +2 -6
- package/dist/core/file-upload.js +0 -4
- package/dist/core/use-file-upload.d.ts +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/mcp.d.ts +2 -2
- package/dist/package.js +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/package.json +1 -3
- package/skills/softr-sdk/SKILL.md +13 -9
- package/skills/softr-sdk/ai/SKILL.md +168 -0
- package/skills/softr-sdk/auth/SKILL.md +1 -1
- package/skills/softr-sdk/charts-and-metrics/SKILL.md +1 -1
- package/skills/softr-sdk/current-user/SKILL.md +1 -1
- package/skills/softr-sdk/file-uploads/SKILL.md +1 -1
- package/skills/softr-sdk/formatting/SKILL.md +1 -1
- package/skills/softr-sdk/integrations/SKILL.md +8 -9
- package/skills/softr-sdk/mcp/SKILL.md +1 -1
- package/skills/softr-sdk/pwa/SKILL.md +1 -1
- package/skills/softr-sdk/record-mutations/SKILL.md +1 -1
- package/skills/softr-sdk/record-queries/SKILL.md +1 -1
- package/skills/softr-sdk/region-visibility/SKILL.md +1 -1
- package/skills/softr-sdk/routes-and-visibility/SKILL.md +1 -1
- package/skills/softr-sdk/workflows/SKILL.md +1 -1
- package/dist/comments/comments.d.ts +0 -168
- package/dist/comments/comments.js +0 -413
- package/dist/comments/use-comment-composer.d.ts +0 -46
- package/dist/comments/use-comment-composer.js +0 -134
- package/skills/softr-sdk/comments/SKILL.md +0 -178
package/dist/action.d.ts
CHANGED
|
@@ -234,35 +234,38 @@ type IntegrationDefinition<TId extends string> = {
|
|
|
234
234
|
* const res = await listEvents({ query: { timeMin: now, singleEvents: "true" } })
|
|
235
235
|
*/
|
|
236
236
|
declare function defineIntegration<const TId extends string>(definition: IntegrationDefinition<TId>): IntegrationAction<TId>;
|
|
237
|
-
type
|
|
238
|
-
type: "
|
|
239
|
-
|
|
237
|
+
type AiResource = {
|
|
238
|
+
type: "SOFTR_AI";
|
|
239
|
+
model: string;
|
|
240
240
|
};
|
|
241
|
-
|
|
242
|
-
type CommentsAction<TId extends string = string> = {
|
|
241
|
+
type AiAction<TId extends string = string> = Action<AiResource> & {
|
|
243
242
|
id: TId;
|
|
244
|
-
resource: CommentsResource;
|
|
245
243
|
};
|
|
246
|
-
type
|
|
244
|
+
type AiDefinition<TId extends string> = {
|
|
247
245
|
id: TId;
|
|
248
|
-
|
|
246
|
+
model: string;
|
|
247
|
+
permissions: ActionPermissions;
|
|
249
248
|
};
|
|
250
249
|
/**
|
|
251
|
-
* Declares
|
|
250
|
+
* Declares an AI action: a model call run by Softr on its own provider keys and billed to the
|
|
251
|
+
* workspace's AI credits, so nothing has to be connected. `model` is the id of a model from
|
|
252
|
+
* Softr's AI catalog, chosen when the app is built: read the catalog with the `list_ai_models`
|
|
253
|
+
* tool and copy the id exactly. An id outside the catalog is refused when the action is saved.
|
|
252
254
|
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
+
* Every call spends the workspace's credits, so keep the audience to signed-in users unless a
|
|
256
|
+
* public page really needs the call.
|
|
255
257
|
*
|
|
256
|
-
* Pass the returned object to `
|
|
258
|
+
* Pass the returned object to `ai.generate()` or `ai.stream()` at runtime.
|
|
257
259
|
*
|
|
258
260
|
* @example
|
|
259
|
-
* const
|
|
260
|
-
* id: "
|
|
261
|
-
*
|
|
261
|
+
* const summarizeDeal = defineAiAction({
|
|
262
|
+
* id: "summarizeDeal",
|
|
263
|
+
* model: "anthropic-claude-sonnet-4-6",
|
|
264
|
+
* permissions: { userGroupTypes: ["LOGGED_IN_USERS"] },
|
|
262
265
|
* })
|
|
263
266
|
*
|
|
264
|
-
* const
|
|
267
|
+
* const answer = await ai.generate(summarizeDeal, { system: "...", prompt: facts })
|
|
265
268
|
*/
|
|
266
|
-
declare function
|
|
269
|
+
declare function defineAiAction<const TId extends string>(definition: AiDefinition<TId>): AiAction<TId>;
|
|
267
270
|
//#endregion
|
|
268
|
-
export { ActionData, ActionPermissions, ActionRecord, ActionShape,
|
|
271
|
+
export { ActionData, ActionPermissions, ActionRecord, ActionShape, AiAction, DatasourceAction, FieldTypeOf, IntegrationAction, ReadOf, ReadShape, SoftrDatasources, WorkflowAction, defineAiAction, defineIntegration, defineMutation, defineQuery, defineWorkflow };
|
package/dist/action.js
CHANGED
|
@@ -50,37 +50,23 @@ function defineIntegration(definition) {
|
|
|
50
50
|
permissions
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
/**
|
|
54
|
-
* Declares comment threads on the records of a datasource. Each record has one thread.
|
|
55
|
-
*
|
|
56
|
-
* Who may read, post and delete comes from the app's comment settings in Softr, not from code. Two
|
|
57
|
-
* declarations on the same datasource share the same threads.
|
|
58
|
-
*
|
|
59
|
-
* Pass the returned object to `comments.*` from `@softr/sdk/server`.
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* const orderComments = defineComments({
|
|
63
|
-
* id: "orderComments",
|
|
64
|
-
* datasourceId: "8f14e45f-ceea-467a-9d0b-2c1a0e3b5d77",
|
|
65
|
-
* })
|
|
66
|
-
*
|
|
67
|
-
* const thread = await comments.list(orderComments, { recordId })
|
|
68
|
-
*/
|
|
69
|
-
function defineComments(definition) {
|
|
70
|
-
return {
|
|
71
|
-
id: definition.id,
|
|
72
|
-
resource: {
|
|
73
|
-
type: "COMMENTS",
|
|
74
|
-
datasourceId: definition.datasourceId
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
53
|
function isDatasourceAction(value) {
|
|
79
54
|
if (typeof value !== "object" || value === null) return false;
|
|
80
55
|
const candidate = value;
|
|
81
56
|
const resource = candidate.resource;
|
|
82
57
|
return typeof candidate.id === "string" && typeof resource === "object" && resource !== null && resource.type === "DATASOURCE";
|
|
83
58
|
}
|
|
59
|
+
function defineAiAction(definition) {
|
|
60
|
+
const { id, model, permissions } = definition;
|
|
61
|
+
return {
|
|
62
|
+
id,
|
|
63
|
+
resource: {
|
|
64
|
+
type: "SOFTR_AI",
|
|
65
|
+
model
|
|
66
|
+
},
|
|
67
|
+
permissions
|
|
68
|
+
};
|
|
69
|
+
}
|
|
84
70
|
|
|
85
71
|
//#endregion
|
|
86
|
-
export {
|
|
72
|
+
export { defineAiAction, defineIntegration, defineMutation, defineQuery, defineWorkflow, isDatasourceAction };
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { FileItem, useFileUpload } from "./core/use-file-upload.js";
|
|
2
|
-
import { useCommentComposer } from "./comments/use-comment-composer.js";
|
|
3
2
|
import "@tanstack/react-start/client-only";
|
|
4
|
-
export { type FileItem,
|
|
3
|
+
export { type FileItem, useFileUpload };
|
package/dist/client.js
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { AiAction } from "../action.js";
|
|
2
|
+
|
|
3
|
+
//#region src/core/ai.d.ts
|
|
4
|
+
/** A document or image the model reads, by the URL the app holds it under: one of its own uploads, as a rule. */
|
|
5
|
+
interface AiFile {
|
|
6
|
+
/** An https URL Softr may fetch. */
|
|
7
|
+
url: string;
|
|
8
|
+
/** The file's type when the URL does not say, such as `application/pdf`. */
|
|
9
|
+
mimeType?: string;
|
|
10
|
+
}
|
|
11
|
+
/** One earlier turn of a conversation. */
|
|
12
|
+
interface AiMessage {
|
|
13
|
+
role: 'user' | 'assistant';
|
|
14
|
+
content: string;
|
|
15
|
+
}
|
|
16
|
+
interface AiGenerateInit {
|
|
17
|
+
/** What the model is and the rules it answers under. */
|
|
18
|
+
system?: string;
|
|
19
|
+
/** The earlier turns of a conversation, oldest first, before the prompt. Leave out for a one-shot call. */
|
|
20
|
+
messages?: ReadonlyArray<AiMessage>;
|
|
21
|
+
/** What it is asked, with the facts it is given. */
|
|
22
|
+
prompt: string;
|
|
23
|
+
/**
|
|
24
|
+
* A JSON schema the answer has to match. With it, the model is asked for JSON only and the
|
|
25
|
+
* answer comes back parsed in `json` as well as written in `text`.
|
|
26
|
+
*/
|
|
27
|
+
schema?: Record<string, unknown>;
|
|
28
|
+
/** Documents and images the model reads alongside the prompt. */
|
|
29
|
+
files?: ReadonlyArray<AiFile>;
|
|
30
|
+
/** A cap on the answer's length, in tokens; Softr caps it further. */
|
|
31
|
+
maxOutputTokens?: number;
|
|
32
|
+
/**
|
|
33
|
+
* How hard a reasoning model thinks before it answers. A model that does not reason ignores it;
|
|
34
|
+
* the catalog says which do. Left out, the provider's default applies.
|
|
35
|
+
*/
|
|
36
|
+
reasoning?: 'low' | 'medium' | 'high';
|
|
37
|
+
/** How varied the answer is, 0 to 1: 0 for an extraction, higher for a draft. A low default when left out. */
|
|
38
|
+
temperature?: number;
|
|
39
|
+
signal?: AbortSignal;
|
|
40
|
+
}
|
|
41
|
+
interface AiUsage {
|
|
42
|
+
inputTokens: number;
|
|
43
|
+
outputTokens: number;
|
|
44
|
+
}
|
|
45
|
+
interface AiAnswer {
|
|
46
|
+
/** The answer as the model wrote it. */
|
|
47
|
+
text: string;
|
|
48
|
+
/** The answer parsed as JSON when `schema` was given and the model kept to it; `null` otherwise. */
|
|
49
|
+
json: unknown;
|
|
50
|
+
usage: AiUsage;
|
|
51
|
+
/** The model that answered. */
|
|
52
|
+
model: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Thrown when the model call was refused or failed. `status` is the HTTP status Softr answered
|
|
56
|
+
* with; 402 means the workspace has no AI credits left.
|
|
57
|
+
*/
|
|
58
|
+
declare class AiError extends Error {
|
|
59
|
+
readonly status: number;
|
|
60
|
+
constructor(status: number, message: string);
|
|
61
|
+
}
|
|
62
|
+
/** Runs the action once and answers when the model is done. */
|
|
63
|
+
declare function aiGenerate(action: AiAction, init: AiGenerateInit): Promise<AiAnswer>;
|
|
64
|
+
/**
|
|
65
|
+
* Runs the action and answers while the model writes. The returned `Response` body is a stream of
|
|
66
|
+
* Server-Sent Events, one JSON object per `data:` line: `{ "text": "..." }` for each piece of the
|
|
67
|
+
* answer, then `{ "done": true, "usage": {...}, "model": "..." }`, or `{ "error": "..." }` in its
|
|
68
|
+
* place. Hand it to the browser as a `Response` with `Content-Type: text/event-stream`.
|
|
69
|
+
*/
|
|
70
|
+
declare function aiStream(action: AiAction, init: AiGenerateInit): Promise<Response>;
|
|
71
|
+
declare const ai: {
|
|
72
|
+
generate: typeof aiGenerate;
|
|
73
|
+
stream: typeof aiStream;
|
|
74
|
+
};
|
|
75
|
+
//#endregion
|
|
76
|
+
export { AiAnswer, AiError, AiFile, AiGenerateInit, AiMessage, AiUsage, ai };
|
package/dist/core/ai.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { fetch } from "../fetch.js";
|
|
2
|
+
import { readSessionToken } from "../auth/session.js";
|
|
3
|
+
import { describeFailure, dsUrl, refererHeader } from "../datasource/record.js";
|
|
4
|
+
|
|
5
|
+
//#region src/core/ai.ts
|
|
6
|
+
/**
|
|
7
|
+
* Thrown when the model call was refused or failed. `status` is the HTTP status Softr answered
|
|
8
|
+
* with; 402 means the workspace has no AI credits left.
|
|
9
|
+
*/
|
|
10
|
+
var AiError = class extends Error {
|
|
11
|
+
status;
|
|
12
|
+
constructor(status, message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "AiError";
|
|
15
|
+
this.status = status;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
function body(init) {
|
|
19
|
+
return JSON.stringify({
|
|
20
|
+
system: init.system,
|
|
21
|
+
messages: init.messages,
|
|
22
|
+
prompt: init.prompt,
|
|
23
|
+
schema: init.schema,
|
|
24
|
+
files: init.files,
|
|
25
|
+
maxOutputTokens: init.maxOutputTokens,
|
|
26
|
+
reasoning: init.reasoning,
|
|
27
|
+
temperature: init.temperature
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async function post(action, path, init) {
|
|
31
|
+
if (init.signal?.aborted) throw init.signal.reason ?? new DOMException("The operation was aborted.", "AbortError");
|
|
32
|
+
const res = await fetch(`${dsUrl(action.id)}/${path}`, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: {
|
|
35
|
+
"Content-Type": "application/json",
|
|
36
|
+
"Authorization": `Bearer ${readSessionToken()}`,
|
|
37
|
+
...refererHeader()
|
|
38
|
+
},
|
|
39
|
+
body: body(init),
|
|
40
|
+
signal: init.signal
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok) throw new AiError(res.status, `AI call "${action.id}" failed: ${await describeFailure(res)}`);
|
|
43
|
+
return res;
|
|
44
|
+
}
|
|
45
|
+
/** Runs the action once and answers when the model is done. */
|
|
46
|
+
async function aiGenerate(action, init) {
|
|
47
|
+
return await (await post(action, "softr-ai/generate", init)).json();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Runs the action and answers while the model writes. The returned `Response` body is a stream of
|
|
51
|
+
* Server-Sent Events, one JSON object per `data:` line: `{ "text": "..." }` for each piece of the
|
|
52
|
+
* answer, then `{ "done": true, "usage": {...}, "model": "..." }`, or `{ "error": "..." }` in its
|
|
53
|
+
* place. Hand it to the browser as a `Response` with `Content-Type: text/event-stream`.
|
|
54
|
+
*/
|
|
55
|
+
async function aiStream(action, init) {
|
|
56
|
+
return post(action, "softr-ai/generate/stream", init);
|
|
57
|
+
}
|
|
58
|
+
const ai = {
|
|
59
|
+
generate: aiGenerate,
|
|
60
|
+
stream: aiStream
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
//#endregion
|
|
64
|
+
export { AiError, ai };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DatasourceAction } from "../action.js";
|
|
2
2
|
|
|
3
3
|
//#region src/core/file-upload.d.ts
|
|
4
4
|
|
|
@@ -12,10 +12,6 @@ type FileAttachment = {
|
|
|
12
12
|
id: string;
|
|
13
13
|
type?: string | null;
|
|
14
14
|
};
|
|
15
|
-
|
|
16
|
-
* A COMMENTS action uploads a comment attachment.
|
|
17
|
-
* The platform checks the comment settings.
|
|
18
|
-
*/
|
|
19
|
-
declare function upload(action: DatasourceAction | CommentsAction, file: File): Promise<FileAttachment>;
|
|
15
|
+
declare function upload(action: DatasourceAction, file: File): Promise<FileAttachment>;
|
|
20
16
|
//#endregion
|
|
21
17
|
export { FileAttachment, upload };
|
package/dist/core/file-upload.js
CHANGED
|
@@ -5,10 +5,6 @@ import { softrApiUrl } from "../softr-api.js";
|
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
6
|
|
|
7
7
|
//#region src/core/file-upload.ts
|
|
8
|
-
/**
|
|
9
|
-
* A COMMENTS action uploads a comment attachment.
|
|
10
|
-
* The platform checks the comment settings.
|
|
11
|
-
*/
|
|
12
8
|
async function upload(action, file) {
|
|
13
9
|
const { applicationId } = sessionConfig();
|
|
14
10
|
const baseUrl = softrApiUrl("SOFTR_PLATFORM_API_URL");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DatasourceAction } from "../action.js";
|
|
2
2
|
import { FileAttachment } from "./file-upload.js";
|
|
3
3
|
|
|
4
4
|
//#region src/core/use-file-upload.d.ts
|
|
@@ -16,7 +16,7 @@ type FileItem = {
|
|
|
16
16
|
filename: string;
|
|
17
17
|
error: Error;
|
|
18
18
|
};
|
|
19
|
-
declare function useFileUpload(action: DatasourceAction
|
|
19
|
+
declare function useFileUpload(action: DatasourceAction, options?: {
|
|
20
20
|
initialAttachments?: FileAttachment[];
|
|
21
21
|
}): {
|
|
22
22
|
files: FileItem[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SoftrUserGroupId, SoftrUserGroups, SoftrUserProperties, User } from "./auth/user.js";
|
|
2
|
-
import { ActionPermissions, SoftrDatasources,
|
|
2
|
+
import { ActionPermissions, SoftrDatasources, defineAiAction, defineIntegration, defineMutation, defineQuery, defineWorkflow } from "./action.js";
|
|
3
3
|
import { FileAttachment } from "./core/file-upload.js";
|
|
4
4
|
import { FileItem, useFileUpload } from "./core/use-file-upload.js";
|
|
5
|
-
import {
|
|
5
|
+
import { AiAnswer, AiFile, AiGenerateInit, AiMessage, AiUsage } from "./core/ai.js";
|
|
6
6
|
import { DateOptions, DateParts, DateSeparator, DateValue, FixedDateFormat, FormattedDate, Formatting, FormattingScope, WeekDay, formatDate, formatDateTime, formatNumber, useFormatting } from "./formatting.js";
|
|
7
7
|
import { SoftrContext } from "./auth/context.js";
|
|
8
8
|
import { AuthSettings } from "./auth/platform.js";
|
|
@@ -18,4 +18,4 @@ import { useUserTimezone } from "./timezone.js";
|
|
|
18
18
|
import { PwaInstall, PwaPlatform, SoftrPwaHead, usePwaInstall } from "./pwa.js";
|
|
19
19
|
import { DefaultErrorOverlay } from "./default-error-overlay.js";
|
|
20
20
|
import { Audience } from "./route/audience.js";
|
|
21
|
-
export { type ActionPermissions,
|
|
21
|
+
export { type ActionPermissions, type AiAnswer, type AiFile, type AiGenerateInit, type AiMessage, type AiUsage, Audience, type AuthOptions, type AuthSettings, AuthSettingsProvider, type DateOptions, type DateParts, type DateSeparator, type DateValue, DefaultErrorOverlay, type FieldShape, type FileAttachment, type FileItem, type FixedDateFormat, FormattedDate, type Formatting, FormattingScope, type Page, type PageSettings, type PwaInstall, type PwaPlatform, type SoftrContext, type SoftrDatasources, type SoftrFieldRegistry, SoftrPwaHead, type SoftrUserGroupId, type SoftrUserGroups, type SoftrUserProperties, type User, type WeekDay, assertRouteAccess, checkAccess, defineAiAction, defineIntegration, defineMutation, definePage, defineQuery, defineVisibility, defineWorkflow, fieldShape, formatDate, formatDateTime, formatDuration, formatField, formatNumber, formatValue, getAuthSettings, getSoftrContext, guardRoute, initialSoftrContext, isAccessError, isAlreadyAuthenticatedError, isAuthorized, isForbiddenError, isUnauthenticatedError, pageHead, registerSoftrFields, softrAuthMiddleware, softrMcpMiddleware, toReturnPath, useAuthSettings, useCurrentUser, useFileUpload, useFormatting, useOverrides, usePwaInstall, useUserTimezone };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useFileUpload } from "./core/use-file-upload.js";
|
|
2
|
-
import {
|
|
2
|
+
import { defineAiAction, defineIntegration, defineMutation, defineQuery, defineWorkflow } from "./action.js";
|
|
3
3
|
import { checkAccess, defineVisibility, isAuthorized } from "./route/visibility.js";
|
|
4
4
|
import { assertRouteAccess, guardRoute, isAccessError, isAlreadyAuthenticatedError, isForbiddenError, isUnauthenticatedError } from "./route/route.js";
|
|
5
5
|
import { definePage, pageHead } from "./route/page.js";
|
|
@@ -14,4 +14,4 @@ import { useUserTimezone } from "./timezone.js";
|
|
|
14
14
|
import { DefaultErrorOverlay } from "./default-error-overlay.js";
|
|
15
15
|
import { Audience } from "./route/audience.js";
|
|
16
16
|
|
|
17
|
-
export { Audience, AuthSettingsProvider, DefaultErrorOverlay, FormattedDate, FormattingScope, SoftrPwaHead, assertRouteAccess, checkAccess,
|
|
17
|
+
export { Audience, AuthSettingsProvider, DefaultErrorOverlay, FormattedDate, FormattingScope, SoftrPwaHead, assertRouteAccess, checkAccess, defineAiAction, defineIntegration, defineMutation, definePage, defineQuery, defineVisibility, defineWorkflow, fieldShape, formatDate, formatDateTime, formatDuration, formatField, formatNumber, formatValue, getAuthSettings, getSoftrContext, guardRoute, initialSoftrContext, isAccessError, isAlreadyAuthenticatedError, isAuthorized, isForbiddenError, isUnauthenticatedError, pageHead, registerSoftrFields, softrAuthMiddleware, softrMcpMiddleware, toReturnPath, useAuthSettings, useCurrentUser, useFileUpload, useFormatting, useOverrides, usePwaInstall, useUserTimezone };
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DatasourceAction } from "./action.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as _tanstack_react_start0 from "@tanstack/react-start";
|
|
3
3
|
|
|
4
4
|
//#region src/mcp.d.ts
|
|
5
5
|
|
|
@@ -31,6 +31,6 @@ type SoftrMcpOptions = {
|
|
|
31
31
|
* ],
|
|
32
32
|
* }))
|
|
33
33
|
*/
|
|
34
|
-
declare function softrMcpMiddleware(options?: SoftrMcpOptions):
|
|
34
|
+
declare function softrMcpMiddleware(options?: SoftrMcpOptions): _tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>;
|
|
35
35
|
//#endregion
|
|
36
36
|
export { softrMcpMiddleware };
|
package/dist/package.js
CHANGED
package/dist/server.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { upload } from "./core/file-upload.js";
|
|
2
|
-
import {
|
|
2
|
+
import { AiError, ai } from "./core/ai.js";
|
|
3
3
|
import { auth } from "./auth/server.js";
|
|
4
4
|
import { FieldChoice, RecordOption, RecordOptions } from "./core/options.js";
|
|
5
5
|
import { ds } from "./datasource/datasource.js";
|
|
6
6
|
import { workflow } from "./core/workflow.js";
|
|
7
7
|
import { integration } from "./core/integration.js";
|
|
8
8
|
import "@tanstack/react-start/server-only";
|
|
9
|
-
export { type FieldChoice, type RecordOption, type RecordOptions,
|
|
9
|
+
export { AiError, type FieldChoice, type RecordOption, type RecordOptions, ai, auth, ds, integration, upload, workflow };
|
package/dist/server.js
CHANGED
|
@@ -3,7 +3,7 @@ import { ds } from "./datasource/datasource.js";
|
|
|
3
3
|
import { auth } from "./auth/server.js";
|
|
4
4
|
import { workflow } from "./core/workflow.js";
|
|
5
5
|
import { integration } from "./core/integration.js";
|
|
6
|
-
import {
|
|
6
|
+
import { AiError, ai } from "./core/ai.js";
|
|
7
7
|
import "@tanstack/react-start/server-only";
|
|
8
8
|
|
|
9
|
-
export {
|
|
9
|
+
export { AiError, ai, auth, ds, integration, upload, workflow };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softr/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.83-alpha.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
|
|
@@ -17,8 +17,6 @@
|
|
|
17
17
|
"typecheck": "tsc --noEmit"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"marked": "^18.0.14",
|
|
21
|
-
"xss": "^1.0.15",
|
|
22
20
|
"zod": "^4.4.3"
|
|
23
21
|
},
|
|
24
22
|
"devDependencies": {
|
|
@@ -8,7 +8,7 @@ description: >-
|
|
|
8
8
|
metadata:
|
|
9
9
|
type: core
|
|
10
10
|
library: softr-sdk
|
|
11
|
-
library_version: 0.0.
|
|
11
|
+
library_version: 0.0.82
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# Softr SDK core
|
|
@@ -18,6 +18,7 @@ metadata:
|
|
|
18
18
|
> **CRITICAL**: The SDK is split across four entrypoints and the split is enforced. `ds` and `auth` exist only on `@softr/sdk/server` and only run inside a `createServerFn` handler. Importing them anywhere else fails the build.
|
|
19
19
|
> **CRITICAL**: Every route file must declare its audience with `defineVisibility` and guard itself with that rule in `beforeLoad`. There is no default and nothing is inherited from a sibling.
|
|
20
20
|
> **CRITICAL**: The app is already wired. `src/start.ts`, `src/router.tsx` and `src/routes/__root.tsx` register `softrAuthMiddleware` and resolve the session. Do not add a second registration of it. `softrMcpMiddleware` is the one thing an app adds to `src/start.ts` itself — load the `softr-sdk/mcp` sub-skill before doing so.
|
|
21
|
+
> **CRITICAL**: `ai.generate` and `ai.stream` live on `@softr/sdk/server` and only run inside a `createServerFn` handler. Use `defineAiAction` from `@softr/sdk` to declare the action with the model it runs on, an id copied from the `ai_list_models` tool. Softr runs the model on its own keys; never ask the user for an API key for the app's own AI feature. Load the `softr-sdk/ai` sub-skill for the full pattern.
|
|
21
22
|
> **CRITICAL**: `workflow.trigger` lives on `@softr/sdk/server` and only runs inside a `createServerFn` handler. Use `defineWorkflow` from `@softr/sdk` to declare the action, then pass it to `workflow.trigger`. Load the `softr-sdk/workflows` sub-skill for the full pattern.
|
|
22
23
|
|
|
23
24
|
Each sub-skill stands alone for its task and repeats the boundary above, so most work needs **one** sub-skill and not this file. Load this one when you are unsure which sub-skill applies, or when the wiring below is what you are touching. Add a second sub-skill only when the work genuinely crosses that boundary: a page that lists records behind a group restriction needs `record-queries` plus `routes-and-visibility`.
|
|
@@ -26,9 +27,9 @@ Each sub-skill stands alone for its task and repeats the boundary above, so most
|
|
|
26
27
|
|
|
27
28
|
| Import | Runs | Holds |
|
|
28
29
|
| --- | --- | --- |
|
|
29
|
-
| `@softr/sdk` | Both | `defineQuery`, `defineMutation`, `
|
|
30
|
-
| `@softr/sdk/server` | Server only | `ds`, `auth`, `workflow`, `integration`, `
|
|
31
|
-
| `@softr/sdk/client` | Browser only | `useFileUpload
|
|
30
|
+
| `@softr/sdk` | Both | `defineQuery`, `defineMutation`, `defineAiAction`, `defineVisibility`, `guardRoute`, `assertRouteAccess`, `isAuthorized`, `checkAccess`, `Audience`, `useCurrentUser`, `useUserTimezone`, `FormattedDate`, `FormattingScope`, `useFormatting`, `formatDate`, `formatDateTime`, `formatNumber`, `formatValue`, `formatField`, `fieldShape`, `registerSoftrFields`, `useOverrides`, `SoftrPwaHead`, `usePwaInstall`, `getSoftrContext`, `initialSoftrContext`, `softrAuthMiddleware`, the error predicates, and every type |
|
|
31
|
+
| `@softr/sdk/server` | Server only | `ds`, `auth`, `workflow`, `integration`, `ai` |
|
|
32
|
+
| `@softr/sdk/client` | Browser only | `useFileUpload` |
|
|
32
33
|
| `@softr/sdk/vite` | Build | `softr()`, already in `vite.config.ts` |
|
|
33
34
|
|
|
34
35
|
## Sub-Skills
|
|
@@ -43,11 +44,11 @@ Each sub-skill stands alone for its task and repeats the boundary above, so most
|
|
|
43
44
|
| Create, update or delete a record | [record-mutations/SKILL.md](./record-mutations/SKILL.md) |
|
|
44
45
|
| Trigger a Softr workflow | [workflows/SKILL.md](./workflows/SKILL.md) |
|
|
45
46
|
| Sign a visitor in, out, or up | [auth/SKILL.md](./auth/SKILL.md) |
|
|
46
|
-
|
|
|
47
|
+
| Ask an AI model: a summary, an extraction from a document, a classification, a draft, a chat | [ai/SKILL.md](./ai/SKILL.md) |
|
|
48
|
+
| Call a connected third-party API (Slack, Stripe, Gmail, …), or an AI model on the user's own provider account | [integrations/SKILL.md](./integrations/SKILL.md) |
|
|
47
49
|
| Open the app to AI assistants over MCP | [mcp/SKILL.md](./mcp/SKILL.md) |
|
|
48
50
|
| Let visitors install the app on their home screen | [pwa/SKILL.md](./pwa/SKILL.md) |
|
|
49
51
|
| Show a date, a time or a number | [formatting/SKILL.md](./formatting/SKILL.md) |
|
|
50
|
-
| Add comments to a record | [comments/SKILL.md](./comments/SKILL.md) |
|
|
51
52
|
|
|
52
53
|
## Quick Decision Tree
|
|
53
54
|
|
|
@@ -76,9 +77,15 @@ Triggering a Softr workflow from a button or form?
|
|
|
76
77
|
Wiring a login, signup, or sign-out?
|
|
77
78
|
load softr-sdk/auth
|
|
78
79
|
|
|
80
|
+
Asking an AI model for anything: a summary, fields out of a document, a classification, a draft, a chat?
|
|
81
|
+
load softr-sdk/ai — Softr runs the model on its own keys, nothing to connect; pick the model from ai_list_models
|
|
82
|
+
|
|
79
83
|
Calling a connected third-party API (Slack, Stripe, Gmail, Google Calendar, …)?
|
|
80
84
|
load softr-sdk/integrations
|
|
81
85
|
|
|
86
|
+
Running a model on the user's OWN provider account, because they chose that for the feature?
|
|
87
|
+
load softr-sdk/integrations: its "Calling an AI model" section
|
|
88
|
+
|
|
82
89
|
Opening the app to an AI assistant over MCP?
|
|
83
90
|
load softr-sdk/mcp
|
|
84
91
|
|
|
@@ -88,9 +95,6 @@ Adding an install button, or making the app installable?
|
|
|
88
95
|
Showing a date, a time or a number on a page?
|
|
89
96
|
load softr-sdk/formatting
|
|
90
97
|
|
|
91
|
-
Letting visitors comment on a record?
|
|
92
|
-
load softr-sdk/comments
|
|
93
|
-
|
|
94
98
|
Writing a server function, loader, or middleware in general?
|
|
95
99
|
not a Softr concern. Use the TanStack Start skills.
|
|
96
100
|
```
|