@serenity-star/sdk 2.7.0 → 2.9.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.7.0",
3
+ "version": "2.9.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)
@@ -39,6 +41,7 @@ The Serenity Star JS/TS SDK provides a comprehensive interface for interacting w
39
41
  - [Download Attached Files](#download-attached-files)
40
42
  - [Stop Streaming Response](#stop-streaming-response)
41
43
  - [Reasoning (Chain-of-Thought)](#reasoning-chain-of-thought)
44
+ - [Task events](#task-events)
42
45
  - [Citations](#citations)
43
46
  - [Citations on stored messages](#citations-on-stored-messages)
44
47
  - [Upload Files (Volatile Knowledge)](#upload-files-volatile-knowledge)
@@ -532,6 +535,75 @@ Notes:
532
535
  finishes, so an approval raised on the very first turn is resolvable.
533
536
  - A resumed turn can itself raise another approval; keep handling `pending_actions` until it is empty.
534
537
 
538
+ ## User choices
539
+
540
+ When the agent needs input before it can continue, it stops and asks. The result carries a
541
+ `user_choice` pending action holding one or more questions, each with the options the agent
542
+ proposes.
543
+
544
+ Detect it on the result (or on the `stop` payload when streaming) and answer with
545
+ `streamUserChoices` / `sendUserChoices`. The resume turn carries **no user message** — the answers
546
+ are the whole turn — and continues the same conversation, so the answer arrives as the rest of the
547
+ same assistant response.
548
+
549
+ ```tsx
550
+ import SerenityClient from '@serenity-star/sdk';
551
+
552
+ const client = new SerenityClient({
553
+ apiKey: '<SERENITY_API_KEY>',
554
+ });
555
+
556
+ const conversation = await client.agents.assistants.createConversation("chef-assistant");
557
+
558
+ const response = await conversation.streamMessage("Plan dinner for me tonight.");
559
+
560
+ const choice = response.pending_actions?.find((action) => action.type === "user_choice");
561
+
562
+ if (choice) {
563
+ for (const question of choice.questions) {
564
+ console.log(question.header); // "Cuisine" — short label, frequently absent
565
+ console.log(question.text); // "What kind of food are you in the mood for?"
566
+ console.log(question.is_multiselect) // false — pick one, or many when true
567
+ console.log(question.options); // [{ id, title, description? }, ...]
568
+ }
569
+
570
+ // Ask the user, then echo each question id back with the option ids they picked.
571
+ const continuation = await conversation.streamUserChoices(
572
+ choice.questions.map((question) => ({
573
+ questionId: question.id,
574
+ selectedOptionIds: [question.options![0].id],
575
+ })),
576
+ );
577
+
578
+ console.log(continuation.content); // the rest of the answer
579
+ }
580
+ ```
581
+
582
+ When none of the options fit, send the user's own words in `other` instead — with or without
583
+ selected options:
584
+
585
+ ```tsx
586
+ await conversation.sendUserChoices([
587
+ { questionId: question.id, selectedOptionIds: [], other: "Something vegetarian" },
588
+ ]);
589
+ ```
590
+
591
+ Notes:
592
+
593
+ - `questionId` must match a question's `id`, and every id in `selectedOptionIds` must match one of
594
+ that question's `options`. `header`, `text` and `description` are informational.
595
+ - Answer members are camelCase (`questionId`, `selectedOptionIds`, `other?`). `other` is optional,
596
+ trimmed, and omitted from the request when empty.
597
+ - Answer every question in the set. `selectedOptionIds` may be empty only when `other` carries the
598
+ answer instead.
599
+ - Unlike approvals, nothing is held server-side: the answers are folded into the text of the next
600
+ user message. An unanswered set never expires, so it can be answered on a later turn, and a plain
601
+ `sendMessage` / `streamMessage` also works if the user would rather just reply in their own words.
602
+ - User choices can only be answered on an existing conversation — both methods throw when
603
+ `conversation.conversationId` is not set yet. It is populated as soon as the first execution
604
+ finishes, so a question raised on the very first turn is answerable.
605
+ - A resumed turn can itself raise another question; keep handling `pending_actions` until it is empty.
606
+
535
607
  ---
536
608
 
537
609
  # Activities
@@ -916,6 +988,83 @@ conversation
916
988
  await conversation.streamMessage("Plan a three-course vegetarian dinner");
917
989
  ```
918
990
 
991
+ ## Task events
992
+
993
+ While an agent streams, it reports the internal work it performs through the `task_start` / `task_stop` event pair. A **task** is any discrete step the agent runs on its way to an answer — a skill execution, a tool call, and whatever step types the platform adds later. The SDK forwards every task frame it receives without filtering, so new task types reach your handlers as soon as the platform starts emitting them.
994
+
995
+ Use them to reflect the agent's progress in your UI while it works, or to time, trace and log what the agent actually did.
996
+
997
+ These events only exist on **streamed** executions (`streamMessage` / `stream`). A non-streamed call returns the final result only.
998
+
999
+ Each task carries a `task_key` identifying what ran and a `metadata` object describing it. Both are task-type specific: match on `task_key` for the types you care about and ignore the rest, rather than assuming a single shape.
1000
+
1001
+ ```tsx
1002
+ import SerenityClient from '@serenity-star/sdk';
1003
+
1004
+ const client = new SerenityClient({
1005
+ apiKey: '<SERENITY_API_KEY>',
1006
+ });
1007
+
1008
+ const conversation = await client.agents.assistants.createConversation("sales-assistant");
1009
+
1010
+ conversation
1011
+ .on("task_start", (task) => console.log("started", task.task, task.task_key))
1012
+ .on("task_stop", (task) =>
1013
+ console.log("finished", task.task_key, task.duration, task.success)
1014
+ )
1015
+ .on("content", (chunk) => process.stdout.write(chunk));
1016
+
1017
+ await conversation.streamMessage("What do we have in stock for vintage guitars?");
1018
+ ```
1019
+
1020
+ ### `task_start` payload
1021
+
1022
+ | Field | Type | Description |
1023
+ | --- | --- | --- |
1024
+ | `type` | `string` | The event name, `task_start`. |
1025
+ | `task` | `string` | Human-readable description of the task, safe to show in a UI. |
1026
+ | `task_key` | `string` | Identifier of what ran. Its format depends on the task type. |
1027
+ | `metadata` | `object` | Extra details about the task. Contents depend on the task type. |
1028
+ | `start_time_utc` | `string` | When the task started (UTC). |
1029
+ | `input` | `object` | The arguments the task was invoked with. Shape depends on the task. |
1030
+
1031
+ ### `task_stop` payload
1032
+
1033
+ Same envelope as `task_start`, plus:
1034
+
1035
+ | Field | Type | Description |
1036
+ | --- | --- | --- |
1037
+ | `end_time_utc` | `string` | When the task finished (UTC). |
1038
+ | `duration` | `string` | Elapsed time as a timespan string, e.g. `00:00:00.0002104`. |
1039
+ | `success` | `boolean` | Whether the task completed successfully. |
1040
+ | `output` | `any` | The task's result. Shape depends on the task. |
1041
+
1042
+ Unknown fields the server may add in the future are preserved on the payload — both types carry an index signature.
1043
+
1044
+ ### Recognising a task type
1045
+
1046
+ Skill executions are one task type. Their `task_key` follows the `skills_<SkillCode>_execute` convention, and the skill is described under `metadata.skill`:
1047
+
1048
+ ```json
1049
+ {
1050
+ "type": "task_start",
1051
+ "task": "Executing Skill: GetProductInfo",
1052
+ "task_key": "skills_GetProductInfo_execute",
1053
+ "metadata": { "skill": { "type": "Prompt", "code": "GetProductInfo" } },
1054
+ "start_time_utc": "2026-08-24T10:22:54.1822224Z",
1055
+ "input": { "categoryName": "Music instruments from the 1960s" }
1056
+ }
1057
+ ```
1058
+
1059
+ ```tsx
1060
+ conversation.on("task_start", (task) => {
1061
+ const skillCode = task.metadata?.skill?.code;
1062
+ if (skillCode) {
1063
+ showSpinner(`Running ${skillCode}…`);
1064
+ }
1065
+ });
1066
+ ```
1067
+
919
1068
  ## Citations
920
1069
 
921
1070
  When an agent grounds its response in knowledge sources (knowledge files or websites), it returns **citations** that map spans of the generated message back to the source passages they came from. Citations are available across all agent types that support knowledge grounding.