@serenity-star/sdk 2.8.0 → 2.10.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serenity-star/sdk",
3
- "version": "2.8.0",
3
+ "version": "2.10.0",
4
4
  "description": "The Serenity Star JavaScript SDK provides a convenient way to interact with the Serenity Star API, enabling you to build custom applications.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/readme.md CHANGED
@@ -25,6 +25,8 @@ The Serenity Star JS/TS SDK provides a comprehensive interface for interacting w
25
25
  - [Submit feedback](#submit-feedback)
26
26
  - [Remove feedback](#remove-feedback)
27
27
  - [Connector Status](#connector-status)
28
+ - [Tool approvals](#tool-approvals)
29
+ - [User choices](#user-choices)
28
30
  - [Activities](#activities)
29
31
  - [Execute an activity](#execute-an-activity)
30
32
  - [Stream responses with SSE](#stream-responses-with-sse)
@@ -42,6 +44,7 @@ The Serenity Star JS/TS SDK provides a comprehensive interface for interacting w
42
44
  - [Task events](#task-events)
43
45
  - [Citations](#citations)
44
46
  - [Citations on stored messages](#citations-on-stored-messages)
47
+ - [Downloading a cited knowledge file](#downloading-a-cited-knowledge-file)
45
48
  - [Upload Files (Volatile Knowledge)](#upload-files-volatile-knowledge)
46
49
  - [Audio Input](#audio-input)
47
50
  - [Send Audio Messages (Assistants/Copilots)](#send-audio-messages-assistantscopilots)
@@ -533,6 +536,75 @@ Notes:
533
536
  finishes, so an approval raised on the very first turn is resolvable.
534
537
  - A resumed turn can itself raise another approval; keep handling `pending_actions` until it is empty.
535
538
 
539
+ ## User choices
540
+
541
+ When the agent needs input before it can continue, it stops and asks. The result carries a
542
+ `user_choice` pending action holding one or more questions, each with the options the agent
543
+ proposes.
544
+
545
+ Detect it on the result (or on the `stop` payload when streaming) and answer with
546
+ `streamUserChoices` / `sendUserChoices`. The resume turn carries **no user message** — the answers
547
+ are the whole turn — and continues the same conversation, so the answer arrives as the rest of the
548
+ same assistant response.
549
+
550
+ ```tsx
551
+ import SerenityClient from '@serenity-star/sdk';
552
+
553
+ const client = new SerenityClient({
554
+ apiKey: '<SERENITY_API_KEY>',
555
+ });
556
+
557
+ const conversation = await client.agents.assistants.createConversation("chef-assistant");
558
+
559
+ const response = await conversation.streamMessage("Plan dinner for me tonight.");
560
+
561
+ const choice = response.pending_actions?.find((action) => action.type === "user_choice");
562
+
563
+ if (choice) {
564
+ for (const question of choice.questions) {
565
+ console.log(question.header); // "Cuisine" — short label, frequently absent
566
+ console.log(question.text); // "What kind of food are you in the mood for?"
567
+ console.log(question.is_multiselect) // false — pick one, or many when true
568
+ console.log(question.options); // [{ id, title, description? }, ...]
569
+ }
570
+
571
+ // Ask the user, then echo each question id back with the option ids they picked.
572
+ const continuation = await conversation.streamUserChoices(
573
+ choice.questions.map((question) => ({
574
+ questionId: question.id,
575
+ selectedOptionIds: [question.options![0].id],
576
+ })),
577
+ );
578
+
579
+ console.log(continuation.content); // the rest of the answer
580
+ }
581
+ ```
582
+
583
+ When none of the options fit, send the user's own words in `other` instead — with or without
584
+ selected options:
585
+
586
+ ```tsx
587
+ await conversation.sendUserChoices([
588
+ { questionId: question.id, selectedOptionIds: [], other: "Something vegetarian" },
589
+ ]);
590
+ ```
591
+
592
+ Notes:
593
+
594
+ - `questionId` must match a question's `id`, and every id in `selectedOptionIds` must match one of
595
+ that question's `options`. `header`, `text` and `description` are informational.
596
+ - Answer members are camelCase (`questionId`, `selectedOptionIds`, `other?`). `other` is optional,
597
+ trimmed, and omitted from the request when empty.
598
+ - Answer every question in the set. `selectedOptionIds` may be empty only when `other` carries the
599
+ answer instead.
600
+ - Unlike approvals, nothing is held server-side: the answers are folded into the text of the next
601
+ user message. An unanswered set never expires, so it can be answered on a later turn, and a plain
602
+ `sendMessage` / `streamMessage` also works if the user would rather just reply in their own words.
603
+ - User choices can only be answered on an existing conversation — both methods throw when
604
+ `conversation.conversationId` is not set yet. It is populated as soon as the first execution
605
+ finishes, so a question raised on the very first turn is answerable.
606
+ - A resumed turn can itself raise another question; keep handling `pending_actions` until it is empty.
607
+
536
608
  ---
537
609
 
538
610
  # Activities
@@ -1056,6 +1128,8 @@ type CitationSource =
1056
1128
  section_id?: string;
1057
1129
  file_name?: string;
1058
1130
  page_range?: string;
1131
+ is_downloadable?: boolean; // Whether the cited file can be downloaded by authorized users
1132
+ download_url?: string; // Absolute download endpoint, or absent when not downloadable
1059
1133
  }
1060
1134
  | {
1061
1135
  type: "knowledge_website";
@@ -1104,6 +1178,40 @@ for (const message of conversation.messages) {
1104
1178
  }
1105
1179
  ```
1106
1180
 
1181
+ ### Downloading a cited knowledge file
1182
+
1183
+ When an agent's knowledge file is configured as available for download, its citations carry a
1184
+ `download_url` alongside `is_downloadable`. The URL points at the platform's download endpoint but
1185
+ **carries no credentials** — a plain `<a href>` will not work. Use `downloadKnowledgeFile` so the
1186
+ SDK attaches the client's API key or bearer token:
1187
+
1188
+ ```tsx
1189
+ for (const citation of response.citations ?? []) {
1190
+ const source = citation.source;
1191
+ if (source?.type !== "knowledge_file" || !source.download_url) continue;
1192
+
1193
+ const blob = await conversation.downloadKnowledgeFile(source.download_url);
1194
+
1195
+ // In the browser, hand the blob to the user
1196
+ const objectUrl = URL.createObjectURL(blob);
1197
+ const link = document.createElement("a");
1198
+ link.href = objectUrl;
1199
+ link.download = source.file_name ?? "download";
1200
+ link.click();
1201
+ URL.revokeObjectURL(objectUrl);
1202
+ }
1203
+ ```
1204
+
1205
+ Notes:
1206
+
1207
+ - Branch on `download_url` alone. The server derives `is_downloadable` from the URL, so the two
1208
+ can never disagree, and a missing URL already covers non-downloadable files and draft versions.
1209
+ - The URL's origin must match the client's `baseUrl`. A mismatch throws before any request is
1210
+ made, so the credential never reaches an origin you did not configure.
1211
+ - Private, deleted, or missing files all answer `404` — deliberately indistinguishable.
1212
+ - Citations loaded from history via [Get conversation by id](#get-conversation-by-id) do **not**
1213
+ currently include `download_url`.
1214
+
1107
1215
  ## Upload Files (Volatile Knowledge)
1108
1216
 
1109
1217
  Upload files to be used as context in your agent executions. This feature is available for all agent types: **Assistants**, **Copilots**, **Activities**, **Proxies**, and **Chat Completions**. Files are agent-scoped automatically and are included in the next message or execution.