sammy-sdk-client 0.1.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/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # sammy-sdk-client
2
+
3
+ Zero-dependency JavaScript client for the [Sammy](https://sammy.dev) AI agent runtime. Works in any framework — React, Vue, Svelte, vanilla — and in any modern JavaScript runtime (browser, Node 18+, edge).
4
+
5
+ `sammy-sdk-client` is the framework-agnostic transport layer. It speaks to the chat endpoint your server exposes (typically backed by [`sammy-sdk`](https://www.npmjs.com/package/sammy-sdk)'s `createSammyRouteHandler`) and handles JSON requests, conversation IDs, and SSE streaming.
6
+
7
+ For React-specific helpers see [`sammy-sdk-react`](https://www.npmjs.com/package/sammy-sdk-react). For a drop-in chat widget see [`sammy-sdk-ui`](https://www.npmjs.com/package/sammy-sdk-ui).
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install sammy-sdk-client
13
+ ```
14
+
15
+ You'll also need a chat endpoint on your backend. The fastest way is `createSammyRouteHandler` from `sammy-sdk`:
16
+
17
+ ```ts
18
+ // app/api/chat/route.ts (Next.js App Router)
19
+ import { Sammy, createSammyRouteHandler } from "sammy-sdk";
20
+ const sammy = new Sammy();
21
+ export const POST = createSammyRouteHandler(sammy);
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ```ts
27
+ import { SammyClient } from "sammy-sdk-client";
28
+
29
+ const client = new SammyClient({
30
+ endpoint: "/api/chat",
31
+ // Optional: custom headers (object or async function)
32
+ headers: async () => ({ Authorization: `Bearer ${await getToken()}` }),
33
+ });
34
+
35
+ // One-shot request/response (returns the full ChatResponse)
36
+ const reply = await client.chat("List all open deals");
37
+ console.log(reply.message);
38
+
39
+ // Streaming
40
+ const stream = client.stream("Summarise this week's pipeline");
41
+ stream
42
+ .on("text", (chunk) => process.stdout.write(chunk))
43
+ .on("tool_call", (call) => console.log("calling tool:", call.name))
44
+ .on("tool_result", (r) => console.log("tool", r.name, "->", r.result.success))
45
+ .on("agent_handoff", (h) => console.log("handed off to:", h.targetAgent))
46
+ .on("done", (final) => console.log("\ntools used:", final.toolsUsed.length))
47
+ .on("error", (err) => console.error(err));
48
+ ```
49
+
50
+ ## Conversations
51
+
52
+ `client.conversation(id?)` gives you a scoped object that re-uses the same `conversationId` across calls — useful for chat threads.
53
+
54
+ ```ts
55
+ const thread = client.conversation();
56
+ await thread.send("hi");
57
+ await thread.send("what did I just say?");
58
+ ```
59
+
60
+ ## API surface
61
+
62
+ - `new SammyClient(config)`
63
+ - `client.chat(message, options?)` — `Promise<ChatResponse>` (one-shot JSON; the server must speak JSON for this path — `createSammyRouteHandler` does)
64
+ - `client.stream(message, options?)` — `SammyStream` (event emitter)
65
+ - `client.conversation(id?)` — convenience scope for a single conversation
66
+
67
+ `SammyStream` events:
68
+
69
+ | Event | Handler argument |
70
+ |---|---|
71
+ | `text` | `string` chunk to append to the assistant message |
72
+ | `tool_call` | `ToolCallEvent` — `{ id, name, params }` |
73
+ | `tool_result` | `ToolResultEvent` — `{ id, name, result: { success, data?, error? } }` |
74
+ | `agent_handoff` | `AgentHandoffEvent` — `{ fromAgent, targetAgent, reason }` (multi-agent only) |
75
+ | `done` | the full `ChatResponse` |
76
+ | `error` | a real `Error` instance |
77
+
78
+ All exported types — `SammyClientConfig`, `ChatOptions`, `ChatResponse`, `SammyStream`, `ToolCallEvent`, `ToolResultEvent`, `ToolResult`, `ToolCallResult`, `AgentHandoffEvent`, `Attachment` — are exported from the package root.
79
+
80
+ ## License
81
+
82
+ MIT
@@ -0,0 +1,14 @@
1
+ import type { SammyClientConfig, ChatOptions, ChatResponse, SammyStream } from "./types";
2
+ export declare class SammyClient {
3
+ private config;
4
+ constructor(config: SammyClientConfig);
5
+ chat(message: string, options?: ChatOptions): Promise<ChatResponse>;
6
+ stream(message: string, options?: ChatOptions): SammyStream;
7
+ conversation(id?: string): {
8
+ id: string;
9
+ send: (message: string) => Promise<ChatResponse>;
10
+ stream: (message: string) => SammyStream;
11
+ };
12
+ private resolveHeaders;
13
+ }
14
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGzF,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAoB;gBAEtB,MAAM,EAAE,iBAAiB;IAQ/B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAwCzE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW;IAI3D,YAAY,CAAC,EAAE,CAAC,EAAE,MAAM;;wBAIJ,MAAM;0BACJ,MAAM;;YAId,cAAc;CAK7B"}
package/dist/client.js ADDED
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SammyClient = void 0;
4
+ const stream_1 = require("./stream");
5
+ class SammyClient {
6
+ config;
7
+ constructor(config) {
8
+ this.config = {
9
+ retries: 3,
10
+ timeout: 30000,
11
+ ...config,
12
+ };
13
+ }
14
+ async chat(message, options) {
15
+ const headers = await this.resolveHeaders();
16
+ const response = await fetch(this.config.endpoint, {
17
+ method: "POST",
18
+ headers: {
19
+ "Content-Type": "application/json",
20
+ Accept: "application/json",
21
+ ...headers,
22
+ },
23
+ body: JSON.stringify({
24
+ message,
25
+ conversationId: options?.conversationId || this.config.conversationId,
26
+ metadata: options?.metadata,
27
+ attachments: options?.attachments,
28
+ }),
29
+ signal: AbortSignal.timeout(this.config.timeout),
30
+ });
31
+ if (!response.ok) {
32
+ const text = await response.text().catch(() => "");
33
+ throw new Error(`Sammy request failed: ${response.status} ${response.statusText}${text ? ` - ${text}` : ""}`);
34
+ }
35
+ const contentType = response.headers.get("content-type") || "";
36
+ if (!contentType.includes("application/json")) {
37
+ const text = await response.text().catch(() => "");
38
+ throw new Error(`Expected JSON from chat endpoint but got "${contentType}". ` +
39
+ `If you're using the Sammy SDK route handler, this should not happen — ` +
40
+ `make sure your /api/chat route uses createSammyRouteHandler() from sammy-sdk, ` +
41
+ `or use client.stream() instead of client.chat() for SSE-only endpoints. ` +
42
+ `Body preview: ${text.slice(0, 200)}`);
43
+ }
44
+ return response.json();
45
+ }
46
+ stream(message, options) {
47
+ return (0, stream_1.createStream)(this.config, message, options);
48
+ }
49
+ conversation(id) {
50
+ const conversationId = id || crypto.randomUUID();
51
+ return {
52
+ id: conversationId,
53
+ send: (message) => this.chat(message, { conversationId }),
54
+ stream: (message) => this.stream(message, { conversationId }),
55
+ };
56
+ }
57
+ async resolveHeaders() {
58
+ if (!this.config.headers)
59
+ return {};
60
+ if (typeof this.config.headers === "function")
61
+ return this.config.headers();
62
+ return this.config.headers;
63
+ }
64
+ }
65
+ exports.SammyClient = SammyClient;
66
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { SammyClient } from "./client";
2
+ export type { SammyClientConfig, ChatOptions, ChatResponse, SammyStream, ToolCallEvent, ToolResultEvent, ToolResult, ToolCallResult, AgentHandoffEvent, Attachment, } from "./types";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,aAAa,EACb,eAAe,EACf,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,UAAU,GACX,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SammyClient = void 0;
4
+ var client_1 = require("./client");
5
+ Object.defineProperty(exports, "SammyClient", { enumerable: true, get: function () { return client_1.SammyClient; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAAuC;AAA9B,qGAAA,WAAW,OAAA"}
@@ -0,0 +1,3 @@
1
+ import type { SammyClientConfig, ChatOptions, SammyStream } from "./types";
2
+ export declare function createStream(config: SammyClientConfig, message: string, options?: ChatOptions): SammyStream;
3
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAgB,WAAW,EAAqD,MAAM,SAAS,CAAC;AAmB5I,wBAAgB,YAAY,CAC1B,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,WAAW,CA8Gb"}
package/dist/stream.js ADDED
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createStream = createStream;
4
+ function coerceError(payload) {
5
+ if (payload instanceof Error)
6
+ return payload;
7
+ if (typeof payload === "string")
8
+ return new Error(payload);
9
+ if (payload && typeof payload === "object") {
10
+ const message = payload.message;
11
+ if (typeof message === "string")
12
+ return new Error(message);
13
+ try {
14
+ return new Error(JSON.stringify(payload));
15
+ }
16
+ catch {
17
+ return new Error("Unknown error");
18
+ }
19
+ }
20
+ return new Error("Unknown error");
21
+ }
22
+ function createStream(config, message, options) {
23
+ const handlers = {};
24
+ let abortController = new AbortController();
25
+ let finalResponse = null;
26
+ const emit = (event, payload) => {
27
+ const list = handlers[event];
28
+ if (!list)
29
+ return;
30
+ for (const handler of list) {
31
+ try {
32
+ handler(payload);
33
+ }
34
+ catch {
35
+ // Swallow handler errors so one bad listener doesn't kill the stream.
36
+ }
37
+ }
38
+ };
39
+ const stream = {
40
+ on(event, handler) {
41
+ if (!handlers[event])
42
+ handlers[event] = [];
43
+ handlers[event].push(handler);
44
+ return stream;
45
+ },
46
+ abort() {
47
+ abortController?.abort();
48
+ abortController = null;
49
+ },
50
+ };
51
+ (async () => {
52
+ try {
53
+ const headersFn = config.headers;
54
+ const resolvedHeaders = headersFn
55
+ ? typeof headersFn === "function" ? await headersFn() : headersFn
56
+ : {};
57
+ const response = await fetch(config.endpoint, {
58
+ method: "POST",
59
+ headers: { "Content-Type": "application/json", Accept: "text/event-stream", ...resolvedHeaders },
60
+ body: JSON.stringify({
61
+ message,
62
+ conversationId: options?.conversationId || config.conversationId,
63
+ stream: true,
64
+ metadata: options?.metadata,
65
+ }),
66
+ signal: abortController?.signal,
67
+ });
68
+ if (!response.ok || !response.body) {
69
+ throw new Error(`Stream failed: ${response.status} ${response.statusText}`);
70
+ }
71
+ const reader = response.body.getReader();
72
+ const decoder = new TextDecoder();
73
+ let buffer = "";
74
+ while (true) {
75
+ const { done, value } = await reader.read();
76
+ if (done)
77
+ break;
78
+ buffer += decoder.decode(value, { stream: true });
79
+ const lines = buffer.split("\n");
80
+ buffer = lines.pop() || "";
81
+ for (const line of lines) {
82
+ if (!line.startsWith("data: "))
83
+ continue;
84
+ const data = line.slice(6);
85
+ if (data === "[DONE]")
86
+ continue;
87
+ let event;
88
+ try {
89
+ event = JSON.parse(data);
90
+ }
91
+ catch {
92
+ continue;
93
+ }
94
+ switch (event.type) {
95
+ case "text":
96
+ if (typeof event.data === "string")
97
+ emit("text", event.data);
98
+ break;
99
+ case "tool_call":
100
+ emit("tool_call", event.data);
101
+ break;
102
+ case "tool_result":
103
+ emit("tool_result", event.data);
104
+ break;
105
+ case "agent_handoff":
106
+ emit("agent_handoff", event.data);
107
+ break;
108
+ case "done":
109
+ finalResponse = event.data;
110
+ break;
111
+ case "error":
112
+ emit("error", coerceError(event.data));
113
+ break;
114
+ default:
115
+ // Forward-compatible: ignore unknown event types.
116
+ break;
117
+ }
118
+ }
119
+ }
120
+ emit("done", finalResponse ?? {});
121
+ }
122
+ catch (error) {
123
+ if (error.name === "AbortError")
124
+ return;
125
+ emit("error", coerceError(error));
126
+ }
127
+ })();
128
+ return stream;
129
+ }
130
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ export interface SammyClientConfig {
2
+ endpoint: string;
3
+ headers?: Record<string, string> | (() => Promise<Record<string, string>>);
4
+ conversationId?: string;
5
+ retries?: number;
6
+ timeout?: number;
7
+ }
8
+ export interface ChatOptions {
9
+ conversationId?: string;
10
+ metadata?: Record<string, unknown>;
11
+ attachments?: Attachment[];
12
+ }
13
+ export interface Attachment {
14
+ type: "image" | "document";
15
+ mimeType: string;
16
+ name: string;
17
+ data?: string;
18
+ url?: string;
19
+ extractedText?: string;
20
+ metadata?: Record<string, unknown>;
21
+ }
22
+ export interface ToolCallEvent {
23
+ id: string;
24
+ name: string;
25
+ params: Record<string, unknown>;
26
+ }
27
+ export interface ToolResult {
28
+ success: boolean;
29
+ data?: unknown;
30
+ error?: string;
31
+ }
32
+ export interface ToolResultEvent {
33
+ id: string;
34
+ name: string;
35
+ result: ToolResult;
36
+ }
37
+ export interface AgentHandoffEvent {
38
+ fromAgent: string;
39
+ targetAgent: string;
40
+ reason: string;
41
+ }
42
+ export interface ToolCallResult {
43
+ id: string;
44
+ name: string;
45
+ params: Record<string, unknown>;
46
+ success: boolean;
47
+ result?: unknown;
48
+ error?: string;
49
+ }
50
+ export interface ChatResponse {
51
+ message: string;
52
+ conversationId: string;
53
+ toolsUsed: ToolCallResult[];
54
+ agentUsed: string;
55
+ suggestedFollowUps: string[];
56
+ agentHandoff?: AgentHandoffEvent;
57
+ }
58
+ export interface SammyStream {
59
+ on(event: "text", handler: (chunk: string) => void): SammyStream;
60
+ on(event: "tool_call", handler: (call: ToolCallEvent) => void): SammyStream;
61
+ on(event: "tool_result", handler: (result: ToolResultEvent) => void): SammyStream;
62
+ on(event: "agent_handoff", handler: (handoff: AgentHandoffEvent) => void): SammyStream;
63
+ on(event: "done", handler: (response: ChatResponse) => void): SammyStream;
64
+ on(event: "error", handler: (error: Error) => void): SammyStream;
65
+ abort(): void;
66
+ }
67
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "sammy-sdk-client",
3
+ "version": "0.1.0",
4
+ "description": "Zero-dependency JavaScript client for the Sammy AI agent runtime (SSE streaming, conversations, attachments).",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "keywords": [
21
+ "sammy",
22
+ "sammy-sdk",
23
+ "ai",
24
+ "agent",
25
+ "chat",
26
+ "client",
27
+ "sse",
28
+ "streaming"
29
+ ],
30
+ "license": "MIT",
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/sammymitch0071/sammy.git",
37
+ "directory": "packages/client"
38
+ },
39
+ "bugs": {
40
+ "url": "https://github.com/sammymitch0071/sammy/issues"
41
+ },
42
+ "homepage": "https://sammy.dev",
43
+ "devDependencies": {
44
+ "rimraf": "^6.0.1",
45
+ "typescript": "^5.7.0"
46
+ },
47
+ "engines": {
48
+ "node": ">=18"
49
+ },
50
+ "scripts": {
51
+ "build": "tsc",
52
+ "dev": "tsc --watch",
53
+ "clean": "rimraf dist tsconfig.tsbuildinfo"
54
+ }
55
+ }