@erdoai/server 0.1.4 → 0.1.5
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.js +2 -241
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,241 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
var
|
|
3
|
-
function getConfigFromEnv() {
|
|
4
|
-
const env = typeof process !== "undefined" ? process.env : {};
|
|
5
|
-
return {
|
|
6
|
-
endpoint: env.ERDO_ENDPOINT || env.NEXT_PUBLIC_ERDO_ENDPOINT || DEFAULT_ENDPOINT,
|
|
7
|
-
authToken: env.ERDO_AUTH_TOKEN || env.NEXT_PUBLIC_ERDO_API_KEY
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
function resolveConfig(userConfig) {
|
|
11
|
-
const envConfig = getConfigFromEnv();
|
|
12
|
-
const endpoint = userConfig?.endpoint || envConfig.endpoint || DEFAULT_ENDPOINT;
|
|
13
|
-
const authToken = userConfig?.authToken || envConfig.authToken;
|
|
14
|
-
if (!authToken) {
|
|
15
|
-
throw new Error(
|
|
16
|
-
"No auth token configured. Set ERDO_AUTH_TOKEN environment variable or pass authToken to ErdoClient."
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
return {
|
|
20
|
-
endpoint,
|
|
21
|
-
authToken
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// src/streaming/sse-client.ts
|
|
26
|
-
async function* parseSSEStream(response) {
|
|
27
|
-
if (!response.body) {
|
|
28
|
-
throw new Error("Response body is null");
|
|
29
|
-
}
|
|
30
|
-
const reader = response.body.getReader();
|
|
31
|
-
const decoder = new TextDecoder();
|
|
32
|
-
let buffer = "";
|
|
33
|
-
try {
|
|
34
|
-
while (true) {
|
|
35
|
-
const { done, value } = await reader.read();
|
|
36
|
-
if (done) {
|
|
37
|
-
if (buffer.trim()) {
|
|
38
|
-
const event = parseSSELine(buffer);
|
|
39
|
-
if (event) {
|
|
40
|
-
yield event;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
buffer += decoder.decode(value, { stream: true });
|
|
46
|
-
const lines = buffer.split("\n");
|
|
47
|
-
buffer = lines.pop() || "";
|
|
48
|
-
for (const line of lines) {
|
|
49
|
-
const event = parseSSELine(line);
|
|
50
|
-
if (event) {
|
|
51
|
-
yield event;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
} finally {
|
|
56
|
-
reader.releaseLock();
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
function parseSSELine(line) {
|
|
60
|
-
const trimmedLine = line.trim();
|
|
61
|
-
if (!trimmedLine) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
if (trimmedLine.startsWith("data: ")) {
|
|
65
|
-
const data = trimmedLine.slice(6);
|
|
66
|
-
if (!data.trim()) {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
try {
|
|
70
|
-
return JSON.parse(data);
|
|
71
|
-
} catch {
|
|
72
|
-
return { raw: data };
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
async function collectSSEEvents(response) {
|
|
78
|
-
const events = [];
|
|
79
|
-
for await (const event of parseSSEStream(response)) {
|
|
80
|
-
events.push(event);
|
|
81
|
-
}
|
|
82
|
-
return events;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// src/client.ts
|
|
86
|
-
var ErdoClient = class {
|
|
87
|
-
endpoint;
|
|
88
|
-
authToken;
|
|
89
|
-
constructor(config) {
|
|
90
|
-
const resolved = resolveConfig(config);
|
|
91
|
-
this.endpoint = resolved.endpoint;
|
|
92
|
-
this.authToken = resolved.authToken;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Invoke an agent and wait for the complete result
|
|
96
|
-
*/
|
|
97
|
-
async invoke(botKey, params = {}) {
|
|
98
|
-
const events = await this.collectEvents(botKey, params);
|
|
99
|
-
return this.extractResult(botKey, events);
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Invoke an agent and stream SSE events
|
|
103
|
-
*/
|
|
104
|
-
async *invokeStream(botKey, params = {}) {
|
|
105
|
-
const response = await this.makeRequest(botKey, params);
|
|
106
|
-
yield* parseSSEStream(response);
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Collect all events from an invocation
|
|
110
|
-
*/
|
|
111
|
-
async collectEvents(botKey, params) {
|
|
112
|
-
const response = await this.makeRequest(botKey, params);
|
|
113
|
-
return collectSSEEvents(response);
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Make the HTTP request to invoke an agent
|
|
117
|
-
*/
|
|
118
|
-
async makeRequest(botKey, params) {
|
|
119
|
-
const url = `${this.endpoint}/bots/${botKey}/invoke`;
|
|
120
|
-
const invokeParams = {};
|
|
121
|
-
if (params.messages) {
|
|
122
|
-
invokeParams.messages = params.messages;
|
|
123
|
-
}
|
|
124
|
-
if (params.parameters) {
|
|
125
|
-
invokeParams.parameters = params.parameters;
|
|
126
|
-
}
|
|
127
|
-
if (params.datasets) {
|
|
128
|
-
invokeParams.dataset_slugs = params.datasets;
|
|
129
|
-
}
|
|
130
|
-
if (params.mode) {
|
|
131
|
-
invokeParams.mode = params.mode;
|
|
132
|
-
}
|
|
133
|
-
if (params.manualMocks) {
|
|
134
|
-
invokeParams.manual_mocks = params.manualMocks;
|
|
135
|
-
}
|
|
136
|
-
const response = await fetch(url, {
|
|
137
|
-
method: "POST",
|
|
138
|
-
headers: {
|
|
139
|
-
Authorization: `Bearer ${this.authToken}`,
|
|
140
|
-
"Content-Type": "application/json",
|
|
141
|
-
Accept: "text/event-stream"
|
|
142
|
-
},
|
|
143
|
-
body: JSON.stringify(invokeParams)
|
|
144
|
-
});
|
|
145
|
-
if (!response.ok) {
|
|
146
|
-
const errorText = await response.text();
|
|
147
|
-
throw new Error(`API request failed with status ${response.status}: ${errorText}`);
|
|
148
|
-
}
|
|
149
|
-
return response;
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Extract structured result from SSE events
|
|
153
|
-
*
|
|
154
|
-
* Ported from: erdo-python-sdk/erdo/invoke/invoke.py - _extract_result_data()
|
|
155
|
-
*/
|
|
156
|
-
extractResult(botKey, events) {
|
|
157
|
-
const messages = [];
|
|
158
|
-
const steps = [];
|
|
159
|
-
const stepsSeenKeys = /* @__PURE__ */ new Set();
|
|
160
|
-
let finalResult;
|
|
161
|
-
let invocationId;
|
|
162
|
-
for (const event of events) {
|
|
163
|
-
if (!event) continue;
|
|
164
|
-
const payload = event.payload;
|
|
165
|
-
const metadata = event.metadata;
|
|
166
|
-
if (payload && typeof payload === "object") {
|
|
167
|
-
if ("invocation_id" in payload && !invocationId) {
|
|
168
|
-
invocationId = payload.invocation_id;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
if (payload && typeof payload === "object" && "action_type" in payload && "key" in payload) {
|
|
172
|
-
const stepKey = payload.key;
|
|
173
|
-
if (!stepsSeenKeys.has(stepKey)) {
|
|
174
|
-
stepsSeenKeys.add(stepKey);
|
|
175
|
-
steps.push({
|
|
176
|
-
key: stepKey,
|
|
177
|
-
action: payload.action_type,
|
|
178
|
-
status: "completed"
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (payload && typeof payload === "object" && "output" in payload && metadata?.user_visibility === "visible") {
|
|
183
|
-
const output = payload.output;
|
|
184
|
-
if (output && typeof output === "object" && "content" in output) {
|
|
185
|
-
const contentArray = output.content;
|
|
186
|
-
if (Array.isArray(contentArray)) {
|
|
187
|
-
for (const item of contentArray) {
|
|
188
|
-
if (item.content_type === "text") {
|
|
189
|
-
const role = metadata?.role || "assistant";
|
|
190
|
-
messages.push({
|
|
191
|
-
role,
|
|
192
|
-
content: item.content || ""
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (payload && typeof payload === "object" && "status" in payload && "output" in payload) {
|
|
200
|
-
finalResult = {
|
|
201
|
-
status: payload.status,
|
|
202
|
-
parameters: payload.parameters,
|
|
203
|
-
output: payload.output,
|
|
204
|
-
message: payload.message,
|
|
205
|
-
error: payload.error
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
return {
|
|
210
|
-
success: true,
|
|
211
|
-
botId: botKey,
|
|
212
|
-
invocationId,
|
|
213
|
-
result: finalResult,
|
|
214
|
-
messages,
|
|
215
|
-
events,
|
|
216
|
-
steps
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
var defaultClient = null;
|
|
221
|
-
function getDefaultClient() {
|
|
222
|
-
if (!defaultClient) {
|
|
223
|
-
defaultClient = new ErdoClient();
|
|
224
|
-
}
|
|
225
|
-
return defaultClient;
|
|
226
|
-
}
|
|
227
|
-
async function invoke(botKey, params = {}) {
|
|
228
|
-
return getDefaultClient().invoke(botKey, params);
|
|
229
|
-
}
|
|
230
|
-
async function* invokeStream(botKey, params = {}) {
|
|
231
|
-
yield* getDefaultClient().invokeStream(botKey, params);
|
|
232
|
-
}
|
|
233
|
-
export {
|
|
234
|
-
ErdoClient,
|
|
235
|
-
collectSSEEvents,
|
|
236
|
-
getConfigFromEnv,
|
|
237
|
-
invoke,
|
|
238
|
-
invokeStream,
|
|
239
|
-
parseSSEStream,
|
|
240
|
-
resolveConfig
|
|
241
|
-
};
|
|
1
|
+
var y="https://api.erdo.ai";function S(){let o=typeof process<"u"?process.env:{};return {endpoint:o.ERDO_ENDPOINT||o.NEXT_PUBLIC_ERDO_ENDPOINT||y,authToken:o.ERDO_AUTH_TOKEN||o.NEXT_PUBLIC_ERDO_API_KEY}}function p(o){let t=S(),e=o?.endpoint||t.endpoint||y,s=o?.authToken||t.authToken;if(!s)throw new Error("No auth token configured. Set ERDO_AUTH_TOKEN environment variable or pass authToken to ErdoClient.");return {endpoint:e,authToken:s}}async function*d(o){if(!o.body)throw new Error("Response body is null");let t=o.body.getReader(),e=new TextDecoder,s="";try{for(;;){let{done:r,value:i}=await t.read();if(r){if(s.trim()){let a=h(s);a&&(yield a);}break}s+=e.decode(i,{stream:!0});let u=s.split(`
|
|
2
|
+
`);s=u.pop()||"";for(let a of u){let l=h(a);l&&(yield l);}}}finally{t.releaseLock();}}function h(o){let t=o.trim();if(!t)return null;if(t.startsWith("data: ")){let e=t.slice(6);if(!e.trim())return null;try{return JSON.parse(e)}catch{return {raw:e}}}return null}async function v(o){let t=[];for await(let e of d(o))t.push(e);return t}var f=class{endpoint;authToken;constructor(t){let e=p(t);this.endpoint=e.endpoint,this.authToken=e.authToken;}async invoke(t,e={}){let s=await this.collectEvents(t,e);return this.extractResult(t,s)}async*invokeStream(t,e={}){let s=await this.makeRequest(t,e);yield*d(s);}async collectEvents(t,e){let s=await this.makeRequest(t,e);return v(s)}async makeRequest(t,e){let s=`${this.endpoint}/bots/${t}/invoke`,r={};e.messages&&(r.messages=e.messages),e.parameters&&(r.parameters=e.parameters),e.datasets&&(r.dataset_slugs=e.datasets),e.mode&&(r.mode=e.mode),e.manualMocks&&(r.manual_mocks=e.manualMocks);let i=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.authToken}`,"Content-Type":"application/json",Accept:"text/event-stream"},body:JSON.stringify(r)});if(!i.ok){let u=await i.text();throw new Error(`API request failed with status ${i.status}: ${u}`)}return i}extractResult(t,e){let s=[],r=[],i=new Set,u,a;for(let l of e){if(!l)continue;let n=l.payload,m=l.metadata;if(n&&typeof n=="object"&&"invocation_id"in n&&!a&&(a=n.invocation_id),n&&typeof n=="object"&&"action_type"in n&&"key"in n){let c=n.key;i.has(c)||(i.add(c),r.push({key:c,action:n.action_type,status:"completed"}));}if(n&&typeof n=="object"&&"output"in n&&m?.user_visibility==="visible"){let c=n.output;if(c&&typeof c=="object"&&"content"in c){let g=c.content;if(Array.isArray(g)){for(let k of g)if(k.content_type==="text"){let w=m?.role||"assistant";s.push({role:w,content:k.content||""});}}}}n&&typeof n=="object"&&"status"in n&&"output"in n&&(u={status:n.status,parameters:n.parameters,output:n.output,message:n.message,error:n.error});}return {success:true,botId:t,invocationId:a,result:u,messages:s,events:e,steps:r}}},E=null;function R(){return E||(E=new f),E}async function C(o,t={}){return R().invoke(o,t)}async function*T(o,t={}){yield*R().invokeStream(o,t);}export{f as ErdoClient,v as collectSSEEvents,S as getConfigFromEnv,C as invoke,T as invokeStream,d as parseSSEStream,p as resolveConfig};
|