@softr/sdk 0.0.78-alpha.0 → 0.0.78-alpha.2
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/core/ai.d.ts +15 -1
- package/dist/core/ai.js +6 -3
- package/dist/default-error-overlay.d.ts +2 -2
- package/dist/formatting.d.ts +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/package.js +1 -1
- package/dist/pwa.d.ts +2 -2
- package/package.json +1 -1
- package/skills/softr-sdk/ai/SKILL.md +24 -1
package/dist/core/ai.d.ts
CHANGED
|
@@ -8,9 +8,16 @@ interface AiFile {
|
|
|
8
8
|
/** The file's type when the URL does not say, such as `application/pdf`. */
|
|
9
9
|
mimeType?: string;
|
|
10
10
|
}
|
|
11
|
+
/** One earlier turn of a conversation. */
|
|
12
|
+
interface AiMessage {
|
|
13
|
+
role: 'user' | 'assistant';
|
|
14
|
+
content: string;
|
|
15
|
+
}
|
|
11
16
|
interface AiGenerateInit {
|
|
12
17
|
/** What the model is and the rules it answers under. */
|
|
13
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>;
|
|
14
21
|
/** What it is asked, with the facts it is given. */
|
|
15
22
|
prompt: string;
|
|
16
23
|
/**
|
|
@@ -22,6 +29,13 @@ interface AiGenerateInit {
|
|
|
22
29
|
files?: ReadonlyArray<AiFile>;
|
|
23
30
|
/** A cap on the answer's length, in tokens; Softr caps it further. */
|
|
24
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;
|
|
25
39
|
signal?: AbortSignal;
|
|
26
40
|
}
|
|
27
41
|
interface AiUsage {
|
|
@@ -59,4 +73,4 @@ declare const ai: {
|
|
|
59
73
|
stream: typeof aiStream;
|
|
60
74
|
};
|
|
61
75
|
//#endregion
|
|
62
|
-
export { AiAnswer, AiError, AiFile, AiGenerateInit, AiUsage, ai };
|
|
76
|
+
export { AiAnswer, AiError, AiFile, AiGenerateInit, AiMessage, AiUsage, ai };
|
package/dist/core/ai.js
CHANGED
|
@@ -18,10 +18,13 @@ var AiError = class extends Error {
|
|
|
18
18
|
function body(init) {
|
|
19
19
|
return JSON.stringify({
|
|
20
20
|
system: init.system,
|
|
21
|
+
messages: init.messages,
|
|
21
22
|
prompt: init.prompt,
|
|
22
23
|
schema: init.schema,
|
|
23
24
|
files: init.files,
|
|
24
|
-
maxOutputTokens: init.maxOutputTokens
|
|
25
|
+
maxOutputTokens: init.maxOutputTokens,
|
|
26
|
+
reasoning: init.reasoning,
|
|
27
|
+
temperature: init.temperature
|
|
25
28
|
});
|
|
26
29
|
}
|
|
27
30
|
async function post(action, path, init) {
|
|
@@ -41,7 +44,7 @@ async function post(action, path, init) {
|
|
|
41
44
|
}
|
|
42
45
|
/** Runs the action once and answers when the model is done. */
|
|
43
46
|
async function aiGenerate(action, init) {
|
|
44
|
-
return await (await post(action, "ai/generate", init)).json();
|
|
47
|
+
return await (await post(action, "softr-ai/generate", init)).json();
|
|
45
48
|
}
|
|
46
49
|
/**
|
|
47
50
|
* Runs the action and answers while the model writes. The returned `Response` body is a stream of
|
|
@@ -50,7 +53,7 @@ async function aiGenerate(action, init) {
|
|
|
50
53
|
* place. Hand it to the browser as a `Response` with `Content-Type: text/event-stream`.
|
|
51
54
|
*/
|
|
52
55
|
async function aiStream(action, init) {
|
|
53
|
-
return post(action, "ai/generate/stream", init);
|
|
56
|
+
return post(action, "softr-ai/generate/stream", init);
|
|
54
57
|
}
|
|
55
58
|
const ai = {
|
|
56
59
|
generate: aiGenerate,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react6 from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/default-error-overlay.d.ts
|
|
4
4
|
type Props = {
|
|
@@ -8,6 +8,6 @@ type Props = {
|
|
|
8
8
|
declare function DefaultErrorOverlay({
|
|
9
9
|
error,
|
|
10
10
|
reset
|
|
11
|
-
}: Props):
|
|
11
|
+
}: Props): react6.JSX.Element;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { DefaultErrorOverlay };
|
package/dist/formatting.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react0 from "react";
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
@@ -94,7 +94,7 @@ declare function FormattingScope({
|
|
|
94
94
|
/** A BCP 47 locale, such as `de-DE`. It drops the app's fixed date format inside the scope. */
|
|
95
95
|
locale?: string;
|
|
96
96
|
children?: ReactNode;
|
|
97
|
-
}):
|
|
97
|
+
}): react0.FunctionComponentElement<react0.ProviderProps<Scope>>;
|
|
98
98
|
/**
|
|
99
99
|
* A date in the app's format, safe to render on the server. A timestamp whose
|
|
100
100
|
* zone is not known yet renders `fallback` until the browser supplies it, so
|
|
@@ -115,6 +115,6 @@ declare function FormattedDate({
|
|
|
115
115
|
time?: boolean;
|
|
116
116
|
/** What renders while the visitor's zone is unknown. */
|
|
117
117
|
fallback?: ReactNode;
|
|
118
|
-
}):
|
|
118
|
+
}): react0.FunctionComponentElement<react0.FragmentProps>;
|
|
119
119
|
//#endregion
|
|
120
120
|
export { DateOptions, DateParts, DateSeparator, DateValue, FixedDateFormat, FormattedDate, Formatting, FormattingScope, WeekDay, formatDate, formatDateTime, formatNumber, useFormatting };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { ActionPermissions, SoftrDatasources, defineAiAction, defineComments, de
|
|
|
3
3
|
import { FileAttachment } from "./core/file-upload.js";
|
|
4
4
|
import { FileItem, useFileUpload } from "./core/use-file-upload.js";
|
|
5
5
|
import { CommentAttachmentInput, CommentMention, CommentThread, CommentView } from "./comments/comments.js";
|
|
6
|
-
import { AiAnswer, AiFile, AiGenerateInit, AiUsage } from "./core/ai.js";
|
|
6
|
+
import { AiAnswer, AiFile, AiGenerateInit, AiMessage, AiUsage } from "./core/ai.js";
|
|
7
7
|
import { DateOptions, DateParts, DateSeparator, DateValue, FixedDateFormat, FormattedDate, Formatting, FormattingScope, WeekDay, formatDate, formatDateTime, formatNumber, useFormatting } from "./formatting.js";
|
|
8
8
|
import { SoftrContext } from "./auth/context.js";
|
|
9
9
|
import { AuthSettings } from "./auth/platform.js";
|
|
@@ -19,4 +19,4 @@ import { useUserTimezone } from "./timezone.js";
|
|
|
19
19
|
import { PwaInstall, PwaPlatform, SoftrPwaHead, usePwaInstall } from "./pwa.js";
|
|
20
20
|
import { DefaultErrorOverlay } from "./default-error-overlay.js";
|
|
21
21
|
import { Audience } from "./route/audience.js";
|
|
22
|
-
export { type ActionPermissions, type AiAnswer, type AiFile, type AiGenerateInit, type AiUsage, Audience, type AuthOptions, type AuthSettings, AuthSettingsProvider, type CommentAttachmentInput, type CommentMention, type CommentThread, type CommentView, 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 User, type WeekDay, assertRouteAccess, checkAccess, defineAiAction, defineComments, 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 };
|
|
22
|
+
export { type ActionPermissions, type AiAnswer, type AiFile, type AiGenerateInit, type AiMessage, type AiUsage, Audience, type AuthOptions, type AuthSettings, AuthSettingsProvider, type CommentAttachmentInput, type CommentMention, type CommentThread, type CommentView, 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 User, type WeekDay, assertRouteAccess, checkAccess, defineAiAction, defineComments, 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/package.js
CHANGED
package/dist/pwa.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react4 from "react";
|
|
2
2
|
import "@tanstack/react-start";
|
|
3
3
|
|
|
4
4
|
//#region src/pwa.d.ts
|
|
@@ -23,7 +23,7 @@ import "@tanstack/react-start";
|
|
|
23
23
|
* )
|
|
24
24
|
* }
|
|
25
25
|
*/
|
|
26
|
-
declare function SoftrPwaHead():
|
|
26
|
+
declare function SoftrPwaHead(): react4.FunctionComponentElement<react4.FragmentProps>;
|
|
27
27
|
type PwaPlatform = "ios" | "android" | "desktop";
|
|
28
28
|
type PwaInstall = {
|
|
29
29
|
available: false;
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@ description: >-
|
|
|
12
12
|
metadata:
|
|
13
13
|
type: sub-skill
|
|
14
14
|
library: softr-sdk
|
|
15
|
-
library_version: 0.0.78-alpha.
|
|
15
|
+
library_version: 0.0.78-alpha.2
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
**Boundary.** `ai` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineAiAction` and every type come from `@softr/sdk` and can be imported anywhere.
|
|
@@ -55,6 +55,9 @@ Declare one action per feature — the summary and the extraction are two action
|
|
|
55
55
|
- `schema` — a JSON schema the answer has to match. With it the model is asked for JSON only, and the answer comes back parsed in `json` as well as written in `text`.
|
|
56
56
|
- `files` — documents and images the model reads, each as `{ url, mimeType? }`: an `https` URL Softr may fetch, one of the app's own uploads as a rule.
|
|
57
57
|
- `maxOutputTokens` — a cap on the answer's length. Softr caps it further.
|
|
58
|
+
- `messages` — the earlier turns of a conversation, oldest first, each `{ role: 'user' | 'assistant', content }`. The prompt is the newest turn. Leave out for a one-shot call.
|
|
59
|
+
- `reasoning` — `'low'`, `'medium'` or `'high'`: how hard a reasoning model thinks before it answers. The catalog says which models reason; the others ignore it. Leave out for the provider's default.
|
|
60
|
+
- `temperature` — 0 to 1: how varied the answer is. `0` for an extraction or a classification, around `0.7` for a draft. A low default when left out.
|
|
58
61
|
|
|
59
62
|
The answer is `{ text, json, usage, model }`: `text` as the model wrote it, `json` parsed when a schema was given and the model kept to it, `null` otherwise.
|
|
60
63
|
|
|
@@ -102,6 +105,26 @@ const extractInvoice = createServerFn({ method: 'POST' })
|
|
|
102
105
|
|
|
103
106
|
The file's URL comes from the app's own upload: load the Softr SDK `file-uploads` guidance for that half. `readInvoice` names a model whose `bestFor` reads PDF documents.
|
|
104
107
|
|
|
108
|
+
## A conversation
|
|
109
|
+
|
|
110
|
+
A chat sends its earlier turns in `messages` and the new one as `prompt`. The app keeps the turns; the model holds nothing between calls.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
const reply = createServerFn({ method: 'POST' })
|
|
114
|
+
.validator(z.object({ turns: z.array(z.object({ role: z.enum(['user', 'assistant']), content: z.string() })), prompt: z.string() }))
|
|
115
|
+
.handler(async ({ data }) => {
|
|
116
|
+
const answer = await ai.generate(supportChat, {
|
|
117
|
+
system: 'You answer questions about the order the user is looking at.',
|
|
118
|
+
messages: data.turns,
|
|
119
|
+
prompt: data.prompt,
|
|
120
|
+
temperature: 0.5,
|
|
121
|
+
})
|
|
122
|
+
return answer.text
|
|
123
|
+
})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
A chat the user watches being written streams instead, with the same `messages`: see the next section.
|
|
127
|
+
|
|
105
128
|
## Streaming: an answer the user watches being written
|
|
106
129
|
|
|
107
130
|
A chat, an assistant, a long draft shown as it is typed — never buffer these: the user would watch a blank panel until the last token. `ai.stream(action, init)` takes the same `init` and answers with a `Response` whose body is a stream of Server-Sent Events. Hand it to the browser from the server function, unchanged:
|