@inferencesh/sdk 0.6.8 → 0.6.12

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.
Files changed (76) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README.md +70 -1
  3. package/dist/agent/actions.js +3 -3
  4. package/dist/agent/actions.test.js +89 -0
  5. package/dist/agent/api.test.js +86 -8
  6. package/dist/api/agents.d.ts +10 -0
  7. package/dist/api/agents.js +17 -3
  8. package/dist/api/agents.test.js +303 -92
  9. package/dist/api/api-keys.d.ts +24 -0
  10. package/dist/api/api-keys.js +26 -0
  11. package/dist/api/api-keys.test.d.ts +1 -0
  12. package/dist/api/api-keys.test.js +44 -0
  13. package/dist/api/apps.js +1 -1
  14. package/dist/api/apps.test.d.ts +1 -0
  15. package/dist/api/apps.test.js +135 -0
  16. package/dist/api/chats.d.ts +14 -0
  17. package/dist/api/chats.js +18 -0
  18. package/dist/api/chats.test.d.ts +1 -0
  19. package/dist/api/chats.test.js +85 -0
  20. package/dist/api/engines.d.ts +12 -0
  21. package/dist/api/engines.js +18 -0
  22. package/dist/api/engines.test.d.ts +1 -0
  23. package/dist/api/engines.test.js +133 -0
  24. package/dist/api/files.test.js +186 -6
  25. package/dist/api/flow-runs.test.d.ts +1 -0
  26. package/dist/api/flow-runs.test.js +97 -0
  27. package/dist/api/flows.d.ts +4 -0
  28. package/dist/api/flows.js +6 -0
  29. package/dist/api/flows.test.d.ts +1 -0
  30. package/dist/api/flows.test.js +118 -0
  31. package/dist/api/integrations.d.ts +41 -0
  32. package/dist/api/integrations.js +56 -0
  33. package/dist/api/integrations.test.d.ts +1 -0
  34. package/dist/api/integrations.test.js +109 -0
  35. package/dist/api/knowledge.d.ts +112 -0
  36. package/dist/api/knowledge.js +163 -0
  37. package/dist/api/knowledge.test.d.ts +1 -0
  38. package/dist/api/knowledge.test.js +94 -0
  39. package/dist/api/mcp-servers.d.ts +45 -0
  40. package/dist/api/mcp-servers.js +62 -0
  41. package/dist/api/mcp-servers.test.d.ts +1 -0
  42. package/dist/api/mcp-servers.test.js +64 -0
  43. package/dist/api/projects.d.ts +29 -0
  44. package/dist/api/projects.js +38 -0
  45. package/dist/api/projects.test.d.ts +1 -0
  46. package/dist/api/projects.test.js +52 -0
  47. package/dist/api/search.d.ts +21 -0
  48. package/dist/api/search.js +20 -0
  49. package/dist/api/search.test.d.ts +1 -0
  50. package/dist/api/search.test.js +39 -0
  51. package/dist/api/secrets.d.ts +29 -0
  52. package/dist/api/secrets.js +38 -0
  53. package/dist/api/secrets.test.d.ts +1 -0
  54. package/dist/api/secrets.test.js +61 -0
  55. package/dist/api/sessions.test.js +4 -4
  56. package/dist/api/tasks.d.ts +13 -1
  57. package/dist/api/tasks.js +18 -0
  58. package/dist/api/tasks.test.js +174 -22
  59. package/dist/api/teams.d.ts +71 -0
  60. package/dist/api/teams.js +92 -0
  61. package/dist/api/teams.test.d.ts +1 -0
  62. package/dist/api/teams.test.js +79 -0
  63. package/dist/client.test.js +8 -8
  64. package/dist/http/client.d.ts +5 -0
  65. package/dist/http/client.js +46 -48
  66. package/dist/http/client.test.js +296 -13
  67. package/dist/http/errors.test.js +13 -0
  68. package/dist/index.d.ts +25 -0
  69. package/dist/index.js +25 -0
  70. package/dist/proxy/express.test.d.ts +1 -0
  71. package/dist/proxy/express.test.js +106 -0
  72. package/dist/proxy/index.test.js +10 -1
  73. package/dist/tool-builder.test.js +11 -1
  74. package/dist/types.d.ts +793 -23
  75. package/dist/types.js +180 -8
  76. package/package.json +4 -4
