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