@ziggs-ai/api-client 0.1.3 → 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/README.md +13 -7
- package/dist/ConnectionManager.d.ts +46 -0
- package/dist/ConnectionManager.js +132 -0
- package/dist/http/AgentSearchClient.d.ts +36 -0
- package/dist/http/AgentSearchClient.js +72 -0
- package/dist/http/AgreementClient.d.ts +153 -0
- package/dist/http/AgreementClient.js +477 -0
- package/dist/http/ArtifactsClient.d.ts +48 -0
- package/dist/http/ArtifactsClient.js +90 -0
- package/dist/http/ChatClient.d.ts +34 -0
- package/dist/http/ChatClient.js +104 -0
- package/dist/http/ContextDiscoveryClient.d.ts +23 -0
- package/dist/http/ContextDiscoveryClient.js +35 -0
- package/dist/http/ContextReadClient.d.ts +33 -0
- package/dist/http/ContextReadClient.js +54 -0
- package/dist/http/MarketplaceClient.d.ts +19 -0
- package/dist/http/MarketplaceClient.js +72 -0
- package/dist/http/MessagesClient.d.ts +26 -0
- package/dist/http/MessagesClient.js +49 -0
- package/dist/http/ScopeClient.d.ts +33 -0
- package/dist/http/ScopeClient.js +39 -0
- package/dist/http/TaskClient.d.ts +75 -0
- package/dist/http/TaskClient.js +352 -0
- package/dist/http/TelemetryClient.d.ts +11 -0
- package/dist/http/TelemetryClient.js +53 -0
- package/dist/http/index.d.ts +16 -0
- package/dist/http/index.js +11 -0
- package/dist/index.d.ts +9 -0
- package/{src → dist}/index.js +2 -12
- package/dist/shared/runtimeLog.d.ts +14 -0
- package/dist/shared/runtimeLog.js +64 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.js +50 -0
- package/dist/utils/urlUtils.d.ts +2 -0
- package/dist/utils/urlUtils.js +8 -0
- package/dist/websocket/ControlSocket.d.ts +13 -0
- package/dist/websocket/ControlSocket.js +37 -0
- package/dist/websocket/WebSocketClient.d.ts +71 -0
- package/dist/websocket/WebSocketClient.js +233 -0
- package/dist/websocket/index.js +1 -0
- package/package.json +20 -7
- package/src/ConnectionManager.ts +172 -0
- package/src/http/AgentSearchClient.ts +115 -0
- package/src/http/AgreementClient.ts +721 -0
- package/src/http/ArtifactsClient.ts +133 -0
- package/src/http/ChatClient.ts +147 -0
- package/src/http/ContextDiscoveryClient.ts +52 -0
- package/src/http/ContextReadClient.ts +83 -0
- package/src/http/MarketplaceClient.ts +94 -0
- package/src/http/MessagesClient.ts +71 -0
- package/src/http/ScopeClient.ts +64 -0
- package/src/http/TaskClient.ts +450 -0
- package/src/http/{TelemetryClient.js → TelemetryClient.ts} +21 -7
- package/src/http/index.ts +26 -0
- package/src/index.ts +27 -0
- package/src/shared/runtimeLog.ts +68 -0
- package/src/types.ts +158 -0
- package/src/utils/urlUtils.ts +9 -0
- package/src/websocket/ControlSocket.ts +51 -0
- package/src/websocket/WebSocketClient.ts +315 -0
- package/src/websocket/index.ts +1 -0
- package/src/ConnectionManager.js +0 -179
- package/src/http/AgentSearchClient.js +0 -113
- package/src/http/ContextReader.js +0 -99
- package/src/http/ContextWriter.js +0 -98
- package/src/http/TaskClient.js +0 -612
- package/src/http/index.js +0 -6
- package/src/types.js +0 -28
- package/src/utils/urlUtils.js +0 -17
- package/src/websocket/ControlSocket.js +0 -55
- package/src/websocket/WebSocketClient.js +0 -318
- /package/{src/websocket/index.js → dist/websocket/index.d.ts} +0 -0
package/src/http/TaskClient.js
DELETED
|
@@ -1,612 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTTP client for the Tasks API.
|
|
3
|
-
*
|
|
4
|
-
* Every function returns a Task object matching the backend ITask shape:
|
|
5
|
-
* { taskId, description, chatId, agentId, executorId, payerId, contract,
|
|
6
|
-
* perspective, state, proposal, processing, deleted, result, errorMessage,
|
|
7
|
-
* createdAt, updatedAt, parentTaskId, rootTaskId, plan, history }
|
|
8
|
-
*
|
|
9
|
-
* ⚠️ SYNC: Field names must match backend/src/tasks/task-core.ts ITask interface.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import 'dotenv/config';
|
|
13
|
-
import { getBackendUrl } from '../utils/urlUtils.js';
|
|
14
|
-
|
|
15
|
-
const baseUrl = getBackendUrl();
|
|
16
|
-
const TASK_BASE_URL = `${baseUrl}/tasks`;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @typedef {{ operatorKey: string, agentId: string }} Creds
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
function buildHeaders(creds) {
|
|
23
|
-
const { operatorKey, agentId } = creds || {};
|
|
24
|
-
if (!operatorKey) {
|
|
25
|
-
throw new Error('operatorKey is required for task service requests');
|
|
26
|
-
}
|
|
27
|
-
if (!agentId) {
|
|
28
|
-
throw new Error('agentId is required for task service requests (operator-token impersonation)');
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
'content-type': 'application/json',
|
|
32
|
-
Authorization: `Bearer ${operatorKey}`,
|
|
33
|
-
'X-Agent-Id': agentId,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function assertCreds(creds, op) {
|
|
38
|
-
if (!creds?.operatorKey) throw new Error(`operatorKey is required for ${op}`);
|
|
39
|
-
if (!creds?.agentId) throw new Error(`agentId is required for ${op}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Parse error message from API response.
|
|
44
|
-
* Checks for details, error, or message fields in JSON response.
|
|
45
|
-
* Falls back to raw body or default message.
|
|
46
|
-
*/
|
|
47
|
-
function parseErrorMessage(responseBody, defaultMessage) {
|
|
48
|
-
if (!responseBody) return defaultMessage;
|
|
49
|
-
try {
|
|
50
|
-
const errorData = JSON.parse(responseBody);
|
|
51
|
-
return errorData.details || errorData.error || errorData.message || defaultMessage;
|
|
52
|
-
} catch {
|
|
53
|
-
return responseBody || defaultMessage;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function throwApiError(response, responseBody, defaultMessage) {
|
|
58
|
-
const errorMessage = parseErrorMessage(responseBody, defaultMessage);
|
|
59
|
-
const error = new Error(errorMessage);
|
|
60
|
-
error.status = response.status;
|
|
61
|
-
error.body = responseBody;
|
|
62
|
-
throw error;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Extract the Task object from an API response.
|
|
67
|
-
* Handles both shapes: `{ task: {...} }` (POST /tasks, PATCH) and direct task (GET, proposal endpoints).
|
|
68
|
-
* @returns {Object|null} The task object, or null if not found.
|
|
69
|
-
*/
|
|
70
|
-
function extractTask(data) {
|
|
71
|
-
if (!data) return null;
|
|
72
|
-
// Wrapped: { status: '...', task: { taskId, ... } }
|
|
73
|
-
if (data.task && data.task.taskId) return data.task;
|
|
74
|
-
// Direct: { taskId, description, ... }
|
|
75
|
-
if (data.taskId) return data;
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// ---------------------------------------------------------------------------
|
|
80
|
-
// CRUD
|
|
81
|
-
// ---------------------------------------------------------------------------
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Create a standalone task (state='active').
|
|
85
|
-
* POST /tasks
|
|
86
|
-
*
|
|
87
|
-
* @param {Object} taskData
|
|
88
|
-
* @param {string} taskData.description
|
|
89
|
-
* @param {string} [taskData.chatId]
|
|
90
|
-
* @param {string} [taskData.executorId]
|
|
91
|
-
* @param {string} [taskData.payerId]
|
|
92
|
-
* @param {string} [taskData.parentTaskId]
|
|
93
|
-
* @param {Object} [taskData.contract]
|
|
94
|
-
* @param {Object} [taskData.perspective]
|
|
95
|
-
* @param {Object} [taskData.plan]
|
|
96
|
-
* @param {string} operatorKey
|
|
97
|
-
* @returns {Promise<Object>} Task object
|
|
98
|
-
*/
|
|
99
|
-
export async function createTask(taskData, creds) {
|
|
100
|
-
if (!taskData) throw new Error('Task data is required for task creation');
|
|
101
|
-
assertCreds(creds, 'task creation');
|
|
102
|
-
|
|
103
|
-
const res = await fetch(`${TASK_BASE_URL}`, {
|
|
104
|
-
method: 'POST',
|
|
105
|
-
headers: buildHeaders(creds),
|
|
106
|
-
body: JSON.stringify(taskData),
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
if (!res.ok) {
|
|
110
|
-
const body = await res.text().catch(() => '');
|
|
111
|
-
throwApiError(res, body, `Task creation failed: ${res.status} ${res.statusText}`);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const data = await res.json().catch(() => null);
|
|
115
|
-
const task = extractTask(data);
|
|
116
|
-
if (!task) throw new Error('Invalid response: task data not found');
|
|
117
|
-
return task;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Get a single task by ID.
|
|
122
|
-
* GET /tasks/:taskId
|
|
123
|
-
*
|
|
124
|
-
* @param {string} taskId
|
|
125
|
-
* @param {string} operatorKey
|
|
126
|
-
* @returns {Promise<Object|null>} Task object or null
|
|
127
|
-
*/
|
|
128
|
-
export async function getTask(taskId, creds) {
|
|
129
|
-
if (!taskId) return null;
|
|
130
|
-
assertCreds(creds, 'task retrieval');
|
|
131
|
-
|
|
132
|
-
try {
|
|
133
|
-
const res = await fetch(`${TASK_BASE_URL}/${taskId}`, {
|
|
134
|
-
method: 'GET',
|
|
135
|
-
headers: buildHeaders(creds),
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
if (!res.ok) {
|
|
139
|
-
const body = await res.text().catch(() => '');
|
|
140
|
-
console.warn(`⚠️ Task get failed: ${res.status} ${res.statusText} ${body}`);
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const data = await res.json().catch(() => null);
|
|
145
|
-
return extractTask(data);
|
|
146
|
-
} catch (e) {
|
|
147
|
-
console.warn(`⚠️ Task get failed: ${e.message}`);
|
|
148
|
-
return null;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Update a task's state.
|
|
154
|
-
* PATCH /tasks/:taskId/state
|
|
155
|
-
*
|
|
156
|
-
* Valid transitions (enforced by backend):
|
|
157
|
-
* proposal → active | cancelled
|
|
158
|
-
* active → completed | failed | cancelled
|
|
159
|
-
*
|
|
160
|
-
* @param {string} taskId
|
|
161
|
-
* @param {'proposal'|'active'|'completed'|'failed'|'cancelled'} state
|
|
162
|
-
* @param {Object} [data]
|
|
163
|
-
* @param {*} [data.result]
|
|
164
|
-
* @param {string} [data.errorMessage]
|
|
165
|
-
* @param {string} operatorKey
|
|
166
|
-
* @returns {Promise<Object|null>} Updated task or null
|
|
167
|
-
*/
|
|
168
|
-
export async function updateTaskState(taskId, state, data = {}, creds) {
|
|
169
|
-
if (!taskId || !state) return null;
|
|
170
|
-
assertCreds(creds, 'task state update');
|
|
171
|
-
|
|
172
|
-
try {
|
|
173
|
-
const res = await fetch(`${TASK_BASE_URL}/${taskId}/state`, {
|
|
174
|
-
method: 'PATCH',
|
|
175
|
-
headers: buildHeaders(creds),
|
|
176
|
-
body: JSON.stringify({ state, ...data }),
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
if (!res.ok) {
|
|
180
|
-
const body = await res.text().catch(() => '');
|
|
181
|
-
console.warn(`⚠️ Task state update failed: ${res.status} ${res.statusText} ${body}`);
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const result = await res.json().catch(() => null);
|
|
186
|
-
return extractTask(result);
|
|
187
|
-
} catch (e) {
|
|
188
|
-
console.warn(`⚠️ Task state update failed: ${e.message}`);
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Get active tasks, optionally filtered by chatId and/or agentId.
|
|
195
|
-
* GET /tasks?state=active[&chatId=...][&agentId=...]
|
|
196
|
-
*
|
|
197
|
-
* @param {string|null} chatId
|
|
198
|
-
* @param {string} operatorKey
|
|
199
|
-
* @param {string|null} [agentId]
|
|
200
|
-
* @returns {Promise<Object[]>} Array of Task objects
|
|
201
|
-
*/
|
|
202
|
-
export async function getActiveTasks(chatId = null, creds, filterAgentId = null) {
|
|
203
|
-
assertCreds(creds, 'getting active tasks');
|
|
204
|
-
|
|
205
|
-
try {
|
|
206
|
-
const url = new URL(`${TASK_BASE_URL}`);
|
|
207
|
-
url.searchParams.set('state', 'active');
|
|
208
|
-
if (chatId) url.searchParams.set('chatId', chatId);
|
|
209
|
-
if (filterAgentId) url.searchParams.set('agentId', filterAgentId);
|
|
210
|
-
|
|
211
|
-
const res = await fetch(url.toString(), {
|
|
212
|
-
method: 'GET',
|
|
213
|
-
headers: buildHeaders(creds),
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
if (!res.ok) {
|
|
217
|
-
const body = await res.text().catch(() => '');
|
|
218
|
-
console.warn(`⚠️ Get active tasks failed: ${res.status} ${res.statusText} ${body}`);
|
|
219
|
-
return [];
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const data = await res.json().catch(() => null);
|
|
223
|
-
return Array.isArray(data?.tasks) ? data.tasks : [];
|
|
224
|
-
} catch (e) {
|
|
225
|
-
console.warn(`⚠️ Get active tasks failed: ${e.message}`);
|
|
226
|
-
return [];
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Acquire or release the atomic processing lock on a task.
|
|
232
|
-
* PATCH /tasks/:taskId/processing
|
|
233
|
-
*
|
|
234
|
-
* @param {string} taskId
|
|
235
|
-
* @param {boolean} processing - true to acquire, false to release
|
|
236
|
-
* @param {string} operatorKey
|
|
237
|
-
* @returns {Promise<{acquired: boolean, task: Object|null}>}
|
|
238
|
-
*/
|
|
239
|
-
export async function markTaskProcessing(taskId, processing, creds) {
|
|
240
|
-
if (!taskId) return { acquired: false, task: null };
|
|
241
|
-
assertCreds(creds, 'task processing lock');
|
|
242
|
-
|
|
243
|
-
try {
|
|
244
|
-
const res = await fetch(`${TASK_BASE_URL}/${taskId}/processing`, {
|
|
245
|
-
method: 'PATCH',
|
|
246
|
-
headers: buildHeaders(creds),
|
|
247
|
-
body: JSON.stringify({ processing }),
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
if (!res.ok) {
|
|
251
|
-
const body = await res.text().catch(() => '');
|
|
252
|
-
console.warn(`⚠️ Task processing lock failed: ${res.status} ${res.statusText} ${body}`);
|
|
253
|
-
return { acquired: false, task: null };
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const data = await res.json().catch(() => null);
|
|
257
|
-
return {
|
|
258
|
-
acquired: data?.acquired ?? false,
|
|
259
|
-
task: data?.task || null,
|
|
260
|
-
};
|
|
261
|
-
} catch (e) {
|
|
262
|
-
console.warn(`⚠️ Task processing lock failed: ${e.message}`);
|
|
263
|
-
return { acquired: false, task: null };
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Cancel a task (transitions to state='cancelled').
|
|
269
|
-
* PATCH /tasks/:taskId/cancel
|
|
270
|
-
*
|
|
271
|
-
* @param {string} taskId
|
|
272
|
-
* @param {string} operatorKey
|
|
273
|
-
* @returns {Promise<Object|null>} Cancelled task or null
|
|
274
|
-
*/
|
|
275
|
-
export async function cancelTask(taskId, creds) {
|
|
276
|
-
if (!taskId) return null;
|
|
277
|
-
assertCreds(creds, 'task cancellation');
|
|
278
|
-
|
|
279
|
-
try {
|
|
280
|
-
const res = await fetch(`${TASK_BASE_URL}/${taskId}/cancel`, {
|
|
281
|
-
method: 'PATCH',
|
|
282
|
-
headers: buildHeaders(creds),
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
if (!res.ok) {
|
|
286
|
-
const body = await res.text().catch(() => '');
|
|
287
|
-
console.warn(`⚠️ Task cancel failed: ${res.status} ${res.statusText} ${body}`);
|
|
288
|
-
return null;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
const result = await res.json().catch(() => null);
|
|
292
|
-
return extractTask(result);
|
|
293
|
-
} catch (e) {
|
|
294
|
-
console.warn(`⚠️ Task cancel failed: ${e.message}`);
|
|
295
|
-
return null;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Get subtasks for a parent task.
|
|
301
|
-
* GET /tasks?parentTaskId=...
|
|
302
|
-
*
|
|
303
|
-
* @param {string} parentTaskId
|
|
304
|
-
* @param {string} operatorKey
|
|
305
|
-
* @returns {Promise<Object[]>} Array of Task objects
|
|
306
|
-
*/
|
|
307
|
-
export async function getSubtasks(parentTaskId, creds) {
|
|
308
|
-
if (!parentTaskId) return [];
|
|
309
|
-
assertCreds(creds, 'getting subtasks');
|
|
310
|
-
|
|
311
|
-
try {
|
|
312
|
-
const url = new URL(`${TASK_BASE_URL}`);
|
|
313
|
-
url.searchParams.set('parentTaskId', parentTaskId);
|
|
314
|
-
|
|
315
|
-
const res = await fetch(url.toString(), {
|
|
316
|
-
method: 'GET',
|
|
317
|
-
headers: buildHeaders(creds),
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
if (!res.ok) {
|
|
321
|
-
const body = await res.text().catch(() => '');
|
|
322
|
-
console.warn(`⚠️ Get subtasks failed: ${res.status} ${res.statusText} ${body}`);
|
|
323
|
-
return [];
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
const data = await res.json().catch(() => null);
|
|
327
|
-
return Array.isArray(data?.tasks) ? data.tasks : [];
|
|
328
|
-
} catch (e) {
|
|
329
|
-
console.warn(`⚠️ Get subtasks failed: ${e.message}`);
|
|
330
|
-
return [];
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// ---------------------------------------------------------------------------
|
|
335
|
-
// Proposal workflow
|
|
336
|
-
// ---------------------------------------------------------------------------
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Propose work to a user or agent for approval.
|
|
340
|
-
* POST /tasks/proposeToDoWork
|
|
341
|
-
*
|
|
342
|
-
* Creates a task with state='proposal', proposal.status='pending'.
|
|
343
|
-
*
|
|
344
|
-
* @param {Object} proposalData
|
|
345
|
-
* @param {string} proposalData.description
|
|
346
|
-
* @param {string} proposalData.proposedTo - userId or agentId to approve
|
|
347
|
-
* @param {string} proposalData.chatId
|
|
348
|
-
* @param {Object} [proposalData.contract]
|
|
349
|
-
* @param {Object} [proposalData.perspective]
|
|
350
|
-
* @param {string} [proposalData.parentTaskId]
|
|
351
|
-
* @param {string} [proposalData.payerId]
|
|
352
|
-
* @param {string} operatorKey
|
|
353
|
-
* @returns {Promise<Object>} TaskWithFlags object
|
|
354
|
-
*/
|
|
355
|
-
export async function proposeToDoWork(proposalData, creds) {
|
|
356
|
-
if (!proposalData) throw new Error('Proposal data is required for proposal creation');
|
|
357
|
-
assertCreds(creds, 'proposal creation');
|
|
358
|
-
|
|
359
|
-
const { description, proposedTo, chatId, contract, perspective, parentTaskId, payerId } = proposalData;
|
|
360
|
-
const res = await fetch(`${baseUrl}/tasks/proposeToDoWork`, {
|
|
361
|
-
method: 'POST',
|
|
362
|
-
headers: buildHeaders(creds),
|
|
363
|
-
body: JSON.stringify({ description, proposedTo, chatId, contract, perspective, parentTaskId, payerId }),
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
if (!res.ok) {
|
|
367
|
-
const body = await res.text().catch(() => '');
|
|
368
|
-
throwApiError(res, body, `Proposal creation failed: ${res.status} ${res.statusText}`);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
const data = await res.json().catch(() => null);
|
|
372
|
-
const task = extractTask(data);
|
|
373
|
-
if (!task) throw new Error('Invalid response: proposal data not found');
|
|
374
|
-
return task;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Assign task directly (no proposal step). Requires parentTaskId.
|
|
379
|
-
* POST /tasks/assignTask
|
|
380
|
-
*
|
|
381
|
-
* Creates a task with state='active' immediately.
|
|
382
|
-
*
|
|
383
|
-
* @param {Object} assignData
|
|
384
|
-
* @param {string} assignData.description
|
|
385
|
-
* @param {string} assignData.executorId
|
|
386
|
-
* @param {string} assignData.chatId
|
|
387
|
-
* @param {string} assignData.parentTaskId - required (proves user approval)
|
|
388
|
-
* @param {Object} [assignData.contract]
|
|
389
|
-
* @param {Object} [assignData.perspective]
|
|
390
|
-
* @param {string} [assignData.payerId]
|
|
391
|
-
* @param {string} operatorKey
|
|
392
|
-
* @returns {Promise<Object>} TaskWithFlags object
|
|
393
|
-
*/
|
|
394
|
-
export async function assignTask(assignData, creds) {
|
|
395
|
-
if (!assignData) throw new Error('Assign data is required');
|
|
396
|
-
assertCreds(creds, 'task assignment');
|
|
397
|
-
|
|
398
|
-
const { description, executorId, chatId, contract, perspective, parentTaskId, payerId } = assignData;
|
|
399
|
-
const res = await fetch(`${baseUrl}/tasks/assignTask`, {
|
|
400
|
-
method: 'POST',
|
|
401
|
-
headers: buildHeaders(creds),
|
|
402
|
-
body: JSON.stringify({ description, executorId, chatId, contract, perspective, parentTaskId, payerId }),
|
|
403
|
-
});
|
|
404
|
-
|
|
405
|
-
if (!res.ok) {
|
|
406
|
-
const body = await res.text().catch(() => '');
|
|
407
|
-
throwApiError(res, body, `Task assignment failed: ${res.status} ${res.statusText}`);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
const data = await res.json().catch(() => null);
|
|
411
|
-
const task = extractTask(data);
|
|
412
|
-
if (!task) throw new Error('Invalid response: assignment data not found');
|
|
413
|
-
return task;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Delegate task to another agent (creates proposal to executor). Requires parentTaskId.
|
|
418
|
-
* POST /tasks/delegateToAgent
|
|
419
|
-
*
|
|
420
|
-
* Creates a task with state='proposal', proposedTo=executorId.
|
|
421
|
-
*
|
|
422
|
-
* @param {Object} proposalData
|
|
423
|
-
* @param {string} proposalData.description
|
|
424
|
-
* @param {string} proposalData.executorId
|
|
425
|
-
* @param {string} proposalData.chatId
|
|
426
|
-
* @param {string} proposalData.parentTaskId - required (proves user approval)
|
|
427
|
-
* @param {Object} [proposalData.contract]
|
|
428
|
-
* @param {Object} [proposalData.perspective]
|
|
429
|
-
* @param {string} [proposalData.payerId]
|
|
430
|
-
* @param {string} operatorKey
|
|
431
|
-
* @returns {Promise<Object>} TaskWithFlags object
|
|
432
|
-
*/
|
|
433
|
-
export async function delegateToAgent(proposalData, creds) {
|
|
434
|
-
if (!proposalData) throw new Error('Proposal data is required for delegation');
|
|
435
|
-
assertCreds(creds, 'proposal creation');
|
|
436
|
-
|
|
437
|
-
const { description, executorId, chatId, contract, perspective, parentTaskId, payerId } = proposalData;
|
|
438
|
-
const res = await fetch(`${baseUrl}/tasks/delegateToAgent`, {
|
|
439
|
-
method: 'POST',
|
|
440
|
-
headers: buildHeaders(creds),
|
|
441
|
-
body: JSON.stringify({ description, executorId, chatId, contract, perspective, parentTaskId, payerId }),
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
if (!res.ok) {
|
|
445
|
-
const body = await res.text().catch(() => '');
|
|
446
|
-
throwApiError(res, body, `Delegation failed: ${res.status} ${res.statusText}`);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
const data = await res.json().catch(() => null);
|
|
450
|
-
const task = extractTask(data);
|
|
451
|
-
if (!task) throw new Error('Invalid response: delegation data not found');
|
|
452
|
-
return task;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
/**
|
|
456
|
-
* Update a plan step within a task.
|
|
457
|
-
* PATCH /tasks/:taskId/plan
|
|
458
|
-
*
|
|
459
|
-
* @param {string} taskId
|
|
460
|
-
* @param {string} stepId
|
|
461
|
-
* @param {'pending'|'in_progress'|'completed'|'skipped'} status
|
|
462
|
-
* @param {*} [result]
|
|
463
|
-
* @param {string} operatorKey
|
|
464
|
-
* @returns {Promise<Object|null>} Updated task or null
|
|
465
|
-
*/
|
|
466
|
-
export async function updatePlanStep(taskId, stepId, status, result, creds) {
|
|
467
|
-
if (!taskId || !stepId || !status) return null;
|
|
468
|
-
assertCreds(creds, 'plan step update');
|
|
469
|
-
|
|
470
|
-
try {
|
|
471
|
-
const body = { stepId, status };
|
|
472
|
-
if (result !== undefined) body.result = result;
|
|
473
|
-
|
|
474
|
-
const res = await fetch(`${TASK_BASE_URL}/${taskId}/plan`, {
|
|
475
|
-
method: 'PATCH',
|
|
476
|
-
headers: buildHeaders(creds),
|
|
477
|
-
body: JSON.stringify(body),
|
|
478
|
-
});
|
|
479
|
-
|
|
480
|
-
if (!res.ok) {
|
|
481
|
-
const responseBody = await res.text().catch(() => '');
|
|
482
|
-
console.warn(`⚠️ Plan step update failed: ${res.status} ${res.statusText} ${responseBody}`);
|
|
483
|
-
return null;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
const data = await res.json().catch(() => null);
|
|
487
|
-
return extractTask(data);
|
|
488
|
-
} catch (e) {
|
|
489
|
-
console.warn(`⚠️ Plan step update failed: ${e.message}`);
|
|
490
|
-
return null;
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Respond to a proposal — approve or reject.
|
|
496
|
-
* POST /tasks/respondToProposal
|
|
497
|
-
*
|
|
498
|
-
* approve: state proposal→active, proposal.status='approved'
|
|
499
|
-
* reject: state proposal→cancelled, proposal.status='rejected'
|
|
500
|
-
*
|
|
501
|
-
* @param {string} taskId
|
|
502
|
-
* @param {'approve'|'reject'} action
|
|
503
|
-
* @param {string} operatorKey
|
|
504
|
-
* @returns {Promise<Object>} TaskWithFlags object
|
|
505
|
-
*/
|
|
506
|
-
export async function respondToProposal(taskId, action, creds) {
|
|
507
|
-
if (!taskId || !action) throw new Error('Task ID and action are required for proposal response');
|
|
508
|
-
assertCreds(creds, 'proposal response');
|
|
509
|
-
|
|
510
|
-
const res = await fetch(`${baseUrl}/tasks/respondToProposal`, {
|
|
511
|
-
method: 'POST',
|
|
512
|
-
headers: buildHeaders(creds),
|
|
513
|
-
body: JSON.stringify({ taskId, action }),
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
if (!res.ok) {
|
|
517
|
-
const body = await res.text().catch(() => '');
|
|
518
|
-
throwApiError(res, body, `Proposal response failed: ${res.status} ${res.statusText}`);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
const data = await res.json().catch(() => null);
|
|
522
|
-
const task = extractTask(data);
|
|
523
|
-
if (!task) throw new Error('Invalid response: proposal response data not found');
|
|
524
|
-
return task;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
// ---------------------------------------------------------------------------
|
|
528
|
-
// Shared Task Ledger (Pub/Sub)
|
|
529
|
-
// ---------------------------------------------------------------------------
|
|
530
|
-
|
|
531
|
-
/**
|
|
532
|
-
* Publish a task to the shared ledger (open for any agent to pull/claim).
|
|
533
|
-
* POST /tasks/ledger/publish
|
|
534
|
-
*
|
|
535
|
-
* Creates a task with state='proposal', proposal.proposedTo='everyone'.
|
|
536
|
-
*
|
|
537
|
-
* @param {Object} payload
|
|
538
|
-
* @param {string} payload.description
|
|
539
|
-
* @param {string} [payload.chatId]
|
|
540
|
-
* @param {string} [payload.payerId]
|
|
541
|
-
* @param {string} [payload.parentTaskId]
|
|
542
|
-
* @param {Object} [payload.contract]
|
|
543
|
-
* @param {Object} [payload.perspective]
|
|
544
|
-
* @param {string} operatorKey
|
|
545
|
-
* @returns {Promise<Object>} Task object
|
|
546
|
-
*/
|
|
547
|
-
export async function publishToLedger(payload, creds) {
|
|
548
|
-
assertCreds(creds, 'ledger publish');
|
|
549
|
-
const res = await fetch(`${TASK_BASE_URL}/ledger/publish`, {
|
|
550
|
-
method: 'POST',
|
|
551
|
-
headers: buildHeaders(creds),
|
|
552
|
-
body: JSON.stringify(payload || {}),
|
|
553
|
-
});
|
|
554
|
-
if (!res.ok) {
|
|
555
|
-
const body = await res.text().catch(() => '');
|
|
556
|
-
throwApiError(res, body, `Ledger publish failed: ${res.status}`);
|
|
557
|
-
}
|
|
558
|
-
const data = await res.json().catch(() => null);
|
|
559
|
-
return extractTask(data);
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
/**
|
|
563
|
-
* Pull open tasks from the ledger (for agents to accept/ignore or claim).
|
|
564
|
-
* POST /tasks/ledger/pull
|
|
565
|
-
*
|
|
566
|
-
* @param {Object} [options]
|
|
567
|
-
* @param {number} [options.limit] - max tasks to return (default 50, max 100)
|
|
568
|
-
* @param {string} [options.since] - ISO date string, only return tasks created after this
|
|
569
|
-
* @param {string} operatorKey
|
|
570
|
-
* @returns {Promise<Object[]>} Array of Task objects
|
|
571
|
-
*/
|
|
572
|
-
export async function pullFromLedger(options, creds) {
|
|
573
|
-
const headers = buildHeaders(creds);
|
|
574
|
-
const res = await fetch(`${TASK_BASE_URL}/ledger/pull`, {
|
|
575
|
-
method: 'POST',
|
|
576
|
-
headers,
|
|
577
|
-
body: JSON.stringify(options || {}),
|
|
578
|
-
});
|
|
579
|
-
if (!res.ok) {
|
|
580
|
-
const body = await res.text().catch(() => '');
|
|
581
|
-
throwApiError(res, body, `Ledger pull failed: ${res.status}`);
|
|
582
|
-
}
|
|
583
|
-
const data = await res.json().catch(() => null);
|
|
584
|
-
return data?.tasks ?? [];
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
/**
|
|
588
|
-
* Claim a ledger task so only this agent works on it.
|
|
589
|
-
* POST /tasks/ledger/claim
|
|
590
|
-
*
|
|
591
|
-
* Atomically sets executorId and transitions state proposal→active.
|
|
592
|
-
*
|
|
593
|
-
* @param {string} taskId
|
|
594
|
-
* @param {string} operatorKey
|
|
595
|
-
* @returns {Promise<Object>} TaskWithFlags object
|
|
596
|
-
*/
|
|
597
|
-
export async function claimLedgerTask(taskId, creds) {
|
|
598
|
-
if (!taskId) throw new Error('taskId is required');
|
|
599
|
-
assertCreds(creds, 'ledger claim');
|
|
600
|
-
const res = await fetch(`${TASK_BASE_URL}/ledger/claim`, {
|
|
601
|
-
method: 'POST',
|
|
602
|
-
headers: buildHeaders(creds),
|
|
603
|
-
body: JSON.stringify({ taskId }),
|
|
604
|
-
});
|
|
605
|
-
if (!res.ok) {
|
|
606
|
-
const body = await res.text().catch(() => '');
|
|
607
|
-
throwApiError(res, body, `Ledger claim failed: ${res.status}`);
|
|
608
|
-
}
|
|
609
|
-
const data = await res.json().catch(() => null);
|
|
610
|
-
if (!data?.ok) throw new Error(data?.error || 'Claim failed');
|
|
611
|
-
return data.task;
|
|
612
|
-
}
|
package/src/http/index.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// HTTP API Clients
|
|
2
|
-
export * from './TaskClient.js';
|
|
3
|
-
export { ContextReader } from './ContextReader.js';
|
|
4
|
-
export { ContextWriter } from './ContextWriter.js';
|
|
5
|
-
export { AgentSearchClient } from './AgentSearchClient.js';
|
|
6
|
-
export { TelemetryClient } from './TelemetryClient.js';
|
package/src/types.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type constants for the Ziggs API
|
|
3
|
-
* These types are used when interacting with the backend timeline/history API
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// Entry Types (entryType) - The kind of timeline entry
|
|
7
|
-
export const EntryTypes = {
|
|
8
|
-
MESSAGE: 'message',
|
|
9
|
-
NOTIFICATION: 'notification',
|
|
10
|
-
ARTIFACT: 'artifact',
|
|
11
|
-
TASK_HISTORY: 'task_history',
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
// Content Types (content_type) - The type of content within an entry
|
|
15
|
-
export const ContentTypes = {
|
|
16
|
-
TEXT: 'text',
|
|
17
|
-
OPERATION: 'operation',
|
|
18
|
-
CONTEXT: 'context',
|
|
19
|
-
RESULT: 'result',
|
|
20
|
-
TASK_UPDATE: 'task_update',
|
|
21
|
-
THOUGHT: 'thought',
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Open ledger proposals: proposal.proposedTo === this value means any agent can claim (approve).
|
|
26
|
-
* ⚠️ SYNC: Keep in sync with backend/src/tasks/task-core.ts and agent-sdk/src/tasks/taskCore.js
|
|
27
|
-
*/
|
|
28
|
-
export const OPEN_PROPOSAL_TARGET = 'everyone';
|
package/src/utils/urlUtils.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gets the HTTP backend URL from HTTP_URL env var or defaults to api.ziggsai.com
|
|
3
|
-
*/
|
|
4
|
-
export function getBackendUrl() {
|
|
5
|
-
const url = process.env.HTTP_URL || 'https://api.ziggsai.com';
|
|
6
|
-
// Ensure it has a protocol
|
|
7
|
-
return url.startsWith('http') ? url : `https://${url}`;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Gets the WebSocket URL from WS_URL env var or defaults to wss://api.ziggsai.com
|
|
12
|
-
*/
|
|
13
|
-
export function getWebSocketUrl() {
|
|
14
|
-
const wsUrl = process.env.WS_URL || 'wss://api.ziggsai.com';
|
|
15
|
-
// Ensure it has a protocol
|
|
16
|
-
return wsUrl.startsWith('ws') ? wsUrl : `wss://${wsUrl}`;
|
|
17
|
-
}
|