@@ -0,0 +1,135 @@
1
+ import { HttpClient } from '../http/client';
2
+ import { AppsAPI } from './apps';
3
+ const mockFetch = jest.fn();
4
+ global.fetch = mockFetch;
5
+ function mockJsonResponse(body) {
6
+ mockFetch.mockResolvedValueOnce({
7
+ ok: true,
8
+ status: 200,
9
+ text: () => Promise.resolve(JSON.stringify(body)),
10
+ });
11
+ }
12
+ describe('AppsAPI', () => {
13
+ beforeEach(() => {
14
+ jest.clearAllMocks();
15
+ });
16
+ const api = () => new AppsAPI(new HttpClient({ apiKey: 'test-key' }));
17
+ it('should POST /apps/list for list()', async () => {
18
+ const apps = { items: [{ id: 'app-1' }], next_cursor: null };
19
+ mockJsonResponse(apps);
20
+ const result = await api().list({ limit: 10 });
21
+ expect(result).toEqual(apps);
22
+ const [url, init] = mockFetch.mock.calls[0];
23
+ expect(url).toContain('/apps/list');
24
+ expect(init.method).toBe('POST');
25
+ expect(JSON.parse(init.body)).toEqual({ limit: 10 });
26
+ });
27
+ it('should GET /apps/{name} for getByName()', async () => {
28
+ const app = { id: 'app-1', name: 'inference/claude-haiku' };
29
+ mockJsonResponse(app);
30
+ const result = await api().getByName('inference/claude-haiku');
31
+ expect(result).toEqual(app);
32
+ const [url] = mockFetch.mock.calls[0];
33
+ expect(url).toContain('/apps/inference/claude-haiku');
34
+ });
35
+ it('should POST transfer with team_id for transferOwnership()', async () => {
36
+ const app = { id: 'app-1' };
37
+ mockJsonResponse(app);
38
+ await api().transferOwnership('app-1', 'team-99');
39
+ const [url, init] = mockFetch.mock.calls[0];
40
+ expect(url).toContain('/apps/app-1/transfer');
41
+ expect(JSON.parse(init.body)).toEqual({ team_id: 'team-99' });
42
+ });
43
+ it('should POST license payload for saveLicense()', async () => {
44
+ const license = { app_id: 'app-1', license: 'key-abc' };
45
+ mockJsonResponse(license);
46
+ const result = await api().saveLicense('app-1', 'key-abc');
47
+ expect(result).toEqual(license);
48
+ const [, init] = mockFetch.mock.calls[0];
49
+ expect(JSON.parse(init.body)).toEqual({ license: 'key-abc' });
50
+ });
51
+ it('should PUT /apps/{id}/versions/{versionId}/current for setCurrentVersion()', async () => {
52
+ const app = { id: 'app-1', current_version_id: 'ver-2' };
53
+ mockJsonResponse(app);
54
+ await api().setCurrentVersion('app-1', 'ver-2');
55
+ const [url, init] = mockFetch.mock.calls[0];
56
+ expect(url).toContain('/apps/app-1/versions/ver-2/current');
57
+ expect(init.method).toBe('PUT');
58
+ });
59
+ it('should POST /apps/{id}/duplicate for duplicate()', async () => {
60
+ const app = { id: 'app-copy' };
61
+ mockJsonResponse(app);
62
+ const result = await api().duplicate('app-1');
63
+ expect(result).toEqual(app);
64
+ const [url, init] = mockFetch.mock.calls[0];
65
+ expect(url).toContain('/apps/app-1/duplicate');
66
+ expect(init.method).toBe('POST');
67
+ });
68
+ it('should GET /apps/{id} for get()', async () => {
69
+ const app = { id: 'app-1', name: 'demo' };
70
+ mockJsonResponse(app);
71
+ const result = await api().get('app-1');
72
+ expect(result).toEqual(app);
73
+ const [url, init] = mockFetch.mock.calls[0];
74
+ expect(url).toContain('/apps/app-1');
75
+ expect(init.method).toBe('GET');
76
+ });
77
+ it('should GET versioned app for getByVersionId()', async () => {
78
+ const app = { id: 'app-1', version_id: 'ver-1' };
79
+ mockJsonResponse(app);
80
+ const result = await api().getByVersionId('app-1', 'ver-1');
81
+ expect(result).toEqual(app);
82
+ const [url] = mockFetch.mock.calls[0];
83
+ expect(url).toContain('/apps/app-1/versions/ver-1');
84
+ });
85
+ it('should POST /apps for create()', async () => {
86
+ const app = { id: 'app-new', name: 'New App' };
87
+ mockJsonResponse(app);
88
+ const result = await api().create({ name: 'New App' });
89
+ expect(result).toEqual(app);
90
+ const [url, init] = mockFetch.mock.calls[0];
91
+ expect(url).toContain('/apps');
92
+ expect(init.method).toBe('POST');
93
+ expect(JSON.parse(init.body)).toEqual({ name: 'New App' });
94
+ });
95
+ it('should POST /apps/{id} for update()', async () => {
96
+ const app = { id: 'app-1', description: 'updated' };
97
+ mockJsonResponse(app);
98
+ const result = await api().update('app-1', { description: 'updated' });
99
+ expect(result).toEqual(app);
100
+ const [url, init] = mockFetch.mock.calls[0];
101
+ expect(url).toContain('/apps/app-1');
102
+ expect(JSON.parse(init.body)).toEqual({ description: 'updated' });
103
+ });
104
+ it('should DELETE /apps/{id} for delete()', async () => {
105
+ mockJsonResponse(null);
106
+ await api().delete('app-1');
107
+ const [url, init] = mockFetch.mock.calls[0];
108
+ expect(url).toContain('/apps/app-1');
109
+ expect(init.method).toBe('DELETE');
110
+ });
111
+ it('should POST /apps/{id}/versions/list for listVersions()', async () => {
112
+ const versions = { items: [{ id: 'ver-1' }], next_cursor: null };
113
+ mockJsonResponse(versions);
114
+ const result = await api().listVersions('app-1', { limit: 20 });
115
+ expect(result).toEqual(versions);
116
+ const [url, init] = mockFetch.mock.calls[0];
117
+ expect(url).toContain('/apps/app-1/versions/list');
118
+ expect(JSON.parse(init.body)).toEqual({ limit: 20 });
119
+ });
120
+ it('should POST visibility for updateVisibility()', async () => {
121
+ const app = { id: 'app-1', visibility: 'private' };
122
+ mockJsonResponse(app);
123
+ await api().updateVisibility('app-1', 'private');
124
+ const [, init] = mockFetch.mock.calls[0];
125
+ expect(JSON.parse(init.body)).toEqual({ visibility: 'private' });
126
+ });
127
+ it('should GET /apps/{id}/license for getLicense()', async () => {
128
+ const license = { app_id: 'app-1', license: 'MIT' };
129
+ mockJsonResponse(license);
130
+ const result = await api().getLicense('app-1');
131
+ expect(result).toEqual(license);
132
+ const [url] = mockFetch.mock.calls[0];
133
+ expect(url).toContain('/apps/app-1/license');
134
+ });
135
+ });
@@ -26,5 +26,19 @@ export declare class ChatsAPI {
26
26
  * Get chat trace (for debugging/observability)
27
27
  */
28
28
  getTrace(chatId: string): Promise<ChatTraceDTO>;
29
+ /**
30
+ * Get chat status
31
+ */
32
+ getStatus(chatId: string): Promise<{
33
+ status: string;
34
+ }>;
35
+ /**
36
+ * Stop chat generation
37
+ */
38
+ stop(chatId: string): Promise<void>;
39
+ /**
40
+ * Stream chat updates
41
+ */
42
+ stream(chatId: string): Promise<import("eventsource").EventSource | null>;
29
43
  }
30
44
  export declare function createChatsAPI(http: HttpClient): ChatsAPI;
package/dist/api/chats.js CHANGED
@@ -35,6 +35,24 @@ export class ChatsAPI {
35
35
  async getTrace(chatId) {
36
36
  return this.http.request('get', `/chats/${chatId}/trace`);
37
37
  }
38
+ /**
39
+ * Get chat status
40
+ */
41
+ async getStatus(chatId) {
42
+ return this.http.request('get', `/chats/${chatId}/status`);
43
+ }
44
+ /**
45
+ * Stop chat generation
46
+ */
47
+ async stop(chatId) {
48
+ return this.http.request('post', `/chats/${chatId}/stop`);
49
+ }
50
+ /**
51
+ * Stream chat updates
52
+ */
53
+ stream(chatId) {
54
+ return this.http.createEventSource(`/chats/${chatId}/stream`);
55
+ }
38
56
  }
39
57
  export function createChatsAPI(http) {
40
58
  return new ChatsAPI(http);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,85 @@
1
+ import { HttpClient } from '../http/client';
2
+ import { ChatsAPI } from './chats';
3
+ const mockFetch = jest.fn();
4
+ global.fetch = mockFetch;
5
+ function mockJsonResponse(body) {
6
+ mockFetch.mockResolvedValueOnce({
7
+ ok: true,
8
+ status: 200,
9
+ text: () => Promise.resolve(JSON.stringify(body)),
10
+ });
11
+ }
12
+ describe('ChatsAPI', () => {
13
+ beforeEach(() => {
14
+ jest.clearAllMocks();
15
+ });
16
+ const api = () => new ChatsAPI(new HttpClient({ apiKey: 'test-key' }));
17
+ it('should GET /chats/{id}/trace for getTrace()', async () => {
18
+ const trace = { chat_id: 'chat-1', spans: [] };
19
+ mockJsonResponse(trace);
20
+ const result = await api().getTrace('chat-1');
21
+ expect(result).toEqual(trace);
22
+ const [url, init] = mockFetch.mock.calls[0];
23
+ expect(url).toContain('/chats/chat-1/trace');
24
+ expect(init.method).toBe('GET');
25
+ });
26
+ it('should DELETE /chats/{id} for delete()', async () => {
27
+ mockJsonResponse(null);
28
+ await api().delete('chat-9');
29
+ const [url, init] = mockFetch.mock.calls[0];
30
+ expect(url).toContain('/chats/chat-9');
31
+ expect(init.method).toBe('DELETE');
32
+ });
33
+ it('should POST /chats/list for list()', async () => {
34
+ const page = { items: [{ id: 'chat-1' }], next_cursor: null };
35
+ mockJsonResponse(page);
36
+ const result = await api().list({ limit: 25 });
37
+ expect(result).toEqual(page);
38
+ const [url, init] = mockFetch.mock.calls[0];
39
+ expect(url).toContain('/chats/list');
40
+ expect(init.method).toBe('POST');
41
+ expect(JSON.parse(init.body)).toEqual({ limit: 25 });
42
+ });
43
+ it('should GET /chats/{id} for get()', async () => {
44
+ const chat = { id: 'chat-1', status: 'open' };
45
+ mockJsonResponse(chat);
46
+ const result = await api().get('chat-1');
47
+ expect(result).toEqual(chat);
48
+ const [url, init] = mockFetch.mock.calls[0];
49
+ expect(url).toContain('/chats/chat-1');
50
+ expect(init.method).toBe('GET');
51
+ });
52
+ it('should POST /chats/{id} for update()', async () => {
53
+ const chat = { id: 'chat-1', name: 'Renamed' };
54
+ mockJsonResponse(chat);
55
+ const result = await api().update('chat-1', { name: 'Renamed' });
56
+ expect(result).toEqual(chat);
57
+ const [, init] = mockFetch.mock.calls[0];
58
+ expect(JSON.parse(init.body)).toEqual({ name: 'Renamed' });
59
+ });
60
+ it('should GET /chats/{id}/status for getStatus()', async () => {
61
+ mockJsonResponse({ status: 'busy' });
62
+ const result = await api().getStatus('chat-1');
63
+ expect(result).toEqual({ status: 'busy' });
64
+ const [url, init] = mockFetch.mock.calls[0];
65
+ expect(url).toContain('/chats/chat-1/status');
66
+ expect(init.method).toBe('GET');
67
+ });
68
+ it('should POST /chats/{id}/stop for stop()', async () => {
69
+ mockJsonResponse(null);
70
+ await api().stop('chat-1');
71
+ const [url, init] = mockFetch.mock.calls[0];
72
+ expect(url).toContain('/chats/chat-1/stop');
73
+ expect(init.method).toBe('POST');
74
+ });
75
+ it('should open SSE on /chats/{id}/stream for stream()', async () => {
76
+ const http = new HttpClient({ apiKey: 'test-key' });
77
+ const createEventSource = jest
78
+ .spyOn(http, 'createEventSource')
79
+ .mockResolvedValue(null);
80
+ const chats = new ChatsAPI(http);
81
+ await chats.stream('chat-42');
82
+ expect(createEventSource).toHaveBeenCalledWith('/chats/chat-42/stream');
83
+ createEventSource.mockRestore();
84
+ });
85
+ });
@@ -53,5 +53,17 @@ export declare class EnginesAPI {
53
53
  * Transfer engine ownership
54
54
  */
55
55
  transferOwnership(engineId: string, newTeamId: string): Promise<Engine>;
56
+ /**
57
+ * Extend engine duration
58
+ */
59
+ extend(engineId: string): Promise<void>;
60
+ /**
61
+ * Drain an engine
62
+ */
63
+ drain(engineId: string): Promise<void>;
64
+ /**
65
+ * Update an engine binary (drain + restart with new version)
66
+ */
67
+ updateBinary(engineId: string): Promise<void>;
56
68
  }
57
69
  export declare function createEnginesAPI(http: HttpClient): EnginesAPI;
@@ -71,6 +71,24 @@ export class EnginesAPI {
71
71
  async transferOwnership(engineId, newTeamId) {
72
72
  return this.http.request('post', `/engines/${engineId}/transfer`, { data: { team_id: newTeamId } });
73
73
  }
74
+ /**
75
+ * Extend engine duration
76
+ */
77
+ async extend(engineId) {
78
+ return this.http.request('post', `/engines/${engineId}/extend`);
79
+ }
80
+ /**
81
+ * Drain an engine
82
+ */
83
+ async drain(engineId) {
84
+ return this.http.request('post', `/engines/${engineId}/drain`);
85
+ }
86
+ /**
87
+ * Update an engine binary (drain + restart with new version)
88
+ */
89
+ async updateBinary(engineId) {
90
+ return this.http.request('post', `/engines/${engineId}/update`);
91
+ }
74
92
  }
75
93
  export function createEnginesAPI(http) {
76
94
  return new EnginesAPI(http);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,133 @@
1
+ import { HttpClient } from '../http/client';
2
+ import { EnginesAPI } from './engines';
3
+ const mockFetch = jest.fn();
4
+ global.fetch = mockFetch;
5
+ function mockJsonResponse(body) {
6
+ mockFetch.mockResolvedValueOnce({
7
+ ok: true,
8
+ status: 200,
9
+ text: () => Promise.resolve(JSON.stringify(body)),
10
+ });
11
+ }
12
+ describe('EnginesAPI', () => {
13
+ beforeEach(() => {
14
+ jest.clearAllMocks();
15
+ });
16
+ const api = () => new EnginesAPI(new HttpClient({ apiKey: 'test-key' }));
17
+ it('should POST resource ids for getForResources()', async () => {
18
+ const engines = [{ id: 'eng-1' }];
19
+ mockJsonResponse(engines);
20
+ const result = await api().getForResources({
21
+ app_ids: ['app-1'],
22
+ agent_ids: ['agent-1'],
23
+ });
24
+ expect(result).toEqual(engines);
25
+ const [url, init] = mockFetch.mock.calls[0];
26
+ expect(url).toContain('/engines/resources');
27
+ expect(JSON.parse(init.body)).toEqual({
28
+ app_ids: ['app-1'],
29
+ agent_ids: ['agent-1'],
30
+ });
31
+ });
32
+ it('should POST /engines/{id}/stop for stop()', async () => {
33
+ mockJsonResponse(null);
34
+ await api().stop('eng-1');
35
+ const [url, init] = mockFetch.mock.calls[0];
36
+ expect(url).toContain('/engines/eng-1/stop');
37
+ expect(init.method).toBe('POST');
38
+ });
39
+ it('should POST /engines/{id}/restart for restart()', async () => {
40
+ mockJsonResponse(null);
41
+ await api().restart('eng-1');
42
+ const [url] = mockFetch.mock.calls[0];
43
+ expect(url).toContain('/engines/eng-1/restart');
44
+ });
45
+ it('should open SSE on /engines/{id}/stream for stream()', async () => {
46
+ const http = new HttpClient({ apiKey: 'test-key' });
47
+ const createEventSource = jest
48
+ .spyOn(http, 'createEventSource')
49
+ .mockResolvedValue(null);
50
+ const engines = new EnginesAPI(http);
51
+ await engines.stream('eng-7');
52
+ expect(createEventSource).toHaveBeenCalledWith('/engines/eng-7/stream');
53
+ createEventSource.mockRestore();
54
+ });
55
+ it('should POST /engines/list for list()', async () => {
56
+ const page = { items: [{ id: 'eng-1' }], next_cursor: null };
57
+ mockJsonResponse(page);
58
+ const result = await api().list();
59
+ expect(result).toEqual(page);
60
+ const [url, init] = mockFetch.mock.calls[0];
61
+ expect(url).toContain('/engines/list');
62
+ expect(init.method).toBe('POST');
63
+ });
64
+ it('should GET /engines/{id} for get()', async () => {
65
+ const engine = { id: 'eng-1' };
66
+ mockJsonResponse(engine);
67
+ const result = await api().get('eng-1');
68
+ expect(result).toEqual(engine);
69
+ const [url, init] = mockFetch.mock.calls[0];
70
+ expect(url).toContain('/engines/eng-1');
71
+ expect(init.method).toBe('GET');
72
+ });
73
+ it('should POST /engines for create()', async () => {
74
+ const engine = { id: 'eng-new', name: 'worker' };
75
+ mockJsonResponse(engine);
76
+ const result = await api().create({ name: 'worker' });
77
+ expect(result).toEqual(engine);
78
+ const [url, init] = mockFetch.mock.calls[0];
79
+ expect(url).toContain('/engines');
80
+ expect(init.method).toBe('POST');
81
+ expect(JSON.parse(init.body)).toEqual({ name: 'worker' });
82
+ });
83
+ it('should POST /engines/{id} for update()', async () => {
84
+ const engine = { id: 'eng-1', name: 'updated' };
85
+ mockJsonResponse(engine);
86
+ const result = await api().update('eng-1', { name: 'updated' });
87
+ expect(result).toEqual(engine);
88
+ const [, init] = mockFetch.mock.calls[0];
89
+ expect(JSON.parse(init.body)).toEqual({ name: 'updated' });
90
+ });
91
+ it('should DELETE /engines/{id} for delete()', async () => {
92
+ mockJsonResponse(null);
93
+ await api().delete('eng-1');
94
+ const [url, init] = mockFetch.mock.calls[0];
95
+ expect(url).toContain('/engines/eng-1');
96
+ expect(init.method).toBe('DELETE');
97
+ });
98
+ it('should POST visibility for updateVisibility()', async () => {
99
+ const engine = { id: 'eng-1', visibility: 'team' };
100
+ mockJsonResponse(engine);
101
+ await api().updateVisibility('eng-1', 'team');
102
+ const [, init] = mockFetch.mock.calls[0];
103
+ expect(JSON.parse(init.body)).toEqual({ visibility: 'team' });
104
+ });
105
+ it('should POST transfer with team_id for transferOwnership()', async () => {
106
+ const engine = { id: 'eng-1' };
107
+ mockJsonResponse(engine);
108
+ await api().transferOwnership('eng-1', 'team-7');
109
+ const [, init] = mockFetch.mock.calls[0];
110
+ expect(JSON.parse(init.body)).toEqual({ team_id: 'team-7' });
111
+ });
112
+ it('should POST /engines/{id}/extend for extend()', async () => {
113
+ mockJsonResponse(null);
114
+ await api().extend('eng-1');
115
+ const [url, init] = mockFetch.mock.calls[0];
116
+ expect(url).toContain('/engines/eng-1/extend');
117
+ expect(init.method).toBe('POST');
118
+ });
119
+ it('should POST /engines/{id}/drain for drain()', async () => {
120
+ mockJsonResponse(null);
121
+ await api().drain('eng-1');
122
+ const [url, init] = mockFetch.mock.calls[0];
123
+ expect(url).toContain('/engines/eng-1/drain');
124
+ expect(init.method).toBe('POST');
125
+ });
126
+ it('should POST /engines/{id}/update for updateBinary()', async () => {
127
+ mockJsonResponse(null);
128
+ await api().updateBinary('eng-1');
129
+ const [url, init] = mockFetch.mock.calls[0];
130
+ expect(url).toContain('/engines/eng-1/update');
131
+ expect(init.method).toBe('POST');
132
+ });
133
+ });