binario 0.1.0 → 0.2.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/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { useState, useRef, useCallback, useEffect } from 'react';
1
+ import { createContext as createContext$1, useState, useRef, useCallback, useEffect, useContext } from 'react';
2
2
  import { z } from 'zod';
3
3
 
4
4
  // src/hooks.ts
@@ -1820,6 +1820,465 @@ function useBinarioSemanticSearch(options = {}) {
1820
1820
  };
1821
1821
  }
1822
1822
 
1823
- export { useBinarioAgent, useBinarioChat, useBinarioChatWithMemory, useBinarioCompletion, useBinarioEmbed, useBinarioMemory, useBinarioSemanticSearch, useBinarioStream, useBinarioStructured, useBinarioTools };
1823
+ // src/client.ts
1824
+ var BINARIO_API_URL = "https://binario-api.databin81.workers.dev";
1825
+ var Binario = class {
1826
+ apiKey;
1827
+ baseUrl;
1828
+ timeout;
1829
+ maxRetries;
1830
+ constructor(apiKey, options = {}) {
1831
+ if (!apiKey || !apiKey.startsWith("bsk_")) {
1832
+ throw new Error('Invalid API key. Keys should start with "bsk_"');
1833
+ }
1834
+ this.apiKey = apiKey;
1835
+ this.baseUrl = options.baseUrl || BINARIO_API_URL;
1836
+ this.timeout = options.timeout || 3e4;
1837
+ this.maxRetries = options.maxRetries || 3;
1838
+ }
1839
+ /**
1840
+ * Simple chat completion
1841
+ */
1842
+ async chat(messageOrMessages, options = {}) {
1843
+ const messages = this.normalizeMessages(messageOrMessages, options.systemPrompt);
1844
+ const response = await this.request("/v1/chat/completions", {
1845
+ messages,
1846
+ model: options.model,
1847
+ temperature: options.temperature,
1848
+ max_tokens: options.maxTokens,
1849
+ tools: options.tools
1850
+ });
1851
+ return response;
1852
+ }
1853
+ /**
1854
+ * Streaming chat - returns async iterator
1855
+ */
1856
+ async *stream(messageOrMessages, options = {}) {
1857
+ const messages = this.normalizeMessages(messageOrMessages, options.systemPrompt);
1858
+ const response = await fetch(`${this.baseUrl}/v1/chat/stream`, {
1859
+ method: "POST",
1860
+ headers: this.getHeaders(),
1861
+ body: JSON.stringify({
1862
+ messages,
1863
+ model: options.model,
1864
+ temperature: options.temperature,
1865
+ max_tokens: options.maxTokens,
1866
+ stream: true
1867
+ })
1868
+ });
1869
+ if (!response.ok) {
1870
+ const error = await response.json().catch(() => ({ error: "Unknown error" }));
1871
+ throw new Error(error.error || `Request failed: ${response.status}`);
1872
+ }
1873
+ const reader = response.body?.getReader();
1874
+ if (!reader) {
1875
+ throw new Error("No response body");
1876
+ }
1877
+ const decoder = new TextDecoder();
1878
+ let fullContent = "";
1879
+ let buffer = "";
1880
+ while (true) {
1881
+ const { done, value } = await reader.read();
1882
+ if (done) break;
1883
+ buffer += decoder.decode(value, { stream: true });
1884
+ const lines = buffer.split("\n");
1885
+ buffer = lines.pop() || "";
1886
+ for (const line of lines) {
1887
+ if (line.startsWith("data: ")) {
1888
+ const data = line.slice(6);
1889
+ if (data === "[DONE]") continue;
1890
+ try {
1891
+ const parsed = JSON.parse(data);
1892
+ const content = parsed.choices?.[0]?.delta?.content;
1893
+ if (content) {
1894
+ fullContent += content;
1895
+ yield content;
1896
+ }
1897
+ } catch {
1898
+ }
1899
+ }
1900
+ }
1901
+ }
1902
+ return {
1903
+ id: crypto.randomUUID(),
1904
+ provider: "cloudflare",
1905
+ content: fullContent,
1906
+ model: options.model || "default",
1907
+ usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
1908
+ finishReason: "stop",
1909
+ latency: 0,
1910
+ cached: false
1911
+ };
1912
+ }
1913
+ /**
1914
+ * Stream with callbacks (alternative API)
1915
+ */
1916
+ async streamWithCallbacks(messageOrMessages, options) {
1917
+ const { onToken, onComplete, onError, ...chatOptions } = options;
1918
+ try {
1919
+ let fullContent = "";
1920
+ for await (const token of this.stream(messageOrMessages, chatOptions)) {
1921
+ fullContent += token;
1922
+ onToken?.(token);
1923
+ }
1924
+ const response = {
1925
+ id: crypto.randomUUID(),
1926
+ provider: "cloudflare",
1927
+ content: fullContent,
1928
+ model: chatOptions.model || "default",
1929
+ usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
1930
+ finishReason: "stop",
1931
+ latency: 0,
1932
+ cached: false
1933
+ };
1934
+ onComplete?.(response);
1935
+ return response;
1936
+ } catch (error) {
1937
+ const err = error instanceof Error ? error : new Error(String(error));
1938
+ onError?.(err);
1939
+ throw err;
1940
+ }
1941
+ }
1942
+ /**
1943
+ * Create an agent with tools
1944
+ */
1945
+ agent(options) {
1946
+ return new BinarioAgent(this, options);
1947
+ }
1948
+ /**
1949
+ * Get current usage
1950
+ */
1951
+ async getUsage() {
1952
+ return this.request("/v1/usage", {}, "GET");
1953
+ }
1954
+ /**
1955
+ * List available models
1956
+ */
1957
+ async listModels() {
1958
+ return this.request("/v1/models", {}, "GET");
1959
+ }
1960
+ // Private helpers
1961
+ normalizeMessages(input, systemPrompt) {
1962
+ const messages = [];
1963
+ if (systemPrompt) {
1964
+ messages.push({ role: "system", content: systemPrompt });
1965
+ }
1966
+ if (typeof input === "string") {
1967
+ messages.push({ role: "user", content: input });
1968
+ } else {
1969
+ messages.push(...input);
1970
+ }
1971
+ return messages;
1972
+ }
1973
+ getHeaders() {
1974
+ return {
1975
+ "Content-Type": "application/json",
1976
+ "Authorization": `Bearer ${this.apiKey}`,
1977
+ "X-Binario-SDK": "js/0.1.0"
1978
+ };
1979
+ }
1980
+ async request(endpoint, body, method = "POST") {
1981
+ let lastError = null;
1982
+ for (let i = 0; i < this.maxRetries; i++) {
1983
+ try {
1984
+ const controller = new AbortController();
1985
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1986
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
1987
+ method,
1988
+ headers: this.getHeaders(),
1989
+ body: method === "POST" ? JSON.stringify(body) : void 0,
1990
+ signal: controller.signal
1991
+ });
1992
+ clearTimeout(timeoutId);
1993
+ if (!response.ok) {
1994
+ const error = await response.json().catch(() => ({ error: "Unknown error" }));
1995
+ if (response.status === 429) {
1996
+ const retryAfter = response.headers.get("Retry-After");
1997
+ throw new BinarioRateLimitError(
1998
+ error.error || "Rate limit exceeded",
1999
+ retryAfter ? parseInt(retryAfter) : 60
2000
+ );
2001
+ }
2002
+ if (response.status === 402) {
2003
+ throw new BinarioPaymentError(error.error || "Payment required");
2004
+ }
2005
+ throw new Error(error.error || `Request failed: ${response.status}`);
2006
+ }
2007
+ return response.json();
2008
+ } catch (error) {
2009
+ lastError = error instanceof Error ? error : new Error(String(error));
2010
+ if (error instanceof BinarioPaymentError) {
2011
+ throw error;
2012
+ }
2013
+ if (i < this.maxRetries - 1) {
2014
+ await new Promise((resolve) => setTimeout(resolve, Math.pow(2, i) * 1e3));
2015
+ }
2016
+ }
2017
+ }
2018
+ throw lastError || new Error("Request failed");
2019
+ }
2020
+ };
2021
+ var BinarioAgent = class {
2022
+ client;
2023
+ options;
2024
+ constructor(client, options) {
2025
+ this.client = client;
2026
+ this.options = options;
2027
+ }
2028
+ /**
2029
+ * Run the agent with a user message
2030
+ */
2031
+ async run(message) {
2032
+ const response = await this.client.request("/v1/agents/run", {
2033
+ message,
2034
+ name: this.options.name,
2035
+ systemPrompt: this.options.systemPrompt,
2036
+ tools: this.options.tools,
2037
+ maxIterations: this.options.maxIterations || 10,
2038
+ model: this.options.model
2039
+ });
2040
+ return response;
2041
+ }
2042
+ /**
2043
+ * Run agent with streaming
2044
+ */
2045
+ async *runStream(message) {
2046
+ const response = await fetch(`${this.client.baseUrl}/v1/agents/stream`, {
2047
+ method: "POST",
2048
+ headers: this.client.getHeaders(),
2049
+ body: JSON.stringify({
2050
+ message,
2051
+ name: this.options.name,
2052
+ systemPrompt: this.options.systemPrompt,
2053
+ tools: this.options.tools,
2054
+ maxIterations: this.options.maxIterations || 10,
2055
+ model: this.options.model
2056
+ })
2057
+ });
2058
+ if (!response.ok) {
2059
+ throw new Error(`Agent request failed: ${response.status}`);
2060
+ }
2061
+ const reader = response.body?.getReader();
2062
+ if (!reader) throw new Error("No response body");
2063
+ const decoder = new TextDecoder();
2064
+ let buffer = "";
2065
+ while (true) {
2066
+ const { done, value } = await reader.read();
2067
+ if (done) break;
2068
+ buffer += decoder.decode(value, { stream: true });
2069
+ const lines = buffer.split("\n");
2070
+ buffer = lines.pop() || "";
2071
+ for (const line of lines) {
2072
+ if (line.startsWith("data: ")) {
2073
+ const data = line.slice(6);
2074
+ if (data === "[DONE]") continue;
2075
+ try {
2076
+ yield JSON.parse(data);
2077
+ } catch {
2078
+ }
2079
+ }
2080
+ }
2081
+ }
2082
+ }
2083
+ };
2084
+ var BinarioRateLimitError = class extends Error {
2085
+ retryAfter;
2086
+ constructor(message, retryAfter) {
2087
+ super(message);
2088
+ this.name = "BinarioRateLimitError";
2089
+ this.retryAfter = retryAfter;
2090
+ }
2091
+ };
2092
+ var BinarioPaymentError = class extends Error {
2093
+ constructor(message) {
2094
+ super(message);
2095
+ this.name = "BinarioPaymentError";
2096
+ }
2097
+ };
2098
+
2099
+ // src/client-hooks.ts
2100
+ var BinarioContext = createContext$1(null);
2101
+ function BinarioProvider({ apiKey, baseUrl, children }) {
2102
+ const clientRef = useRef(null);
2103
+ if (!clientRef.current || clientRef.current.apiKey !== apiKey) {
2104
+ clientRef.current = new Binario(apiKey, { baseUrl });
2105
+ }
2106
+ return (
2107
+ // @ts-ignore - React.createElement for compatibility
2108
+ BinarioContext.Provider({ value: { client: clientRef.current } }, children)
2109
+ );
2110
+ }
2111
+ function useBinarioClient() {
2112
+ const context = useContext(BinarioContext);
2113
+ if (!context) {
2114
+ throw new Error("useBinarioClient must be used within a BinarioProvider");
2115
+ }
2116
+ return context.client;
2117
+ }
2118
+ function useChat(client, options = {}) {
2119
+ const [messages, setMessages] = useState(options.initialMessages || []);
2120
+ const [input, setInput] = useState("");
2121
+ const [isLoading, setIsLoading] = useState(false);
2122
+ const [error, setError] = useState(null);
2123
+ const abortRef = useRef(false);
2124
+ const stop = useCallback(() => {
2125
+ abortRef.current = true;
2126
+ setIsLoading(false);
2127
+ }, []);
2128
+ const send = useCallback(async (content) => {
2129
+ const messageContent = content || input;
2130
+ if (!messageContent.trim()) return;
2131
+ setIsLoading(true);
2132
+ setError(null);
2133
+ abortRef.current = false;
2134
+ const userMessage = { role: "user", content: messageContent };
2135
+ const newMessages = [...messages, userMessage];
2136
+ setMessages(newMessages);
2137
+ setInput("");
2138
+ try {
2139
+ const response = await client.chat(newMessages, {
2140
+ model: options.model,
2141
+ temperature: options.temperature,
2142
+ maxTokens: options.maxTokens,
2143
+ systemPrompt: options.systemPrompt
2144
+ });
2145
+ if (abortRef.current) return;
2146
+ const assistantMessage = {
2147
+ role: "assistant",
2148
+ content: response.content || response.choices?.[0]?.message?.content || ""
2149
+ };
2150
+ setMessages([...newMessages, assistantMessage]);
2151
+ options.onFinish?.(response);
2152
+ } catch (err) {
2153
+ const e = err instanceof Error ? err : new Error(String(err));
2154
+ setError(e);
2155
+ options.onError?.(e);
2156
+ } finally {
2157
+ setIsLoading(false);
2158
+ }
2159
+ }, [messages, input, client, options]);
2160
+ return { messages, input, setInput, isLoading, error, send, setMessages, stop };
2161
+ }
2162
+ function useStream(client, options = {}) {
2163
+ const [messages, setMessages] = useState(options.initialMessages || []);
2164
+ const [input, setInput] = useState("");
2165
+ const [isStreaming, setIsStreaming] = useState(false);
2166
+ const [error, setError] = useState(null);
2167
+ const [streamingContent, setStreamingContent] = useState("");
2168
+ const abortRef = useRef(false);
2169
+ const stop = useCallback(() => {
2170
+ abortRef.current = true;
2171
+ setIsStreaming(false);
2172
+ }, []);
2173
+ const send = useCallback(async (content) => {
2174
+ const messageContent = content || input;
2175
+ if (!messageContent.trim()) return;
2176
+ setIsStreaming(true);
2177
+ setError(null);
2178
+ setStreamingContent("");
2179
+ abortRef.current = false;
2180
+ const userMessage = { role: "user", content: messageContent };
2181
+ const newMessages = [...messages, userMessage];
2182
+ setMessages(newMessages);
2183
+ setInput("");
2184
+ let fullContent = "";
2185
+ try {
2186
+ for await (const token of client.stream(newMessages, {
2187
+ model: options.model,
2188
+ temperature: options.temperature,
2189
+ maxTokens: options.maxTokens,
2190
+ systemPrompt: options.systemPrompt
2191
+ })) {
2192
+ if (abortRef.current) break;
2193
+ fullContent += token;
2194
+ setStreamingContent(fullContent);
2195
+ options.onToken?.(token);
2196
+ }
2197
+ if (!abortRef.current) {
2198
+ const assistantMessage = { role: "assistant", content: fullContent };
2199
+ setMessages([...newMessages, assistantMessage]);
2200
+ setStreamingContent("");
2201
+ options.onFinish?.({ content: fullContent });
2202
+ }
2203
+ } catch (err) {
2204
+ const e = err instanceof Error ? err : new Error(String(err));
2205
+ setError(e);
2206
+ options.onError?.(e);
2207
+ } finally {
2208
+ setIsStreaming(false);
2209
+ }
2210
+ }, [messages, input, client, options]);
2211
+ return { messages, input, setInput, isStreaming, error, streamingContent, send, setMessages, stop };
2212
+ }
2213
+ function useAgent(client, options) {
2214
+ const [output, setOutput] = useState("");
2215
+ const [isRunning, setIsRunning] = useState(false);
2216
+ const [error, setError] = useState(null);
2217
+ const [toolCalls, setToolCalls] = useState([]);
2218
+ const abortRef = useRef(false);
2219
+ const stop = useCallback(() => {
2220
+ abortRef.current = true;
2221
+ setIsRunning(false);
2222
+ }, []);
2223
+ const run = useCallback(async (message) => {
2224
+ setIsRunning(true);
2225
+ setError(null);
2226
+ setOutput("");
2227
+ setToolCalls([]);
2228
+ abortRef.current = false;
2229
+ try {
2230
+ const agent = client.agent({
2231
+ name: options.name,
2232
+ systemPrompt: options.systemPrompt,
2233
+ tools: options.tools,
2234
+ maxIterations: options.maxIterations,
2235
+ model: options.model
2236
+ });
2237
+ const result = await agent.run(message);
2238
+ if (abortRef.current) return null;
2239
+ setOutput(result.output || "");
2240
+ if (result.toolCalls) {
2241
+ const calls = result.toolCalls.map((tc) => ({
2242
+ tool: tc.tool || tc.name,
2243
+ args: tc.args || tc.arguments
2244
+ }));
2245
+ setToolCalls(calls);
2246
+ calls.forEach((tc) => options.onToolCall?.(tc.tool, tc.args));
2247
+ }
2248
+ return result.output || "";
2249
+ } catch (err) {
2250
+ const e = err instanceof Error ? err : new Error(String(err));
2251
+ setError(e);
2252
+ options.onError?.(e);
2253
+ return null;
2254
+ } finally {
2255
+ setIsRunning(false);
2256
+ }
2257
+ }, [client, options]);
2258
+ return { output, isRunning, error, toolCalls, run, stop };
2259
+ }
2260
+ function useUsage(client) {
2261
+ const [usage, setUsage] = useState(null);
2262
+ const [isLoading, setIsLoading] = useState(false);
2263
+ const [error, setError] = useState(null);
2264
+ const refresh = useCallback(async () => {
2265
+ setIsLoading(true);
2266
+ setError(null);
2267
+ try {
2268
+ const data = await client.getUsage();
2269
+ setUsage(data);
2270
+ } catch (err) {
2271
+ setError(err instanceof Error ? err : new Error(String(err)));
2272
+ } finally {
2273
+ setIsLoading(false);
2274
+ }
2275
+ }, [client]);
2276
+ useEffect(() => {
2277
+ refresh();
2278
+ }, [refresh]);
2279
+ return { usage, isLoading, error, refresh };
2280
+ }
2281
+
2282
+ export { BinarioProvider, useAgent, useBinarioAgent, useBinarioChat, useBinarioChatWithMemory, useBinarioClient, useBinarioCompletion, useBinarioEmbed, useBinarioMemory, useBinarioSemanticSearch, useBinarioStream, useBinarioStructured, useBinarioTools, useChat, useStream, useUsage };
1824
2283
  //# sourceMappingURL=react.js.map
1825
2284
  //# sourceMappingURL=react.js.map