@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 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 react0 from "react";
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): react0.JSX.Element;
11
+ }: Props): react6.JSX.Element;
12
12
  //#endregion
13
13
  export { DefaultErrorOverlay };
@@ -1,4 +1,4 @@
1
- import * as react3 from "react";
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
- }): react3.FunctionComponentElement<react3.ProviderProps<Scope>>;
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
- }): react3.FunctionComponentElement<react3.FragmentProps>;
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
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.0.78-alpha.0";
2
+ var version = "0.0.78-alpha.2";
3
3
 
4
4
  //#endregion
5
5
  export { version };
package/dist/pwa.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react1 from "react";
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(): react1.FunctionComponentElement<react1.FragmentProps>;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softr/sdk",
3
- "version": "0.0.78-alpha.0",
3
+ "version": "0.0.78-alpha.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
@@ -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.0
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: