@reactive-agents/svelte 0.9.0 → 0.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.
@@ -0,0 +1,94 @@
1
+ import * as svelte_store from 'svelte/store';
2
+
3
+ /** Mirrors the AgentStreamEvent union from @reactive-agents/runtime. */
4
+ type AgentStreamEvent = {
5
+ readonly _tag: "TextDelta";
6
+ readonly text: string;
7
+ } | {
8
+ readonly _tag: "StreamCompleted";
9
+ readonly output: string;
10
+ readonly metadata: Record<string, unknown>;
11
+ readonly taskId?: string;
12
+ readonly agentId?: string;
13
+ } | {
14
+ readonly _tag: "StreamError";
15
+ readonly cause: string;
16
+ } | {
17
+ readonly _tag: "IterationProgress";
18
+ readonly iteration: number;
19
+ readonly maxIterations: number;
20
+ readonly status: string;
21
+ } | {
22
+ readonly _tag: "StreamCancelled";
23
+ readonly reason: string;
24
+ readonly iterationsCompleted: number;
25
+ } | {
26
+ readonly _tag: string;
27
+ readonly [key: string]: unknown;
28
+ };
29
+ type AgentHookState = "idle" | "streaming" | "completed" | "error";
30
+ interface UseAgentStreamReturn {
31
+ /** Accumulated text output so far (grows as TextDelta events arrive). */
32
+ text: string;
33
+ /** All raw events received since the last run(). */
34
+ events: AgentStreamEvent[];
35
+ /** Current execution status. */
36
+ status: AgentHookState;
37
+ /** Error message if status === "error". */
38
+ error: string | null;
39
+ /** Full output when status === "completed". */
40
+ output: string | null;
41
+ /** Trigger a new run. Cancels any in-progress stream. */
42
+ run: (prompt: string, body?: Record<string, unknown>) => void;
43
+ /** Cancel the active stream. */
44
+ cancel: () => void;
45
+ }
46
+ interface UseAgentReturn {
47
+ /** Final output when status === "completed". */
48
+ output: string | null;
49
+ /** Whether the agent is currently running. */
50
+ loading: boolean;
51
+ /** Error message if the run failed. */
52
+ error: string | null;
53
+ /** Trigger a run. Resolves on completion. */
54
+ run: (prompt: string, body?: Record<string, unknown>) => Promise<string>;
55
+ }
56
+
57
+ interface AgentStreamState {
58
+ text: string;
59
+ events: AgentStreamEvent[];
60
+ status: "idle" | "streaming" | "completed" | "error";
61
+ error: string | null;
62
+ output: string | null;
63
+ }
64
+ /**
65
+ * Create a reactive Svelte store that streams agent output token-by-token.
66
+ * Returns a store + run() and cancel() functions.
67
+ *
68
+ * @example
69
+ * ```svelte
70
+ * <script>
71
+ * import { createAgentStream } from "@reactive-agents/svelte";
72
+ * const agent = createAgentStream("/api/agent");
73
+ * </script>
74
+ * <button on:click={() => agent.run("Hello!")}>Run</button>
75
+ * <p>{$agent.text}</p>
76
+ * ```
77
+ */
78
+ declare function createAgentStream(endpoint: string, requestInit?: Omit<RequestInit, "method" | "body" | "signal">): {
79
+ subscribe: (this: void, run: svelte_store.Subscriber<AgentStreamState>, invalidate?: () => void) => svelte_store.Unsubscriber;
80
+ run: (prompt: string, body?: Record<string, unknown>) => Promise<void>;
81
+ cancel: () => void;
82
+ };
83
+
84
+ interface AgentState {
85
+ output: string | null;
86
+ loading: boolean;
87
+ error: string | null;
88
+ }
89
+ declare function createAgent(endpoint: string, requestInit?: Omit<RequestInit, "method" | "body">): {
90
+ subscribe: (this: void, run: svelte_store.Subscriber<AgentState>, invalidate?: () => void) => svelte_store.Unsubscriber;
91
+ run: (prompt: string, body?: Record<string, unknown>) => Promise<string>;
92
+ };
93
+
94
+ export { type AgentHookState, type AgentState, type AgentStreamEvent, type AgentStreamState, type UseAgentReturn, type UseAgentStreamReturn, createAgent, createAgentStream };
package/dist/index.js ADDED
@@ -0,0 +1,105 @@
1
+ // src/agent-stream.ts
2
+ import { writable } from "svelte/store";
3
+ function createAgentStream(endpoint, requestInit) {
4
+ const store = writable({
5
+ text: "",
6
+ events: [],
7
+ status: "idle",
8
+ error: null,
9
+ output: null
10
+ });
11
+ let abortController = null;
12
+ function cancel() {
13
+ abortController?.abort();
14
+ store.update((s) => ({ ...s, status: "idle" }));
15
+ }
16
+ async function run(prompt, body) {
17
+ abortController?.abort();
18
+ abortController = new AbortController();
19
+ store.set({ text: "", events: [], status: "streaming", error: null, output: null });
20
+ try {
21
+ const res = await fetch(endpoint, {
22
+ ...requestInit,
23
+ method: "POST",
24
+ signal: abortController.signal,
25
+ headers: { "Content-Type": "application/json", ...requestInit?.headers },
26
+ body: JSON.stringify({ prompt, ...body })
27
+ });
28
+ if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
29
+ if (!res.body) throw new Error("No response body");
30
+ const reader = res.body.getReader();
31
+ const decoder = new TextDecoder();
32
+ let buffer = "";
33
+ while (true) {
34
+ const { done, value } = await reader.read();
35
+ if (done) break;
36
+ buffer += decoder.decode(value, { stream: true });
37
+ const lines = buffer.split("\n");
38
+ buffer = lines.pop() ?? "";
39
+ for (const line of lines) {
40
+ if (!line.startsWith("data: ")) continue;
41
+ const raw = line.slice(6).trim();
42
+ if (!raw) continue;
43
+ try {
44
+ const event = JSON.parse(raw);
45
+ store.update((s) => {
46
+ const next = { ...s, events: [...s.events, event] };
47
+ if (event._tag === "TextDelta" && "text" in event) {
48
+ next.text = s.text + event.text;
49
+ } else if (event._tag === "StreamCompleted" && "output" in event) {
50
+ next.output = event.output;
51
+ next.status = "completed";
52
+ } else if (event._tag === "StreamError" && "cause" in event) {
53
+ next.error = event.cause;
54
+ next.status = "error";
55
+ } else if (event._tag === "StreamCancelled") {
56
+ next.status = "idle";
57
+ }
58
+ return next;
59
+ });
60
+ } catch {
61
+ }
62
+ }
63
+ }
64
+ } catch (err) {
65
+ if (err instanceof Error && err.name === "AbortError") return;
66
+ store.update((s) => ({
67
+ ...s,
68
+ error: err instanceof Error ? err.message : String(err),
69
+ status: "error"
70
+ }));
71
+ }
72
+ }
73
+ return { subscribe: store.subscribe, run, cancel };
74
+ }
75
+
76
+ // src/agent.ts
77
+ import { writable as writable2 } from "svelte/store";
78
+ function createAgent(endpoint, requestInit) {
79
+ const store = writable2({ output: null, loading: false, error: null });
80
+ async function run(prompt, body) {
81
+ store.update((s) => ({ ...s, loading: true, error: null, output: null }));
82
+ try {
83
+ const res = await fetch(endpoint, {
84
+ ...requestInit,
85
+ method: "POST",
86
+ headers: { "Content-Type": "application/json", ...requestInit?.headers },
87
+ body: JSON.stringify({ prompt, ...body })
88
+ });
89
+ if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
90
+ const data = await res.json();
91
+ const result = data.output ?? data.result ?? "";
92
+ store.update((s) => ({ ...s, output: result, loading: false }));
93
+ return result;
94
+ } catch (err) {
95
+ const msg = err instanceof Error ? err.message : String(err);
96
+ store.update((s) => ({ ...s, error: msg, loading: false }));
97
+ throw err;
98
+ }
99
+ }
100
+ return { subscribe: store.subscribe, run };
101
+ }
102
+ export {
103
+ createAgent,
104
+ createAgentStream
105
+ };
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@reactive-agents/svelte",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Svelte stores for Reactive Agents — agentStream, agentRun",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": {
8
+ "bun": "./src/index.ts",
8
9
  "types": "./dist/index.d.ts",
9
10
  "import": "./dist/index.js",
10
11
  "default": "./dist/index.js"