@inferencesh/sdk 0.27.0 → 0.29.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/CHANGELOG.md +20 -0
- package/dist/agent/actions.js +16 -7
- package/dist/agent/reducer.d.ts +6 -0
- package/dist/agent/reducer.js +72 -8
- package/dist/agent/types.d.ts +2 -0
- package/dist/api/agents.js +14 -3
- package/dist/api/engines.d.ts +11 -3
- package/dist/api/engines.js +14 -3
- package/dist/api/write-bodies.d.ts +2 -2
- package/dist/http/client.js +36 -2
- package/dist/http/poll.d.ts +7 -2
- package/dist/http/poll.js +5 -2
- package/dist/types.d.ts +310 -130
- package/dist/types.js +39 -32
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.29.0] - 2026-10-17
|
|
11
|
+
|
|
12
|
+
### Removed
|
|
13
|
+
- `CredentialConfigDTO.provider_info` is gone: read `company` (INF-1079). The API stopped sending it in api-v1313.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- `CredentialConfigDTO.auth_scheme_id` is `auth_provider_id`, matching the API (INF-1079).
|
|
17
|
+
- Generated types follow the API: engine release targets (`client.engines.updateBinary` takes a release target, `releases()` lists channel heads), `EngineDTO.capabilities` (`EngineCapability`, `EngineCapabilities`), `ChatMessageDTO.compaction_meta`.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- Partial chat and run stream updates merge instead of replacing, and streamed text never blinks back to an older copy.
|
|
21
|
+
- A read that got no response is sent again, twice.
|
|
22
|
+
|
|
23
|
+
## [0.28.0] - 2026-10-15
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- Types regenerated for the credentials vocabulary (INF-1079): `AuthSchemeDTO`, `AuthSchemeCreateRequest`, `AuthSchemeUpdateRequest`, `AuthSchemeHooksDTO`, `AuthSchemeSeedResult` are now `AuthProviderDTO`, `AuthProviderCreateRequest`, `AuthProviderUpdateRequest`, `AuthProviderHooksDTO`, `AuthProviderSeedResult`; `AuthSchemeSpec` and its `AuthScheme*` enums are `AuthMethod` and `AuthMethod*`; `ProviderDTO`, `ProviderSeed`, `ProviderSummary`, `ProviderTreeDTO`, `ProviderUpsertRequest`, `ProviderCategory`, `ProviderStatus` are `Company*`. `CredentialConfigDTO.company` is the company (`provider_info` still carries the same value, deprecated). Wire formats are unchanged.
|
|
27
|
+
- `pollUntilIdle` rejects once and stops polling when the run fails; `sendMessage({ stream: false })` no longer hangs forever (99075b7).
|
|
28
|
+
- Test mocks tidied (70cce44); dependabot overrides and `allowBuilds` in the pnpm workspace (75be627, 54b7ce1).
|
|
29
|
+
|
|
10
30
|
## [0.27.0] - 2026-10-13
|
|
11
31
|
|
|
12
32
|
### Changed
|
package/dist/agent/actions.js
CHANGED
|
@@ -12,6 +12,7 @@ import { createLLMDeltaAccumulator } from '../delta.js';
|
|
|
12
12
|
import { isAdHocConfig, extractClientToolHandlers } from './types.js';
|
|
13
13
|
import * as api from './api.js';
|
|
14
14
|
import { buildMCPInputResult } from './mcp-input.js';
|
|
15
|
+
import { applyChatUpdate } from './reducer.js';
|
|
15
16
|
import { isInferenceError } from '../http/errors.js';
|
|
16
17
|
// =============================================================================
|
|
17
18
|
// Action Creators
|
|
@@ -226,11 +227,16 @@ export function createActions(ctx) {
|
|
|
226
227
|
},
|
|
227
228
|
});
|
|
228
229
|
// Listen for Chat object updates (status changes only — don't replace messages)
|
|
229
|
-
manager.addEventListener('chats', (chatData) => {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
230
|
+
manager.addEventListener('chats', (chatData, fields) => {
|
|
231
|
+
if (!chatData)
|
|
232
|
+
return;
|
|
233
|
+
dispatch({ type: 'UPDATE_CHAT', payload: chatData, fields });
|
|
234
|
+
// A partial update (a plan step writing agent_data) says nothing about
|
|
235
|
+
// the turn on its own: judge the chat it merges into.
|
|
236
|
+
const chat = applyChatUpdate(getState().chat, chatData, fields);
|
|
237
|
+
if (chat) {
|
|
238
|
+
callbacks.onStatusChange?.(isChatBusy(chat) ? 'streaming' : 'idle');
|
|
239
|
+
checkTurnEnd(chat);
|
|
234
240
|
}
|
|
235
241
|
});
|
|
236
242
|
// Listen for ChatMessage updates
|
|
@@ -244,8 +250,11 @@ export function createActions(ctx) {
|
|
|
244
250
|
updateMessage(message, fields);
|
|
245
251
|
});
|
|
246
252
|
// Listen for AgentRun updates (state transitions, output)
|
|
247
|
-
manager.addEventListener('agent_runs', (run) => {
|
|
248
|
-
dispatch({ type: 'UPDATE_ACTIVE_RUN', payload: run });
|
|
253
|
+
manager.addEventListener('agent_runs', (run, fields) => {
|
|
254
|
+
dispatch({ type: 'UPDATE_ACTIVE_RUN', payload: run, fields });
|
|
255
|
+
// A partial update (the run's output) carries no state.
|
|
256
|
+
if (fields)
|
|
257
|
+
return;
|
|
249
258
|
callbacks.onStatusChange?.(isRunWorking(run.state) || isRunInterrupted(run.state) ? 'streaming' : 'idle');
|
|
250
259
|
const currentChat = getState().chat;
|
|
251
260
|
if (currentChat)
|
package/dist/agent/reducer.d.ts
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Pure reducer for managing agent chat state.
|
|
5
5
|
*/
|
|
6
|
+
import type { ChatDTO } from '../types.js';
|
|
6
7
|
import type { AgentChatState, ChatAction } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* The chat after a chats event: replaced by a full one, merged with a partial
|
|
10
|
+
* one. A partial update to another chat (or before any chat) is dropped.
|
|
11
|
+
*/
|
|
12
|
+
export declare function applyChatUpdate(existing: ChatDTO | null, update: ChatDTO, fields?: string[]): ChatDTO | null;
|
|
7
13
|
export declare const initialState: AgentChatState;
|
|
8
14
|
export declare function chatReducer(state: AgentChatState, action: ChatAction): AgentChatState;
|
package/dist/agent/reducer.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Pure reducer for managing agent chat state.
|
|
5
5
|
*/
|
|
6
6
|
import { ChatStatusBusy, ChatStatusAwaitingInput, ChatStatusIdle } from '../types.js';
|
|
7
|
-
import { isRunInterrupted, isRunWorking } from '../utils.js';
|
|
7
|
+
import { isMessageTerminal, isRunInterrupted, isRunWorking } from '../utils.js';
|
|
8
8
|
function deriveChatStatus(run) {
|
|
9
9
|
if (!run)
|
|
10
10
|
return ChatStatusIdle;
|
|
@@ -14,6 +14,38 @@ function deriveChatStatus(run) {
|
|
|
14
14
|
return ChatStatusAwaitingInput;
|
|
15
15
|
return ChatStatusIdle;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* A partial stream update (`fields` set) carries only the fields it names, so
|
|
19
|
+
* it merges into the object it updates instead of replacing it: a chat update
|
|
20
|
+
* naming only agent_data (a plan step) keeps the chat's status and active run.
|
|
21
|
+
* A named field missing from the payload was cleared (omitempty).
|
|
22
|
+
*/
|
|
23
|
+
function mergeFields(existing, update, fields) {
|
|
24
|
+
const merged = { ...existing };
|
|
25
|
+
for (const field of fields)
|
|
26
|
+
merged[field] = update[field];
|
|
27
|
+
return merged;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The chat after a chats event: replaced by a full one, merged with a partial
|
|
31
|
+
* one. A partial update to another chat (or before any chat) is dropped.
|
|
32
|
+
*/
|
|
33
|
+
export function applyChatUpdate(existing, update, fields) {
|
|
34
|
+
if (!fields)
|
|
35
|
+
return update;
|
|
36
|
+
if (!existing || existing.id !== update.id)
|
|
37
|
+
return existing;
|
|
38
|
+
const merged = mergeFields(existing, update, fields);
|
|
39
|
+
// The projector's update names active_run_id, which ChatDTO does not
|
|
40
|
+
// declare. The run object belongs to that id: a new or cleared active run
|
|
41
|
+
// drops it until the run's own event arrives.
|
|
42
|
+
if (fields.includes('active_run_id')) {
|
|
43
|
+
const runId = update.active_run_id;
|
|
44
|
+
if (merged.active_run && merged.active_run.id !== runId)
|
|
45
|
+
merged.active_run = undefined;
|
|
46
|
+
}
|
|
47
|
+
return merged;
|
|
48
|
+
}
|
|
17
49
|
/**
|
|
18
50
|
* Every message enters state through here. The API serializes a message with
|
|
19
51
|
* no content as `content: null` (a nil Go slice), and a partial stream update
|
|
@@ -27,6 +59,28 @@ function normalizeMessage(message, existing) {
|
|
|
27
59
|
return message;
|
|
28
60
|
return { ...message, content: existing?.content ?? [] };
|
|
29
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Streamed text only grows until the message is done. Deltas build the text
|
|
64
|
+
* locally, while a message update carries the server's saved copy, which can
|
|
65
|
+
* lag behind them (often still empty). Taking that copy as-is blanks the text
|
|
66
|
+
* until the next delta, so while the message is still generating, a text
|
|
67
|
+
* that is an earlier version of what is shown keeps what is shown. Once the
|
|
68
|
+
* message is terminal the server's copy is final and wins.
|
|
69
|
+
*/
|
|
70
|
+
function keepStreamedText(updated, existing) {
|
|
71
|
+
if (isMessageTerminal(updated.status))
|
|
72
|
+
return updated;
|
|
73
|
+
const shown = existing.content.find((c) => c.type === 'text')?.text;
|
|
74
|
+
if (!shown)
|
|
75
|
+
return updated;
|
|
76
|
+
const incoming = updated.content.find((c) => c.type === 'text');
|
|
77
|
+
if (incoming?.text && !shown.startsWith(incoming.text))
|
|
78
|
+
return updated;
|
|
79
|
+
const content = incoming
|
|
80
|
+
? updated.content.map((c) => (c === incoming ? { ...c, text: shown } : c))
|
|
81
|
+
: [{ type: 'text', text: shown }, ...updated.content];
|
|
82
|
+
return { ...updated, content };
|
|
83
|
+
}
|
|
30
84
|
const normalizeMessages = (messages) => messages.map((m) => normalizeMessage(m));
|
|
31
85
|
// =============================================================================
|
|
32
86
|
// Initial State
|
|
@@ -59,10 +113,10 @@ export function chatReducer(state, action) {
|
|
|
59
113
|
}
|
|
60
114
|
case 'UPDATE_CHAT': {
|
|
61
115
|
// Update chat metadata without replacing messages
|
|
62
|
-
|
|
63
|
-
if (!chat)
|
|
116
|
+
if (!action.payload)
|
|
64
117
|
return state;
|
|
65
|
-
|
|
118
|
+
const chat = applyChatUpdate(state.chat, action.payload, action.fields);
|
|
119
|
+
return chat === state.chat ? state : { ...state, chat };
|
|
66
120
|
}
|
|
67
121
|
// The settings and set-agent endpoints answer with only what they wrote.
|
|
68
122
|
// Merge it into the chat it belongs to; a chat switched away from in the
|
|
@@ -104,7 +158,15 @@ export function chatReducer(state, action) {
|
|
|
104
158
|
case 'UPDATE_ACTIVE_RUN': {
|
|
105
159
|
if (!state.chat)
|
|
106
160
|
return state;
|
|
107
|
-
|
|
161
|
+
let run = action.payload;
|
|
162
|
+
if (action.fields) {
|
|
163
|
+
// A partial update (the run's output) needs the run it belongs to.
|
|
164
|
+
const existing = state.chat.active_run;
|
|
165
|
+
if (!existing || existing.id !== run.id)
|
|
166
|
+
return state;
|
|
167
|
+
run = mergeFields(existing, run, action.fields);
|
|
168
|
+
}
|
|
169
|
+
return { ...state, chat: { ...state.chat, active_run: run, status: deriveChatStatus(run) } };
|
|
108
170
|
}
|
|
109
171
|
case 'SET_MESSAGES':
|
|
110
172
|
return { ...state, messages: normalizeMessages(action.payload) };
|
|
@@ -120,9 +182,7 @@ export function chatReducer(state, action) {
|
|
|
120
182
|
const existingIndex = state.messages.findIndex((m) => m.id === message.id);
|
|
121
183
|
if (existingIndex !== -1) {
|
|
122
184
|
const existing = state.messages[existingIndex];
|
|
123
|
-
const updated = action.partial
|
|
124
|
-
? normalizeMessage({ ...existing, ...message }, existing)
|
|
125
|
-
: normalizeMessage(message);
|
|
185
|
+
const updated = keepStreamedText(action.partial ? normalizeMessage({ ...existing, ...message }, existing) : normalizeMessage(message), existing);
|
|
126
186
|
if (existing === updated)
|
|
127
187
|
return state;
|
|
128
188
|
const newMessages = [...state.messages];
|
|
@@ -148,6 +208,10 @@ export function chatReducer(state, action) {
|
|
|
148
208
|
if (!target)
|
|
149
209
|
return state;
|
|
150
210
|
const textBlock = target.content.find(c => c.type === 'text');
|
|
211
|
+
// Deltas from a stream joined mid-message start partway; the message
|
|
212
|
+
// update already showed more, so keep it until they catch up.
|
|
213
|
+
if (textBlock?.text && textBlock.text.startsWith(output.response ?? ''))
|
|
214
|
+
return state;
|
|
151
215
|
const newContent = textBlock
|
|
152
216
|
? target.content.map(c => c.type === 'text' ? { ...c, text: output.response } : c)
|
|
153
217
|
: [{ type: 'text', text: output.response }, ...target.content];
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -261,6 +261,7 @@ export type ChatAction = {
|
|
|
261
261
|
} | {
|
|
262
262
|
type: 'UPDATE_CHAT';
|
|
263
263
|
payload: ChatDTO | null;
|
|
264
|
+
fields?: string[];
|
|
264
265
|
} | {
|
|
265
266
|
type: 'MERGE_CHAT_SETTINGS';
|
|
266
267
|
payload: ChatSettingsDTO;
|
|
@@ -270,6 +271,7 @@ export type ChatAction = {
|
|
|
270
271
|
} | {
|
|
271
272
|
type: 'UPDATE_ACTIVE_RUN';
|
|
272
273
|
payload: AgentRunDTO;
|
|
274
|
+
fields?: string[];
|
|
273
275
|
} | {
|
|
274
276
|
type: 'SET_MESSAGES';
|
|
275
277
|
payload: ChatMessageDTO[];
|
package/dist/api/agents.js
CHANGED
|
@@ -330,9 +330,9 @@ export class Agent {
|
|
|
330
330
|
// fetched chat never carries chat_messages, so their absence cannot tell
|
|
331
331
|
// the two apart.
|
|
332
332
|
const unchanged = {};
|
|
333
|
-
return new Promise((resolve) => {
|
|
333
|
+
return new Promise((resolve, reject) => {
|
|
334
334
|
this.poller?.stop();
|
|
335
|
-
|
|
335
|
+
const poller = new PollManager({
|
|
336
336
|
pollFunction: async () => {
|
|
337
337
|
// Lightweight status check first
|
|
338
338
|
const statusResp = await this.http.request('get', `/chats/${this.chatId}/status`);
|
|
@@ -391,8 +391,19 @@ export class Agent {
|
|
|
391
391
|
onError: (error) => {
|
|
392
392
|
console.warn('[Agent] Poll error:', error);
|
|
393
393
|
},
|
|
394
|
+
// PollManager gave up after maxRetries consecutive errors: it has
|
|
395
|
+
// already stopped polling, so fail the turn once. A caller stop
|
|
396
|
+
// (disconnect, abort, a newer turn) passes no error.
|
|
397
|
+
onStop: (error) => {
|
|
398
|
+
if (!error)
|
|
399
|
+
return;
|
|
400
|
+
if (this.poller === poller)
|
|
401
|
+
this.poller = null;
|
|
402
|
+
reject(error);
|
|
403
|
+
},
|
|
394
404
|
});
|
|
395
|
-
this.poller
|
|
405
|
+
this.poller = poller;
|
|
406
|
+
poller.start();
|
|
396
407
|
});
|
|
397
408
|
}
|
|
398
409
|
}
|
package/dist/api/engines.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HttpClient } from '../http/client.js';
|
|
2
2
|
import type { Response } from '../http/response.js';
|
|
3
3
|
import type { EngineUpdateBody } from './write-bodies.js';
|
|
4
|
-
import { EngineDTO as Engine, CursorListRequest, CursorListResponse } from '../types.js';
|
|
4
|
+
import { EngineDTO as Engine, EngineReleasesResponse, CursorListRequest, CursorListResponse } from '../types.js';
|
|
5
5
|
/**
|
|
6
6
|
* Engines API
|
|
7
7
|
*/
|
|
@@ -65,8 +65,16 @@ export declare class EnginesAPI {
|
|
|
65
65
|
*/
|
|
66
66
|
drain(engineId: string): Promise<Response<void>>;
|
|
67
67
|
/**
|
|
68
|
-
* Update an engine binary
|
|
68
|
+
* Update an engine binary: it drains, installs the release and restarts.
|
|
69
|
+
* `version` is "stable" (the default: newest stable, lifting any pin),
|
|
70
|
+
* "canary" (the current canary build, pinned), or a version such as
|
|
71
|
+
* v1.9.3 (pinned). A pinned engine stays on its version until sent
|
|
72
|
+
* "stable" again.
|
|
69
73
|
*/
|
|
70
|
-
updateBinary(engineId: string): Promise<Response<void>>;
|
|
74
|
+
updateBinary(engineId: string, version?: string): Promise<Response<void>>;
|
|
75
|
+
/**
|
|
76
|
+
* The head of each engine release channel (stable, canary) on dist.inference.sh.
|
|
77
|
+
*/
|
|
78
|
+
releases(): Promise<Response<EngineReleasesResponse>>;
|
|
71
79
|
}
|
|
72
80
|
export declare function createEnginesAPI(http: HttpClient): EnginesAPI;
|
package/dist/api/engines.js
CHANGED
|
@@ -85,10 +85,21 @@ export class EnginesAPI {
|
|
|
85
85
|
return this.http.request('post', `/engines/${engineId}/drain`);
|
|
86
86
|
}
|
|
87
87
|
/**
|
|
88
|
-
* Update an engine binary
|
|
88
|
+
* Update an engine binary: it drains, installs the release and restarts.
|
|
89
|
+
* `version` is "stable" (the default: newest stable, lifting any pin),
|
|
90
|
+
* "canary" (the current canary build, pinned), or a version such as
|
|
91
|
+
* v1.9.3 (pinned). A pinned engine stays on its version until sent
|
|
92
|
+
* "stable" again.
|
|
89
93
|
*/
|
|
90
|
-
async updateBinary(engineId) {
|
|
91
|
-
|
|
94
|
+
async updateBinary(engineId, version) {
|
|
95
|
+
const body = version ? { version } : {};
|
|
96
|
+
return this.http.request('post', `/engines/${engineId}/update`, { data: body });
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The head of each engine release channel (stable, canary) on dist.inference.sh.
|
|
100
|
+
*/
|
|
101
|
+
async releases() {
|
|
102
|
+
return this.http.request('get', '/engines/releases');
|
|
92
103
|
}
|
|
93
104
|
}
|
|
94
105
|
export function createEnginesAPI(http) {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* chats, engines and teams send PATCH; apps.patch and flows.patch are the
|
|
13
13
|
* partial siblings of the POST updates that also edit a version.
|
|
14
14
|
*/
|
|
15
|
-
import type { AgentConfigInput,
|
|
15
|
+
import type { AgentConfigInput, ResourceImages, AppDTO, ChatDTO, CredentialRequirements, EngineDTO, FlowDTO, FlowVersionDTO, KnowledgeDTO, ProjectDTO, TeamDTO, Visibility } from '../types.js';
|
|
16
16
|
/**
|
|
17
17
|
* POST /agents/{id}. Visibility and images, and a new version when
|
|
18
18
|
* `version` is set. Name, title, harness, placement: set at creation.
|
|
@@ -20,7 +20,7 @@ import type { AgentConfigInput, AgentImages, AppDTO, ChatDTO, CredentialRequirem
|
|
|
20
20
|
*/
|
|
21
21
|
export interface AgentUpdateBody {
|
|
22
22
|
visibility?: Visibility;
|
|
23
|
-
images?:
|
|
23
|
+
images?: ResourceImages;
|
|
24
24
|
version?: AgentConfigInput;
|
|
25
25
|
}
|
|
26
26
|
/**
|
package/dist/http/client.js
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
import { InferenceError, RequirementsNotMetException } from './errors.js';
|
|
2
2
|
import { EventSource } from 'eventsource';
|
|
3
3
|
import { SDK_VERSION } from '../version.js';
|
|
4
|
+
/** How long to wait before each new try of a read that got no response. */
|
|
5
|
+
const NETWORK_RETRY_DELAYS_MS = [300, 1000];
|
|
6
|
+
/**
|
|
7
|
+
* fetch, sending a GET or HEAD that got no response again after each of
|
|
8
|
+
* NETWORK_RETRY_DELAYS_MS: a dropped connection or a network change fails a
|
|
9
|
+
* read that would succeed a moment later, and a read changes nothing on the
|
|
10
|
+
* server, so sending it again is safe. fetch rejects with a TypeError only
|
|
11
|
+
* when no response came; a response of any status, an abort, or a request
|
|
12
|
+
* of another method is the caller's at once.
|
|
13
|
+
*/
|
|
14
|
+
function fetchRetryingReads(input, init, attempt = 0) {
|
|
15
|
+
const method = (init.method ?? 'GET').toUpperCase();
|
|
16
|
+
const read = method === 'GET' || method === 'HEAD';
|
|
17
|
+
const sent = fetch(input, init);
|
|
18
|
+
if (!read)
|
|
19
|
+
return sent;
|
|
20
|
+
return sent.catch(async (error) => {
|
|
21
|
+
const delay = NETWORK_RETRY_DELAYS_MS[attempt];
|
|
22
|
+
if (delay === undefined || !(error instanceof TypeError) || init.signal?.aborted)
|
|
23
|
+
throw error;
|
|
24
|
+
await wait(delay, init.signal);
|
|
25
|
+
return fetchRetryingReads(input, init, attempt + 1);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/** Resolves after ms, or rejects with the abort when signal aborts first. */
|
|
29
|
+
function wait(ms, signal) {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
const timer = setTimeout(resolve, ms);
|
|
32
|
+
signal?.addEventListener('abort', () => {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
reject(signal.reason);
|
|
35
|
+
}, { once: true });
|
|
36
|
+
});
|
|
37
|
+
}
|
|
4
38
|
/**
|
|
5
39
|
* Low-level HTTP client for inference.sh API
|
|
6
40
|
*
|
|
@@ -127,7 +161,7 @@ export class HttpClient {
|
|
|
127
161
|
* (`refused: 'return'`), handed back with its body unread.
|
|
128
162
|
*/
|
|
129
163
|
async fetchHandled(url, targetUrl, init, refused) {
|
|
130
|
-
const send = (token) =>
|
|
164
|
+
const send = (token) => fetchRetryingReads(url, {
|
|
131
165
|
...init,
|
|
132
166
|
headers: { ...init.headers, ...this.requestHeaders(targetUrl, token) },
|
|
133
167
|
credentials: this.credentials,
|
|
@@ -213,7 +247,7 @@ export class HttpClient {
|
|
|
213
247
|
if (options.data) {
|
|
214
248
|
fetchOptions.body = JSON.stringify(options.data);
|
|
215
249
|
}
|
|
216
|
-
const response = await
|
|
250
|
+
const response = await fetchRetryingReads(fetchUrl, fetchOptions);
|
|
217
251
|
const responseText = await response.text();
|
|
218
252
|
let data = null;
|
|
219
253
|
try {
|
package/dist/http/poll.d.ts
CHANGED
|
@@ -19,8 +19,12 @@ export interface PollManagerOptions<T> {
|
|
|
19
19
|
onError?: (error: Error) => void;
|
|
20
20
|
/** Called when polling starts */
|
|
21
21
|
onStart?: () => void;
|
|
22
|
-
/**
|
|
23
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Called once when polling stops. `error` is the last poll error when the
|
|
24
|
+
* manager gave up after `maxRetries` consecutive errors; it is undefined
|
|
25
|
+
* when the caller stopped it.
|
|
26
|
+
*/
|
|
27
|
+
onStop?: (error?: Error) => void;
|
|
24
28
|
}
|
|
25
29
|
export declare class PollManager<T> {
|
|
26
30
|
private options;
|
|
@@ -34,6 +38,7 @@ export declare class PollManager<T> {
|
|
|
34
38
|
start(): void;
|
|
35
39
|
/** Stop polling and clean up. */
|
|
36
40
|
stop(): void;
|
|
41
|
+
private halt;
|
|
37
42
|
private cleanup;
|
|
38
43
|
private poll;
|
|
39
44
|
}
|
package/dist/http/poll.js
CHANGED
|
@@ -30,11 +30,14 @@ export class PollManager {
|
|
|
30
30
|
}
|
|
31
31
|
/** Stop polling and clean up. */
|
|
32
32
|
stop() {
|
|
33
|
+
this.halt();
|
|
34
|
+
}
|
|
35
|
+
halt(error) {
|
|
33
36
|
if (this.isStopped)
|
|
34
37
|
return;
|
|
35
38
|
this.isStopped = true;
|
|
36
39
|
this.cleanup();
|
|
37
|
-
this.options.onStop?.();
|
|
40
|
+
this.options.onStop?.(error);
|
|
38
41
|
}
|
|
39
42
|
cleanup() {
|
|
40
43
|
if (this.interval) {
|
|
@@ -66,7 +69,7 @@ export class PollManager {
|
|
|
66
69
|
this.consecutiveErrors++;
|
|
67
70
|
this.options.onError?.(error);
|
|
68
71
|
if (this.consecutiveErrors >= this.options.maxRetries) {
|
|
69
|
-
this.
|
|
72
|
+
this.halt(error);
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
}
|