@pylonsync/react 0.4.27 → 0.4.28

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/index.d.ts CHANGED
@@ -144,6 +144,35 @@ export declare function getReactStorage(): PylonStorage;
144
144
  export declare function callFn<T = unknown>(name: string, args?: Record<string, unknown>, options?: {
145
145
  token?: string;
146
146
  }): Promise<T>;
147
+ /**
148
+ * Ask an `agent()` run to stop.
149
+ *
150
+ * Cancel is durable, not a stream teardown: it lands on the run row,
151
+ * so it reaches a loop running on a different machine, and abandoning
152
+ * the SSE connection is NOT a cancel (a detached cloud run is supposed
153
+ * to survive the window closing).
154
+ *
155
+ * The call returns as soon as the request is recorded. A live
156
+ * generation stops at its next turn boundary — between tool calls
157
+ * within seconds, or after the current model response finishes.
158
+ * `run.cancelRequested` is true in that window; drive the stop
159
+ * button's pending state from it and treat `run.status === "cancelled"`
160
+ * as the confirmation.
161
+ *
162
+ * ```ts
163
+ * const { run } = useAgentRun(runId);
164
+ * <button
165
+ * disabled={run?.cancelRequested === true}
166
+ * onClick={() => cancelAgentRun("helper", runId)}
167
+ * >Stop</button>
168
+ * ```
169
+ */
170
+ export declare function cancelAgentRun(agentName: string, runId: string, options?: {
171
+ token?: string;
172
+ }): Promise<{
173
+ runId: string;
174
+ cancelled: boolean;
175
+ }>;
147
176
  /** Options for {@link streamFn}. */
148
177
  export interface StreamFnOptions {
149
178
  token?: string;
@@ -9,23 +9,35 @@
9
9
  * ```tsx
10
10
  * const { run, messages } = useAgentRun(runId);
11
11
  * // messages[i]: { role: "user" | "assistant", content: string | LlmContentBlock[] , seq, ... }
12
- * // run.status: "idle" | "running" | "completed" | "failed"
12
+ * // run.status: "idle" | "running" | "completed" | "failed" | "cancelled"
13
13
  * // run.streamId: attach to live tokens with resumeStream(run.streamId)
14
+ * // run.pendingInput: messages sent mid-generation, not yet drained
14
15
  * ```
15
16
  *
16
17
  * Start or continue a run with `streamFn("<agentName>", { input, runId? })`
17
18
  * — tokens stream on that connection; the persisted transcript arrives
18
- * here.
19
+ * here. Sending while the run is generating queues the message rather
20
+ * than failing, so the composer stays live. Stop a run with
21
+ * `cancelAgentRun(agentName, runId)`.
19
22
  */
20
23
  export interface AgentRunRow {
21
24
  id: string;
22
25
  agent: string;
23
- status: "idle" | "running" | "completed" | "failed" | string;
26
+ status: "idle" | "running" | "completed" | "failed" | "cancelled" | string;
24
27
  userId?: string | null;
25
28
  title?: string | null;
26
29
  /** Resumable-stream id of the current/last generation. */
27
30
  streamId?: string | null;
28
31
  error?: string | null;
32
+ /** Messages sent while the agent was generating, not yet folded into
33
+ * the transcript. Render these as queued below the last message. */
34
+ pendingInput?: string[] | null;
35
+ /** A cancel has been asked for and the loop has not reached the
36
+ * boundary where it stops. Drive the stop button's pending state
37
+ * from this. */
38
+ cancelRequested?: boolean | null;
39
+ /** Cumulative model↔tool round-trips across every turn of this run. */
40
+ steps?: number | null;
29
41
  createdAt: string;
30
42
  updatedAt: string;
31
43
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.4.27",
6
+ "version": "0.4.28",
7
7
  "type": "module",
8
8
  "main": "./src/index.ts",
9
9
  "types": "./dist/index.d.ts",
@@ -14,8 +14,8 @@
14
14
  "prepack": "bun run build"
15
15
  },
16
16
  "dependencies": {
17
- "@pylonsync/sdk": "0.4.27",
18
- "@pylonsync/sync": "0.4.27"
17
+ "@pylonsync/sdk": "0.4.28",
18
+ "@pylonsync/sync": "0.4.28"
19
19
  },
20
20
  "peerDependencies": {
21
21
  "react": ">=19.0.0"
package/src/index.ts CHANGED
@@ -525,6 +525,41 @@ export async function callFn<T = unknown>(
525
525
  );
526
526
  }
527
527
 
528
+ /**
529
+ * Ask an `agent()` run to stop.
530
+ *
531
+ * Cancel is durable, not a stream teardown: it lands on the run row,
532
+ * so it reaches a loop running on a different machine, and abandoning
533
+ * the SSE connection is NOT a cancel (a detached cloud run is supposed
534
+ * to survive the window closing).
535
+ *
536
+ * The call returns as soon as the request is recorded. A live
537
+ * generation stops at its next turn boundary — between tool calls
538
+ * within seconds, or after the current model response finishes.
539
+ * `run.cancelRequested` is true in that window; drive the stop
540
+ * button's pending state from it and treat `run.status === "cancelled"`
541
+ * as the confirmation.
542
+ *
543
+ * ```ts
544
+ * const { run } = useAgentRun(runId);
545
+ * <button
546
+ * disabled={run?.cancelRequested === true}
547
+ * onClick={() => cancelAgentRun("helper", runId)}
548
+ * >Stop</button>
549
+ * ```
550
+ */
551
+ export async function cancelAgentRun(
552
+ agentName: string,
553
+ runId: string,
554
+ options: { token?: string } = {},
555
+ ): Promise<{ runId: string; cancelled: boolean }> {
556
+ return callFn<{ runId: string; cancelled: boolean }>(
557
+ agentName,
558
+ { runId, cancel: true },
559
+ options,
560
+ );
561
+ }
562
+
528
563
  /** Options for {@link streamFn}. */
529
564
  export interface StreamFnOptions {
530
565
  token?: string;
Binary file