@datalayer/agent-runtimes 1.5.51 → 1.5.52
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.
|
@@ -163,12 +163,6 @@ export declare class HostStarters<K, P> implements StarterSource<K> {
|
|
|
163
163
|
}
|
|
164
164
|
/** Each AG-UI event of a run's `text/event-stream` body, as it arrives (`AgUiFrames`). */
|
|
165
165
|
export declare function agUiEventsOf(body: ReadableStream<Uint8Array>): AsyncIterable<AgUiEvent>;
|
|
166
|
-
/**
|
|
167
|
-
* The host's Datalayer client: a turn is started or sent on the deployment's
|
|
168
|
-
* session API (idempotent by the host's event id, SLACK §4.3, 2), its AG-UI
|
|
169
|
-
* stream reduced to semantic events, and its session mapped to the host's
|
|
170
|
-
* thread so that approvals and completions are delivered (§4.3, 3).
|
|
171
|
-
*/
|
|
172
166
|
export declare class HttpAgentClient<P> implements AgentClient<P>, SessionBinder<P> {
|
|
173
167
|
#private;
|
|
174
168
|
readonly apiUrl: string;
|
|
@@ -118,12 +118,16 @@ export class DevelopmentCredentials {
|
|
|
118
118
|
async forTurn(request) {
|
|
119
119
|
const response = await this.fetchImplementation(`${this.apiUrl}/api/ai-agents/v1/apps/deployments/${encodeURIComponent(request.applicationId)}`, { headers: { authorization: `Bearer ${this.token}` } });
|
|
120
120
|
if (!response.ok) {
|
|
121
|
-
throw new
|
|
121
|
+
throw new HostRefusedError(response.status, 'Datalayer did not answer the deployment.', 'The deployment');
|
|
122
122
|
}
|
|
123
123
|
const body = (await response.json());
|
|
124
124
|
const kept = body.deployment?.kept;
|
|
125
125
|
if (!kept?.url || !kept.agent_id) {
|
|
126
|
-
|
|
126
|
+
// A refusal the host says to the person (409), with the deployment's
|
|
127
|
+
// own reason when it gives one (a daily credit limit spent, paused).
|
|
128
|
+
throw new HostRefusedError(409, kept?.why
|
|
129
|
+
? `The deployment is not answering now: ${kept.why}`
|
|
130
|
+
: 'The deployment is not kept always on: turn it on under Ship.', 'The deployment');
|
|
127
131
|
}
|
|
128
132
|
return {
|
|
129
133
|
accessToken: this.token,
|
|
@@ -203,6 +207,19 @@ export async function* agUiEventsOf(body) {
|
|
|
203
207
|
* stream reduced to semantic events, and its session mapped to the host's
|
|
204
208
|
* thread so that approvals and completions are delivered (§4.3, 3).
|
|
205
209
|
*/
|
|
210
|
+
/** A refusal's `detail` when the answer is FastAPI's JSON, its status alone otherwise. */
|
|
211
|
+
async function refusalDetailOf(response) {
|
|
212
|
+
const text = await response.text().catch(() => '');
|
|
213
|
+
try {
|
|
214
|
+
const detail = JSON.parse(text).detail;
|
|
215
|
+
if (typeof detail === 'string' && detail)
|
|
216
|
+
return detail;
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
// Not JSON: the status says it.
|
|
220
|
+
}
|
|
221
|
+
return `Datalayer refused the turn (${response.status}).`;
|
|
222
|
+
}
|
|
206
223
|
export class HttpAgentClient {
|
|
207
224
|
apiUrl;
|
|
208
225
|
credentials;
|
|
@@ -251,7 +268,10 @@ export class HttpAgentClient {
|
|
|
251
268
|
method: 'POST',
|
|
252
269
|
});
|
|
253
270
|
if (!response.ok || !response.body) {
|
|
254
|
-
|
|
271
|
+
// The runtime's own reason, said to the person by the host: an
|
|
272
|
+
// application that signs its users and got no user token, a spent
|
|
273
|
+
// limit, a session of someone else.
|
|
274
|
+
throw new HostRefusedError(response.status, await refusalDetailOf(response), 'The turn');
|
|
255
275
|
}
|
|
256
276
|
const hostKey = host.bindable && this.hostKeyFor
|
|
257
277
|
? await this.hostKeyFor(request)
|
|
@@ -40,6 +40,13 @@ export interface WorkQueue<T> {
|
|
|
40
40
|
/** In-process development queue. A durable adapter is required in production. */
|
|
41
41
|
export declare class MemoryWorkQueue<T> implements WorkQueue<T> {
|
|
42
42
|
#private;
|
|
43
|
+
readonly onFailure: (error: unknown, item: T) => void;
|
|
44
|
+
/**
|
|
45
|
+
* A job that throws is reported here and dropped, and the next one is
|
|
46
|
+
* worked: one failure never stops the queue, nor the process with an
|
|
47
|
+
* unhandled rejection. The durable queue retries and dead-letters instead.
|
|
48
|
+
*/
|
|
49
|
+
constructor(onFailure?: (error: unknown, item: T) => void);
|
|
43
50
|
enqueue(item: T, idempotencyKey?: string): Promise<boolean>;
|
|
44
51
|
ready(): Promise<boolean>;
|
|
45
52
|
start(handler: (item: T) => Promise<void>): void;
|
|
@@ -11,10 +11,21 @@ export function tablePrefixOf(prefix) {
|
|
|
11
11
|
}
|
|
12
12
|
/** In-process development queue. A durable adapter is required in production. */
|
|
13
13
|
export class MemoryWorkQueue {
|
|
14
|
+
onFailure;
|
|
14
15
|
#items = [];
|
|
15
16
|
#keys = new Set();
|
|
16
17
|
#handler;
|
|
17
18
|
#running = false;
|
|
19
|
+
/**
|
|
20
|
+
* A job that throws is reported here and dropped, and the next one is
|
|
21
|
+
* worked: one failure never stops the queue, nor the process with an
|
|
22
|
+
* unhandled rejection. The durable queue retries and dead-letters instead.
|
|
23
|
+
*/
|
|
24
|
+
constructor(onFailure = error => {
|
|
25
|
+
console.error(`A job failed and was dropped: ${error instanceof Error ? error.message : String(error)}`);
|
|
26
|
+
}) {
|
|
27
|
+
this.onFailure = onFailure;
|
|
28
|
+
}
|
|
18
29
|
async enqueue(item, idempotencyKey) {
|
|
19
30
|
if (idempotencyKey) {
|
|
20
31
|
if (this.#keys.has(idempotencyKey)) {
|
|
@@ -52,7 +63,12 @@ export class MemoryWorkQueue {
|
|
|
52
63
|
}
|
|
53
64
|
const item = this.#items.shift();
|
|
54
65
|
if (item !== undefined) {
|
|
55
|
-
|
|
66
|
+
try {
|
|
67
|
+
await handler(item);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
this.onFailure(error, item);
|
|
71
|
+
}
|
|
56
72
|
}
|
|
57
73
|
}
|
|
58
74
|
}
|