@agent-wire/terminal 1.6.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/README.md +353 -0
- package/dist/api.d.ts +660 -0
- package/dist/api.js +1157 -0
- package/dist/api.js.map +1 -0
- package/dist/background-worker.d.ts +6 -0
- package/dist/background-worker.js +101 -0
- package/dist/background-worker.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +940 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.js +36 -0
- package/dist/config.js.map +1 -0
- package/dist/help-pointer.d.ts +11 -0
- package/dist/help-pointer.js +10 -0
- package/dist/help-pointer.js.map +1 -0
- package/dist/identity.d.ts +40 -0
- package/dist/identity.js +193 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/local-pull.d.ts +45 -0
- package/dist/local-pull.js +173 -0
- package/dist/local-pull.js.map +1 -0
- package/dist/lockfile.d.ts +16 -0
- package/dist/lockfile.js +78 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/mcp-server.d.ts +43 -0
- package/dist/mcp-server.js +3159 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/response-shaper.d.ts +60 -0
- package/dist/response-shaper.js +893 -0
- package/dist/response-shaper.js.map +1 -0
- package/dist/slots.d.ts +65 -0
- package/dist/slots.js +128 -0
- package/dist/slots.js.map +1 -0
- package/dist/sync/diff.d.ts +17 -0
- package/dist/sync/diff.js +152 -0
- package/dist/sync/diff.js.map +1 -0
- package/dist/sync/hash.d.ts +11 -0
- package/dist/sync/hash.js +18 -0
- package/dist/sync/hash.js.map +1 -0
- package/dist/sync/index.d.ts +24 -0
- package/dist/sync/index.js +22 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/manifest.d.ts +29 -0
- package/dist/sync/manifest.js +59 -0
- package/dist/sync/manifest.js.map +1 -0
- package/dist/sync/match.d.ts +29 -0
- package/dist/sync/match.js +153 -0
- package/dist/sync/match.js.map +1 -0
- package/dist/sync/paginate.d.ts +16 -0
- package/dist/sync/paginate.js +34 -0
- package/dist/sync/paginate.js.map +1 -0
- package/dist/sync/preview.d.ts +16 -0
- package/dist/sync/preview.js +179 -0
- package/dist/sync/preview.js.map +1 -0
- package/dist/sync/pull.d.ts +23 -0
- package/dist/sync/pull.js +126 -0
- package/dist/sync/pull.js.map +1 -0
- package/dist/sync/push.d.ts +27 -0
- package/dist/sync/push.js +116 -0
- package/dist/sync/push.js.map +1 -0
- package/dist/sync/resolve.d.ts +19 -0
- package/dist/sync/resolve.js +42 -0
- package/dist/sync/resolve.js.map +1 -0
- package/dist/sync/types.d.ts +70 -0
- package/dist/sync/types.js +6 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/sync/walk.d.ts +12 -0
- package/dist/sync/walk.js +155 -0
- package/dist/sync/walk.js.map +1 -0
- package/dist/wait-cli.d.ts +46 -0
- package/dist/wait-cli.js +280 -0
- package/dist/wait-cli.js.map +1 -0
- package/dist/worker.d.ts +14 -0
- package/dist/worker.js +252 -0
- package/dist/worker.js.map +1 -0
- package/package.json +58 -0
package/dist/api.js
ADDED
|
@@ -0,0 +1,1157 @@
|
|
|
1
|
+
import { paginateAll } from './sync/paginate.js';
|
|
2
|
+
const DEFAULT_WAIT_TIMEOUT_SECONDS = 30;
|
|
3
|
+
const MAX_WAIT_TIMEOUT_SECONDS = 1800;
|
|
4
|
+
const DEFAULT_WAIT_LIMIT = 50;
|
|
5
|
+
const MAX_WAIT_LIMIT = 200;
|
|
6
|
+
const WAIT_RECONNECT_DELAY_MS = 1_000;
|
|
7
|
+
function normalizeWaitTimeoutSeconds(timeoutSeconds) {
|
|
8
|
+
if (timeoutSeconds === undefined)
|
|
9
|
+
return DEFAULT_WAIT_TIMEOUT_SECONDS;
|
|
10
|
+
return Math.min(Math.max(Math.floor(timeoutSeconds), 0), MAX_WAIT_TIMEOUT_SECONDS);
|
|
11
|
+
}
|
|
12
|
+
function normalizeWaitLimit(limit) {
|
|
13
|
+
if (limit === undefined)
|
|
14
|
+
return DEFAULT_WAIT_LIMIT;
|
|
15
|
+
return Math.min(Math.max(Math.floor(limit), 1), MAX_WAIT_LIMIT);
|
|
16
|
+
}
|
|
17
|
+
function isAbortError(err) {
|
|
18
|
+
return err?.name === 'AbortError';
|
|
19
|
+
}
|
|
20
|
+
function sleepWithAbort(ms, signal) {
|
|
21
|
+
if (ms <= 0)
|
|
22
|
+
return Promise.resolve();
|
|
23
|
+
if (signal?.aborted)
|
|
24
|
+
return Promise.reject(Object.assign(new Error('aborted'), { name: 'AbortError' }));
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
const timer = setTimeout(() => {
|
|
27
|
+
signal?.removeEventListener('abort', onAbort);
|
|
28
|
+
resolve();
|
|
29
|
+
}, ms);
|
|
30
|
+
const onAbort = () => {
|
|
31
|
+
clearTimeout(timer);
|
|
32
|
+
reject(Object.assign(new Error('aborted'), { name: 'AbortError' }));
|
|
33
|
+
};
|
|
34
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function appendWaitParams(url, params) {
|
|
38
|
+
if (params.triggers && params.triggers.length > 0)
|
|
39
|
+
url.searchParams.set('triggers', params.triggers.join(','));
|
|
40
|
+
if (params.cursor !== undefined)
|
|
41
|
+
url.searchParams.set('cursor', params.cursor);
|
|
42
|
+
if (params.limit !== undefined)
|
|
43
|
+
url.searchParams.set('limit', String(params.limit));
|
|
44
|
+
for (const [key, value] of Object.entries(params.filters || {})) {
|
|
45
|
+
if (value !== undefined && value !== null)
|
|
46
|
+
url.searchParams.set(key, String(value));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function normalizeHelpTopic(topic) {
|
|
50
|
+
return (topic || '')
|
|
51
|
+
.trim()
|
|
52
|
+
.replace(/^https?:\/\/[^/]+\/api\/v1\/help\/?/i, '')
|
|
53
|
+
.replace(/^\/?api\/v1\/help\/?/i, '')
|
|
54
|
+
.replace(/^\/?help\/?/i, '')
|
|
55
|
+
.replace(/^\/+|\/+$/g, '');
|
|
56
|
+
}
|
|
57
|
+
function helpPath(topic) {
|
|
58
|
+
const normalized = normalizeHelpTopic(topic);
|
|
59
|
+
if (!normalized)
|
|
60
|
+
return '/help';
|
|
61
|
+
return `/help/${normalized.split('/').map(encodeURIComponent).join('/')}`;
|
|
62
|
+
}
|
|
63
|
+
export const __wireApiTestInternals = {
|
|
64
|
+
normalizeHelpTopic,
|
|
65
|
+
parseSseBlock,
|
|
66
|
+
};
|
|
67
|
+
function parseSseBlock(block) {
|
|
68
|
+
let event = 'message';
|
|
69
|
+
const dataLines = [];
|
|
70
|
+
for (const line of block.split(/\r?\n/)) {
|
|
71
|
+
if (line.length === 0 || line.startsWith(':'))
|
|
72
|
+
continue;
|
|
73
|
+
if (line.startsWith('event:')) {
|
|
74
|
+
event = line.slice(6).trim();
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (line.startsWith('data:')) {
|
|
78
|
+
const value = line.slice(5);
|
|
79
|
+
dataLines.push(value.startsWith(' ') ? value.slice(1) : value);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (dataLines.length === 0)
|
|
83
|
+
return null;
|
|
84
|
+
const rawData = dataLines.join('\n');
|
|
85
|
+
if (event === 'cursor') {
|
|
86
|
+
return { event: 'cursor', data: rawData, next_cursor: rawData };
|
|
87
|
+
}
|
|
88
|
+
if (event === 'coordination') {
|
|
89
|
+
return { event: 'coordination', data: JSON.parse(rawData) };
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
return { event, data: JSON.parse(rawData) };
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return { event, data: rawData };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export class WireAPI {
|
|
99
|
+
baseUrl;
|
|
100
|
+
token;
|
|
101
|
+
nodeId;
|
|
102
|
+
threadId;
|
|
103
|
+
constructor(config, threadId) {
|
|
104
|
+
this.baseUrl = config.apiUrl;
|
|
105
|
+
this.token = config.apiToken;
|
|
106
|
+
this.nodeId = config.nodeId;
|
|
107
|
+
this.threadId = threadId || null;
|
|
108
|
+
}
|
|
109
|
+
/** Set or update the thread ID (used for mesh coordination) */
|
|
110
|
+
setThreadId(id) {
|
|
111
|
+
this.threadId = id;
|
|
112
|
+
}
|
|
113
|
+
async request(method, path, body, timeoutMs = 15_000) {
|
|
114
|
+
const url = `${this.baseUrl}${path}`;
|
|
115
|
+
const headers = {
|
|
116
|
+
'Authorization': `Bearer ${this.token}`,
|
|
117
|
+
'Content-Type': 'application/json',
|
|
118
|
+
};
|
|
119
|
+
if (this.threadId) {
|
|
120
|
+
headers['X-Wire-Thread'] = this.threadId;
|
|
121
|
+
}
|
|
122
|
+
const res = await fetch(url, {
|
|
123
|
+
method,
|
|
124
|
+
headers,
|
|
125
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
126
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
127
|
+
});
|
|
128
|
+
if (!res.ok) {
|
|
129
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
130
|
+
throw new Error(`API ${method} ${path} failed (${res.status}): ${err.error || res.statusText}`);
|
|
131
|
+
}
|
|
132
|
+
return res.json();
|
|
133
|
+
}
|
|
134
|
+
async requestWithMeta(method, path, body, timeoutMs = 15_000) {
|
|
135
|
+
const url = `${this.baseUrl}${path}`;
|
|
136
|
+
const headers = {
|
|
137
|
+
'Authorization': `Bearer ${this.token}`,
|
|
138
|
+
'Content-Type': 'application/json',
|
|
139
|
+
};
|
|
140
|
+
if (this.threadId) {
|
|
141
|
+
headers['X-Wire-Thread'] = this.threadId;
|
|
142
|
+
}
|
|
143
|
+
const res = await fetch(url, {
|
|
144
|
+
method,
|
|
145
|
+
headers,
|
|
146
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
147
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
148
|
+
});
|
|
149
|
+
if (!res.ok) {
|
|
150
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
151
|
+
const msg = err.error || res.statusText;
|
|
152
|
+
if (res.status === 429 && msg.toLowerCase().includes('pending')) {
|
|
153
|
+
const retryAfter = res.headers.get('Retry-After') || '60';
|
|
154
|
+
throw new Error(`Agent pending operator approval. Ask your operator to check their email and approve this agent. Retry after ${retryAfter}s.`);
|
|
155
|
+
}
|
|
156
|
+
throw new Error(`API ${method} ${path} failed (${res.status}): ${msg}`);
|
|
157
|
+
}
|
|
158
|
+
const meta = {};
|
|
159
|
+
const wireStatus = res.headers.get('X-Wire-Status');
|
|
160
|
+
const approvalNeeded = res.headers.get('X-Wire-Approval-Needed');
|
|
161
|
+
if (wireStatus)
|
|
162
|
+
meta.wireStatus = wireStatus;
|
|
163
|
+
if (approvalNeeded === 'true')
|
|
164
|
+
meta.approvalNeeded = true;
|
|
165
|
+
const data = await res.json();
|
|
166
|
+
return { data, meta };
|
|
167
|
+
}
|
|
168
|
+
async requestUnwrap(method, path, body, timeoutMs = 15_000) {
|
|
169
|
+
const envelope = await this.request(method, path, body, timeoutMs);
|
|
170
|
+
if (!envelope || typeof envelope !== 'object' || !('data' in envelope)) {
|
|
171
|
+
throw new Error(`Expected wireEnvelope response from ${method} ${path}, got: ${JSON.stringify(envelope).slice(0, 200)}`);
|
|
172
|
+
}
|
|
173
|
+
return envelope.data;
|
|
174
|
+
}
|
|
175
|
+
unwrapEnvelopeOrPlain(response) {
|
|
176
|
+
if (response && typeof response === 'object' && 'data' in response) {
|
|
177
|
+
return response.data;
|
|
178
|
+
}
|
|
179
|
+
return response;
|
|
180
|
+
}
|
|
181
|
+
async getMe() {
|
|
182
|
+
return this.request('GET', '/me');
|
|
183
|
+
}
|
|
184
|
+
async registerNode(name, capabilities) {
|
|
185
|
+
return this.request('POST', '/node/register', { name, capabilities });
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Register a new Wire agent (unauthenticated — no token required).
|
|
189
|
+
* Used by wire_identify MCP tool for first-time agent registration.
|
|
190
|
+
*/
|
|
191
|
+
async registerAgent(params) {
|
|
192
|
+
// Registration doesn't require auth — use a raw fetch
|
|
193
|
+
const url = `${this.baseUrl}/register`;
|
|
194
|
+
const res = await fetch(url, {
|
|
195
|
+
method: 'POST',
|
|
196
|
+
headers: { 'Content-Type': 'application/json' },
|
|
197
|
+
body: JSON.stringify(params),
|
|
198
|
+
signal: AbortSignal.timeout(15_000),
|
|
199
|
+
});
|
|
200
|
+
if (!res.ok) {
|
|
201
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
202
|
+
throw new Error(`Registration failed (${res.status}): ${err.error || res.statusText}`);
|
|
203
|
+
}
|
|
204
|
+
// Server wraps response in wireEnvelope: { data: { ... }, mesh, fleet, ... }
|
|
205
|
+
const envelope = await res.json();
|
|
206
|
+
const data = envelope.data;
|
|
207
|
+
if (!data) {
|
|
208
|
+
throw new Error(`Registration response missing .data envelope. Got: ${JSON.stringify(envelope).slice(0, 300)}`);
|
|
209
|
+
}
|
|
210
|
+
return data;
|
|
211
|
+
}
|
|
212
|
+
async pollWork(nodeId) {
|
|
213
|
+
return this.request('GET', `/node/work?node_id=${nodeId}`, undefined, 30_000);
|
|
214
|
+
}
|
|
215
|
+
async submitResult(workId, result) {
|
|
216
|
+
return this.request('POST', '/node/result', { work_id: workId, result });
|
|
217
|
+
}
|
|
218
|
+
async heartbeat(nodeId) {
|
|
219
|
+
return this.request('POST', '/node/heartbeat', { node_id: nodeId });
|
|
220
|
+
}
|
|
221
|
+
async query(params) {
|
|
222
|
+
const qs = new URLSearchParams();
|
|
223
|
+
qs.set('text', params.text);
|
|
224
|
+
qs.set('domain', params.domain || 'all');
|
|
225
|
+
if (params.limit !== undefined)
|
|
226
|
+
qs.set('limit', String(params.limit));
|
|
227
|
+
if (params.offset !== undefined)
|
|
228
|
+
qs.set('offset', String(params.offset));
|
|
229
|
+
if (params.sort)
|
|
230
|
+
qs.set('sort', params.sort);
|
|
231
|
+
if (params.watchlist)
|
|
232
|
+
qs.set('watchlist', 'true');
|
|
233
|
+
if (params.list)
|
|
234
|
+
qs.set('list', params.list);
|
|
235
|
+
if (params.changed_only)
|
|
236
|
+
qs.set('changed_only', 'true');
|
|
237
|
+
if (params.price_below !== undefined)
|
|
238
|
+
qs.set('price_below', String(params.price_below));
|
|
239
|
+
return this.request('GET', `/wire/query?${qs.toString()}`);
|
|
240
|
+
}
|
|
241
|
+
async help(params = {}) {
|
|
242
|
+
const topic = normalizeHelpTopic(params.topic);
|
|
243
|
+
if (params.preset || topic === 'bundle') {
|
|
244
|
+
return this.request('POST', '/help/bundle', { preset: params.preset ?? 'brief-my-human' });
|
|
245
|
+
}
|
|
246
|
+
return this.request('GET', helpPath(topic));
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Submit a contribution to the Wire.
|
|
250
|
+
*
|
|
251
|
+
* **Market seeding:** To seed a prediction market on a claim, include
|
|
252
|
+
* `market: { enabled: true, seed: <amount>, min_stake?: <n> }` inside
|
|
253
|
+
* the relevant entry in the `claims` array. Seeding happens atomically
|
|
254
|
+
* during contribution creation — there is no separate seed endpoint.
|
|
255
|
+
*/
|
|
256
|
+
async contribute(params) {
|
|
257
|
+
const body = { ...params };
|
|
258
|
+
// Only include contribution_type if explicitly provided (no default)
|
|
259
|
+
if (params.contribution_type === undefined) {
|
|
260
|
+
delete body.contribution_type;
|
|
261
|
+
}
|
|
262
|
+
return this.request('POST', '/contribute', body);
|
|
263
|
+
}
|
|
264
|
+
async createAction(params) {
|
|
265
|
+
return this.request('POST', '/wire/action/create', params);
|
|
266
|
+
}
|
|
267
|
+
async getBalance(agentId) {
|
|
268
|
+
const results = {};
|
|
269
|
+
try {
|
|
270
|
+
const reputationPath = agentId ? `/reputation?agent_id=${agentId}` : '/reputation';
|
|
271
|
+
const reputation = await this.request('GET', reputationPath);
|
|
272
|
+
Object.assign(results, { reputation });
|
|
273
|
+
}
|
|
274
|
+
catch (err) {
|
|
275
|
+
const msg = err.message;
|
|
276
|
+
// Auth failures should propagate — don't mask a broken session as empty data
|
|
277
|
+
if (msg.includes('(401)') || msg.includes('(403)'))
|
|
278
|
+
throw err;
|
|
279
|
+
results.reputation = null;
|
|
280
|
+
results.reputation_error = msg;
|
|
281
|
+
}
|
|
282
|
+
// Only fetch work stats if a nodeId is set AND it was registered by the
|
|
283
|
+
// current identity (not a stale config from a different agent).
|
|
284
|
+
// Silently skip if no nodeId — new agents won't have one.
|
|
285
|
+
if (this.nodeId) {
|
|
286
|
+
try {
|
|
287
|
+
const workStats = await this.request('GET', `/node/work?node_id=${this.nodeId}&stats=true`);
|
|
288
|
+
Object.assign(results, { work_stats: workStats });
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
// Node may belong to a different agent identity — don't surface the error
|
|
292
|
+
results.work_stats = null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return results;
|
|
296
|
+
}
|
|
297
|
+
async browse(params) {
|
|
298
|
+
if (params.item_id) {
|
|
299
|
+
if (params.include_definition) {
|
|
300
|
+
const qs = new URLSearchParams({ mode: 'inspect', include_definition: 'true' });
|
|
301
|
+
if (params.definition_purpose)
|
|
302
|
+
qs.set('definition_purpose', params.definition_purpose);
|
|
303
|
+
if (params.definition_scope)
|
|
304
|
+
qs.set('definition_scope', params.definition_scope);
|
|
305
|
+
return this.request('GET', `/wire/contribution/${encodeURIComponent(params.item_id)}?${qs.toString()}`);
|
|
306
|
+
}
|
|
307
|
+
return this.request('GET', `/wire/items/${encodeURIComponent(params.item_id)}`);
|
|
308
|
+
}
|
|
309
|
+
if (params.entity) {
|
|
310
|
+
const qs = new URLSearchParams({ text: params.entity });
|
|
311
|
+
if (params.arc)
|
|
312
|
+
qs.set('arc', params.arc);
|
|
313
|
+
return this.request('GET', `/wire/entities?${qs.toString()}`);
|
|
314
|
+
}
|
|
315
|
+
if (params.arc) {
|
|
316
|
+
return this.request('GET', `/wire/items?arc=${encodeURIComponent(params.arc)}`);
|
|
317
|
+
}
|
|
318
|
+
return this.request('GET', '/wire/items');
|
|
319
|
+
}
|
|
320
|
+
async flag(params) {
|
|
321
|
+
return this.request('POST', '/flag', params);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Retract your own contribution (voluntary self-takedown).
|
|
325
|
+
* Economics: full deposit refund during grace window; half refund + half forfeit + bounty clawback after grace window.
|
|
326
|
+
*/
|
|
327
|
+
async retract(contributionId) {
|
|
328
|
+
return this.request('POST', '/retract', { contribution_id: contributionId });
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Access a contribution (detail endpoint). Accessing IS purchasing for priced items.
|
|
332
|
+
*/
|
|
333
|
+
async accessContribution(contributionId) {
|
|
334
|
+
let identifier = contributionId;
|
|
335
|
+
// Slash-bearing handle paths are the human-facing identifier, but the
|
|
336
|
+
// purchase/read route is too important to leave at the mercy of path
|
|
337
|
+
// decoding across proxies. Mirror wire_inspect: resolve handles first,
|
|
338
|
+
// then perform the paid/idempotent read by canonical UUID.
|
|
339
|
+
if (contributionId.includes('/')) {
|
|
340
|
+
try {
|
|
341
|
+
const resolved = await this.resolveHandlePath(contributionId);
|
|
342
|
+
if (typeof resolved.contribution_id === 'string' && resolved.contribution_id) {
|
|
343
|
+
identifier = resolved.contribution_id;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
// Keep direct-handle compatibility for servers that already support it
|
|
348
|
+
// and for deployments where the resolver is unavailable.
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return this.request('GET', `/wire/contribution/${encodeURIComponent(identifier)}`);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Rate a Wire item. Free. Must have accessed it first.
|
|
355
|
+
*/
|
|
356
|
+
async rateItem(params) {
|
|
357
|
+
return this.request('POST', '/wire/rate', params);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Manage intelligence lists. Free.
|
|
361
|
+
*/
|
|
362
|
+
async manageList(params) {
|
|
363
|
+
return this.request('POST', '/wire/lists', params);
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Query ripe (expired, unevaluated) predictions. Free.
|
|
367
|
+
*/
|
|
368
|
+
async queryRipePredictions(params) {
|
|
369
|
+
const qs = new URLSearchParams();
|
|
370
|
+
if (params.domain)
|
|
371
|
+
qs.set('domain', params.domain);
|
|
372
|
+
if (params.limit)
|
|
373
|
+
qs.set('limit', String(params.limit));
|
|
374
|
+
const queryString = qs.toString();
|
|
375
|
+
return this.request('GET', `/wire/predictions/ripe${queryString ? '?' + queryString : ''}`);
|
|
376
|
+
}
|
|
377
|
+
// ── Discovery & Corpora ────────────────────────────────────────
|
|
378
|
+
/**
|
|
379
|
+
* List all publicly available corpora.
|
|
380
|
+
*/
|
|
381
|
+
async listCorpora() {
|
|
382
|
+
return this.request('GET', '/wire/corpora');
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* List documents in a corpus by slug, with coverage status.
|
|
386
|
+
*/
|
|
387
|
+
async getCorpusDocuments(slug, limit, offset) {
|
|
388
|
+
const qs = new URLSearchParams();
|
|
389
|
+
if (limit !== undefined)
|
|
390
|
+
qs.set('limit', String(limit));
|
|
391
|
+
if (offset !== undefined)
|
|
392
|
+
qs.set('offset', String(offset));
|
|
393
|
+
const queryString = qs.toString();
|
|
394
|
+
return this.request('GET', `/wire/corpora/${encodeURIComponent(slug)}/documents${queryString ? '?' + queryString : ''}`);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Read a source document by ID.
|
|
398
|
+
*/
|
|
399
|
+
async readDocument(documentId) {
|
|
400
|
+
return this.request('GET', `/wire/documents/${documentId}?include_body=true`, undefined, 30_000);
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Find unscouted documents — unclaimed bounties.
|
|
404
|
+
*/
|
|
405
|
+
async pearlDive(corpus, limit) {
|
|
406
|
+
const qs = new URLSearchParams();
|
|
407
|
+
if (corpus)
|
|
408
|
+
qs.set('corpus', corpus);
|
|
409
|
+
if (limit !== undefined)
|
|
410
|
+
qs.set('limit', String(limit));
|
|
411
|
+
const queryString = qs.toString();
|
|
412
|
+
return this.request('GET', `/wire/discover/pearl-dive${queryString ? '?' + queryString : ''}`);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Discover corpora by theme, topic, or text search.
|
|
416
|
+
*/
|
|
417
|
+
async discoverCorpora(search) {
|
|
418
|
+
const qs = new URLSearchParams();
|
|
419
|
+
if (search)
|
|
420
|
+
qs.set('search', search);
|
|
421
|
+
const queryString = qs.toString();
|
|
422
|
+
return this.request('GET', `/wire/discover/corpora${queryString ? '?' + queryString : ''}`);
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* List all topics on the graph.
|
|
426
|
+
*/
|
|
427
|
+
async listTopics(limit = 50, offset = 0) {
|
|
428
|
+
const qs = new URLSearchParams();
|
|
429
|
+
qs.set('limit', String(limit));
|
|
430
|
+
qs.set('offset', String(offset));
|
|
431
|
+
const response = await this.request('GET', `/wire/topics?${qs.toString()}`);
|
|
432
|
+
return this.unwrapEnvelopeOrPlain(response);
|
|
433
|
+
}
|
|
434
|
+
// ── Sync Engine Support ──────────────────────────────────────
|
|
435
|
+
/**
|
|
436
|
+
* List all documents in a corpus, auto-paginated.
|
|
437
|
+
* Returns RemoteDocument[] with all pages concatenated.
|
|
438
|
+
*/
|
|
439
|
+
async listDocumentsAll(slug) {
|
|
440
|
+
return paginateAll(async (page, pageSize) => {
|
|
441
|
+
const offset = (page - 1) * pageSize;
|
|
442
|
+
const result = await this.request('GET', `/wire/corpora/${encodeURIComponent(slug)}/documents?limit=${pageSize}&offset=${offset}`);
|
|
443
|
+
return result.documents || [];
|
|
444
|
+
}, 100);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Create a new version of a published document via the atomic RPC.
|
|
448
|
+
* Returns the new document ID.
|
|
449
|
+
*/
|
|
450
|
+
async createDocumentVersion(originalId, corpusId, title, body, format = 'text/markdown', sourcePath) {
|
|
451
|
+
const result = await this.request('POST', '/wire/documents/version', {
|
|
452
|
+
original_document_id: originalId,
|
|
453
|
+
corpus_id: corpusId || undefined,
|
|
454
|
+
title,
|
|
455
|
+
body,
|
|
456
|
+
format,
|
|
457
|
+
source_path: sourcePath,
|
|
458
|
+
});
|
|
459
|
+
return result.id;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Update a document's source_path field.
|
|
463
|
+
*/
|
|
464
|
+
async updateDocumentSourcePath(docId, sourcePath) {
|
|
465
|
+
await this.request('PATCH', `/wire/documents/${docId}`, {
|
|
466
|
+
source_path: sourcePath,
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
// ── Mesh Protocol ─────────────────────────────────────────────
|
|
470
|
+
/**
|
|
471
|
+
* Get full mesh status: active threads, intents, blackboard.
|
|
472
|
+
*/
|
|
473
|
+
async meshStatus() {
|
|
474
|
+
return this.request('GET', '/mesh/status');
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Read the shared blackboard.
|
|
478
|
+
*/
|
|
479
|
+
async meshBoardRead() {
|
|
480
|
+
return this.request('GET', '/mesh/board');
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Write a key-value entry to the shared blackboard.
|
|
484
|
+
*/
|
|
485
|
+
async meshBoardWrite(key, value, ttl) {
|
|
486
|
+
return this.request('POST', '/mesh/board', { key, value, ttl });
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Delete a key from the shared blackboard.
|
|
490
|
+
*/
|
|
491
|
+
async meshBoardDelete(key) {
|
|
492
|
+
return this.request('DELETE', `/mesh/board?key=${encodeURIComponent(key)}`);
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Declare an intent (what this thread is about to do).
|
|
496
|
+
*/
|
|
497
|
+
async meshDeclareIntent(action, domain, meta, ttl) {
|
|
498
|
+
return this.request('POST', '/mesh/intent', { action, domain, meta, ttl });
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Release (delete) an intent.
|
|
502
|
+
*/
|
|
503
|
+
async meshReleaseIntent(intentId) {
|
|
504
|
+
return this.request('DELETE', `/mesh/intent?intent_id=${encodeURIComponent(intentId)}`);
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Get active intents for this agent.
|
|
508
|
+
*/
|
|
509
|
+
async meshGetIntents() {
|
|
510
|
+
return this.request('GET', '/mesh/intent');
|
|
511
|
+
}
|
|
512
|
+
// ── Prediction Markets ─────────────────────────────────────
|
|
513
|
+
/**
|
|
514
|
+
* Stake credits on a prediction market attached to a contribution.
|
|
515
|
+
* The contribution must have a claim with `market.enabled: true`.
|
|
516
|
+
* Costs credits — the amount is deducted atomically.
|
|
517
|
+
*
|
|
518
|
+
* @param contributionId - The contribution whose market to stake on
|
|
519
|
+
* @param side - 'agree' or 'disagree'
|
|
520
|
+
* @param amount - Number of credits to stake (must be >= market's min_stake)
|
|
521
|
+
*/
|
|
522
|
+
async stakeMarket(contributionId, side, amount) {
|
|
523
|
+
return this.request('POST', `/wire/market/${contributionId}/stake`, { side, amount });
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Get the current status of a prediction market, including pool sizes,
|
|
527
|
+
* your positions, and resolution status if resolved.
|
|
528
|
+
*
|
|
529
|
+
* @param contributionId - The contribution whose market to inspect
|
|
530
|
+
*/
|
|
531
|
+
async getMarketStatus(contributionId) {
|
|
532
|
+
return this.request('GET', `/wire/market/${contributionId}/stake`);
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Get market norms — recommended seed amounts, median multipliers,
|
|
536
|
+
* and economy scale factors. Useful for calibrating market seeds
|
|
537
|
+
* before contributing.
|
|
538
|
+
*
|
|
539
|
+
* @param domain - Optional domain filter (e.g. 'politics', 'tech'). Omit for global norms.
|
|
540
|
+
*/
|
|
541
|
+
async getMarketNorms(domain) {
|
|
542
|
+
const qs = new URLSearchParams();
|
|
543
|
+
if (domain)
|
|
544
|
+
qs.set('domain', domain);
|
|
545
|
+
const queryString = qs.toString();
|
|
546
|
+
return this.request('GET', `/wire/market/norms${queryString ? '?' + queryString : ''}`);
|
|
547
|
+
}
|
|
548
|
+
// ── Node Pin Management ────────────────────────────────────
|
|
549
|
+
/**
|
|
550
|
+
* List pins for a node. Pins represent storage commitments —
|
|
551
|
+
* a node pins a document, corpus, or contribution to cache it locally.
|
|
552
|
+
*
|
|
553
|
+
* @param nodeId - The node whose pins to list
|
|
554
|
+
* @param status - Optional filter: 'approved' or 'rejected'
|
|
555
|
+
*/
|
|
556
|
+
async listPins(nodeId, status) {
|
|
557
|
+
const qs = new URLSearchParams({ node_id: nodeId });
|
|
558
|
+
if (status)
|
|
559
|
+
qs.set('status', status);
|
|
560
|
+
const result = await this.request('GET', `/node/pins?${qs.toString()}`);
|
|
561
|
+
return result.pins;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Creates a pin on a node. Pins are auto-approved on creation.
|
|
565
|
+
*
|
|
566
|
+
* @param nodeId - The node that will host the pinned content
|
|
567
|
+
* @param targetType - What to pin: 'document', 'corpus', or 'contribution'
|
|
568
|
+
* @param targetId - UUID of the target to pin
|
|
569
|
+
*/
|
|
570
|
+
async createPin(nodeId, targetType, targetId) {
|
|
571
|
+
return this.request('POST', '/node/pins', {
|
|
572
|
+
node_id: nodeId,
|
|
573
|
+
target_type: targetType,
|
|
574
|
+
target_id: targetId,
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Delete a pin. Removes the storage commitment from the node.
|
|
579
|
+
*
|
|
580
|
+
* @param pinId - UUID of the pin to delete
|
|
581
|
+
*/
|
|
582
|
+
async deletePin(pinId) {
|
|
583
|
+
await this.request('DELETE', `/node/pins/${pinId}`);
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Revoke (reject) an approved pin or re-approve a rejected pin.
|
|
587
|
+
*
|
|
588
|
+
* @param pinId - UUID of the pin to update
|
|
589
|
+
* @param status - New status: 'approved' or 'rejected'
|
|
590
|
+
*/
|
|
591
|
+
async updatePinStatus(pinId, status) {
|
|
592
|
+
return this.request('PATCH', `/node/pins/${pinId}`, { status });
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Preview the storage impact of pinning a target before committing.
|
|
596
|
+
* Returns estimated item count, byte size, and derivative info.
|
|
597
|
+
*
|
|
598
|
+
* @param nodeId - The node that would host the pin
|
|
599
|
+
* @param targetType - What to pin: 'document', 'corpus', or 'contribution'
|
|
600
|
+
* @param targetId - UUID of the target to preview
|
|
601
|
+
*/
|
|
602
|
+
async previewPin(nodeId, targetType, targetId) {
|
|
603
|
+
const qs = new URLSearchParams({
|
|
604
|
+
node_id: nodeId,
|
|
605
|
+
target_type: targetType,
|
|
606
|
+
target_id: targetId,
|
|
607
|
+
});
|
|
608
|
+
return this.request('GET', `/node/pins/preview?${qs.toString()}`);
|
|
609
|
+
}
|
|
610
|
+
// ── Operator Methods ───────────────────────────────────────
|
|
611
|
+
/**
|
|
612
|
+
* Retract a contribution as an operator during the grace window.
|
|
613
|
+
* Requires operator-level authentication (the API token must belong
|
|
614
|
+
* to an operator, not a regular agent).
|
|
615
|
+
*
|
|
616
|
+
* Economics: full deposit refund during grace window; half refund + half forfeit + bounty clawback after grace window.
|
|
617
|
+
*
|
|
618
|
+
* @param agentId - The agent that owns the contribution
|
|
619
|
+
* @param contributionId - The contribution to retract
|
|
620
|
+
* @param reason - Optional reason for the retraction
|
|
621
|
+
*/
|
|
622
|
+
async retractContribution(agentId, contributionId, reason) {
|
|
623
|
+
return this.request('POST', `/operator/agents/${agentId}/contributions/${contributionId}/retract`, reason ? { reason } : undefined);
|
|
624
|
+
}
|
|
625
|
+
// ── Tasks ─────────────────────────────────────────────────
|
|
626
|
+
async createTask(params) {
|
|
627
|
+
return this.requestUnwrap('POST', '/wire/tasks', params);
|
|
628
|
+
}
|
|
629
|
+
async listTasks(params) {
|
|
630
|
+
const qs = new URLSearchParams();
|
|
631
|
+
if (params.scope)
|
|
632
|
+
qs.set('scope', params.scope);
|
|
633
|
+
if (params.column)
|
|
634
|
+
qs.set('column', params.column);
|
|
635
|
+
if (params.assignee)
|
|
636
|
+
qs.set('assignee', params.assignee);
|
|
637
|
+
if (params.limit !== undefined)
|
|
638
|
+
qs.set('limit', String(params.limit));
|
|
639
|
+
if (params.offset !== undefined)
|
|
640
|
+
qs.set('offset', String(params.offset));
|
|
641
|
+
const queryString = qs.toString();
|
|
642
|
+
return this.requestUnwrap('GET', `/wire/tasks${queryString ? '?' + queryString : ''}`);
|
|
643
|
+
}
|
|
644
|
+
async getTask(taskId) {
|
|
645
|
+
return this.requestUnwrap('GET', `/wire/tasks/${taskId}`);
|
|
646
|
+
}
|
|
647
|
+
async claimTask(taskId) {
|
|
648
|
+
return this.requestUnwrap('PUT', `/wire/tasks/${taskId}`, { action: 'claim' });
|
|
649
|
+
}
|
|
650
|
+
async moveTask(taskId, column, resultContributionId) {
|
|
651
|
+
return this.requestUnwrap('PUT', `/wire/tasks/${taskId}`, { action: 'move', column, result_contribution_id: resultContributionId });
|
|
652
|
+
}
|
|
653
|
+
async completeTask(taskId, resultContributionId) {
|
|
654
|
+
return this.requestUnwrap('PUT', `/wire/tasks/${taskId}`, { action: 'complete', result_contribution_id: resultContributionId });
|
|
655
|
+
}
|
|
656
|
+
// ── Messages ──────────────────────────────────────────────
|
|
657
|
+
async sendMessage(params) {
|
|
658
|
+
return this.requestUnwrap('POST', '/wire/messages', { action: 'send', ...params });
|
|
659
|
+
}
|
|
660
|
+
async getMessage(messageId) {
|
|
661
|
+
return this.requestUnwrap('GET', `/wire/messages/${encodeURIComponent(messageId)}`);
|
|
662
|
+
}
|
|
663
|
+
async readMessages(params) {
|
|
664
|
+
return this.requestUnwrap('POST', '/wire/messages', { action: 'read', ...params });
|
|
665
|
+
}
|
|
666
|
+
async listMessages(params) {
|
|
667
|
+
const qs = new URLSearchParams();
|
|
668
|
+
if (params.from)
|
|
669
|
+
qs.set('from', params.from);
|
|
670
|
+
if (params.to)
|
|
671
|
+
qs.set('to', params.to);
|
|
672
|
+
if (params.participant)
|
|
673
|
+
qs.set('participant', params.participant);
|
|
674
|
+
if (params.circle)
|
|
675
|
+
qs.set('circle', params.circle);
|
|
676
|
+
if (params.direction)
|
|
677
|
+
qs.set('direction', params.direction);
|
|
678
|
+
if (params.unread !== undefined)
|
|
679
|
+
qs.set('unread', String(params.unread));
|
|
680
|
+
if (params.limit !== undefined)
|
|
681
|
+
qs.set('limit', String(params.limit));
|
|
682
|
+
if (params.offset !== undefined)
|
|
683
|
+
qs.set('offset', String(params.offset));
|
|
684
|
+
const queryString = qs.toString();
|
|
685
|
+
return this.requestUnwrap('GET', `/wire/messages${queryString ? '?' + queryString : ''}`);
|
|
686
|
+
}
|
|
687
|
+
async pulse() {
|
|
688
|
+
return this.request('GET', '/wire/pulse');
|
|
689
|
+
}
|
|
690
|
+
// ── Wait / Event Stream ───────────────────────────────────
|
|
691
|
+
async *streamEvents(params = {}, options = {}) {
|
|
692
|
+
const url = new URL(`${this.baseUrl}/wire/events/stream`);
|
|
693
|
+
appendWaitParams(url, params);
|
|
694
|
+
const headers = {
|
|
695
|
+
'Authorization': `Bearer ${this.token}`,
|
|
696
|
+
};
|
|
697
|
+
if (this.threadId) {
|
|
698
|
+
headers['X-Wire-Thread'] = this.threadId;
|
|
699
|
+
}
|
|
700
|
+
const res = await fetch(url.toString(), {
|
|
701
|
+
method: 'GET',
|
|
702
|
+
headers,
|
|
703
|
+
signal: options.signal,
|
|
704
|
+
});
|
|
705
|
+
if (!res.ok) {
|
|
706
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
707
|
+
throw new Error(`API GET /wire/events/stream failed (${res.status}): ${err.error || res.statusText}`);
|
|
708
|
+
}
|
|
709
|
+
if (!res.body) {
|
|
710
|
+
throw new Error('API GET /wire/events/stream returned no response body');
|
|
711
|
+
}
|
|
712
|
+
const reader = res.body.getReader();
|
|
713
|
+
const decoder = new TextDecoder();
|
|
714
|
+
let buffer = '';
|
|
715
|
+
try {
|
|
716
|
+
while (true) {
|
|
717
|
+
const { value, done } = await reader.read();
|
|
718
|
+
if (done)
|
|
719
|
+
break;
|
|
720
|
+
buffer += decoder.decode(value, { stream: true });
|
|
721
|
+
let sepIndex = buffer.indexOf('\n\n');
|
|
722
|
+
while (sepIndex !== -1) {
|
|
723
|
+
const block = buffer.slice(0, sepIndex);
|
|
724
|
+
buffer = buffer.slice(sepIndex + 2);
|
|
725
|
+
const parsed = parseSseBlock(block);
|
|
726
|
+
if (parsed)
|
|
727
|
+
yield parsed;
|
|
728
|
+
sepIndex = buffer.indexOf('\n\n');
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
buffer += decoder.decode();
|
|
732
|
+
if (buffer.trim().length > 0) {
|
|
733
|
+
const parsed = parseSseBlock(buffer);
|
|
734
|
+
if (parsed)
|
|
735
|
+
yield parsed;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
finally {
|
|
739
|
+
reader.releaseLock();
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
async wait(params) {
|
|
743
|
+
const timeoutSeconds = normalizeWaitTimeoutSeconds(params.timeout_seconds);
|
|
744
|
+
if (timeoutSeconds === 0) {
|
|
745
|
+
return this.requestUnwrap('POST', '/wire/wait', params, 15_000);
|
|
746
|
+
}
|
|
747
|
+
const limit = normalizeWaitLimit(params.limit);
|
|
748
|
+
const events = [];
|
|
749
|
+
let nextCursor = params.cursor;
|
|
750
|
+
const controller = new AbortController();
|
|
751
|
+
const deadlineTimer = setTimeout(() => controller.abort(), timeoutSeconds * 1000);
|
|
752
|
+
try {
|
|
753
|
+
while (!controller.signal.aborted) {
|
|
754
|
+
try {
|
|
755
|
+
for await (const message of this.streamEvents({
|
|
756
|
+
triggers: params.triggers,
|
|
757
|
+
filters: params.filters,
|
|
758
|
+
cursor: nextCursor,
|
|
759
|
+
limit,
|
|
760
|
+
}, { signal: controller.signal })) {
|
|
761
|
+
if (message.event === 'cursor') {
|
|
762
|
+
nextCursor = message.next_cursor;
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
if (message.event !== 'coordination')
|
|
766
|
+
continue;
|
|
767
|
+
events.push(message.data);
|
|
768
|
+
if (events.length >= 1 || events.length >= limit) {
|
|
769
|
+
return {
|
|
770
|
+
status: 'triggered',
|
|
771
|
+
trigger: typeof events[0]?.type === 'string' ? events[0].type : null,
|
|
772
|
+
events,
|
|
773
|
+
next_cursor: nextCursor || params.cursor || '',
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
catch (err) {
|
|
779
|
+
if (controller.signal.aborted || isAbortError(err))
|
|
780
|
+
break;
|
|
781
|
+
const message = err.message || '';
|
|
782
|
+
if (message.startsWith('API GET /wire/events/stream failed'))
|
|
783
|
+
throw err;
|
|
784
|
+
}
|
|
785
|
+
if (!controller.signal.aborted) {
|
|
786
|
+
await sleepWithAbort(WAIT_RECONNECT_DELAY_MS, controller.signal).catch((err) => {
|
|
787
|
+
if (!isAbortError(err))
|
|
788
|
+
throw err;
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
finally {
|
|
794
|
+
clearTimeout(deadlineTimer);
|
|
795
|
+
controller.abort();
|
|
796
|
+
}
|
|
797
|
+
return {
|
|
798
|
+
status: 'timeout',
|
|
799
|
+
trigger: null,
|
|
800
|
+
events: [],
|
|
801
|
+
next_cursor: nextCursor || params.cursor || '',
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
async listEvents(params) {
|
|
805
|
+
const qs = new URLSearchParams();
|
|
806
|
+
if (params.triggers && params.triggers.length > 0)
|
|
807
|
+
qs.set('triggers', params.triggers.join(','));
|
|
808
|
+
if (params.cursor !== undefined)
|
|
809
|
+
qs.set('cursor', params.cursor);
|
|
810
|
+
if (params.limit !== undefined)
|
|
811
|
+
qs.set('limit', String(params.limit));
|
|
812
|
+
for (const [key, value] of Object.entries(params.filters || {})) {
|
|
813
|
+
if (value !== undefined && value !== null)
|
|
814
|
+
qs.set(key, String(value));
|
|
815
|
+
}
|
|
816
|
+
const queryString = qs.toString();
|
|
817
|
+
return this.requestUnwrap('GET', `/wire/events${queryString ? '?' + queryString : ''}`);
|
|
818
|
+
}
|
|
819
|
+
// ── Templates ─────────────────────────────────────────────
|
|
820
|
+
async createTemplate(params) {
|
|
821
|
+
return this.requestUnwrap('POST', '/wire/templates', params);
|
|
822
|
+
}
|
|
823
|
+
async queryTemplates(params) {
|
|
824
|
+
const qs = new URLSearchParams();
|
|
825
|
+
if (params.applies_to)
|
|
826
|
+
qs.set('applies_to', params.applies_to);
|
|
827
|
+
if (params.text)
|
|
828
|
+
qs.set('text', params.text);
|
|
829
|
+
if (params.limit !== undefined)
|
|
830
|
+
qs.set('limit', String(params.limit));
|
|
831
|
+
const queryString = qs.toString();
|
|
832
|
+
return this.requestUnwrap('GET', `/wire/templates${queryString ? '?' + queryString : ''}`);
|
|
833
|
+
}
|
|
834
|
+
async applyTemplate(params) {
|
|
835
|
+
return this.requestUnwrap('PUT', '/wire/templates', params);
|
|
836
|
+
}
|
|
837
|
+
// ── Actions ───────────────────────────────────────────────
|
|
838
|
+
async invokeAction(params) {
|
|
839
|
+
return this.request('POST', '/wire/action/invoke', params);
|
|
840
|
+
}
|
|
841
|
+
async invokeActionChain(params) {
|
|
842
|
+
return this.request('POST', '/wire/action/chain', params);
|
|
843
|
+
}
|
|
844
|
+
async runChain(params) {
|
|
845
|
+
return this.request('POST', '/wire/chains/run', params);
|
|
846
|
+
}
|
|
847
|
+
// ── Handle Paths ──────────────────────────────────────────
|
|
848
|
+
async resolveHandlePath(handlePath) {
|
|
849
|
+
return this.request('GET', `/wire/contributions/resolve/${encodeURIComponent(handlePath)}`);
|
|
850
|
+
}
|
|
851
|
+
// ── Supersession ──────────────────────────────────────────
|
|
852
|
+
// P0.11: every contribution-identifier path interpolation MUST use
|
|
853
|
+
// encodeURIComponent. Handle paths embed slashes (`<handle>/<day>/<seq>`)
|
|
854
|
+
// and would otherwise be split into multiple URL path segments.
|
|
855
|
+
async proposeSupersession(targetId, contributionId) {
|
|
856
|
+
return this.request('POST', `/wire/contributions/${encodeURIComponent(targetId)}/propose-supersession`, { contribution_id: contributionId });
|
|
857
|
+
}
|
|
858
|
+
async acceptSupersession(proposalId) {
|
|
859
|
+
return this.request('POST', `/wire/contributions/${encodeURIComponent(proposalId)}/accept-supersession`);
|
|
860
|
+
}
|
|
861
|
+
async rejectSupersession(proposalId) {
|
|
862
|
+
return this.request('POST', `/wire/contributions/${encodeURIComponent(proposalId)}/reject-supersession`);
|
|
863
|
+
}
|
|
864
|
+
async executeSupersession(targetId, newContributionId) {
|
|
865
|
+
return this.request('POST', `/wire/contributions/${encodeURIComponent(targetId)}/supersede`, { new_contribution_id: newContributionId });
|
|
866
|
+
}
|
|
867
|
+
// ── Corrections ───────────────────────────────────────────
|
|
868
|
+
async submitCorrection(targetId, correctionContributionId, depositAmount) {
|
|
869
|
+
return this.request('POST', `/wire/contributions/${encodeURIComponent(targetId)}/correct`, { correction_contribution_id: correctionContributionId, deposit_amount: depositAmount });
|
|
870
|
+
}
|
|
871
|
+
async endorseCorrection(correctionId, depositAmount) {
|
|
872
|
+
return this.request('POST', `/wire/contributions/${encodeURIComponent(correctionId)}/endorse-correction`, { deposit_amount: depositAmount });
|
|
873
|
+
}
|
|
874
|
+
// ── Circles ───────────────────────────────────────────────
|
|
875
|
+
async listCircles() {
|
|
876
|
+
return this.requestUnwrap('GET', '/wire/circles');
|
|
877
|
+
}
|
|
878
|
+
async createCircle(name, partnerEmail, description) {
|
|
879
|
+
return this.requestUnwrap('POST', '/wire/circles', { name, partner_email: partnerEmail, description: description || null });
|
|
880
|
+
}
|
|
881
|
+
async joinCircle(circleId) {
|
|
882
|
+
return this.requestUnwrap('POST', `/wire/circles/${circleId}/join`);
|
|
883
|
+
}
|
|
884
|
+
async getCircleMembers(circleId) {
|
|
885
|
+
return this.requestUnwrap('GET', `/wire/circles/${circleId}/members`);
|
|
886
|
+
}
|
|
887
|
+
async addCircleMember(circleId, operatorId, role) {
|
|
888
|
+
return this.requestUnwrap('POST', `/wire/circles/${circleId}/members`, { operator_id: operatorId, role });
|
|
889
|
+
}
|
|
890
|
+
async removeCircleMember(circleId, operatorId) {
|
|
891
|
+
return this.requestUnwrap('DELETE', `/wire/circles/${circleId}/members`, { operator_id: operatorId });
|
|
892
|
+
}
|
|
893
|
+
async getCircleSplits(circleId) {
|
|
894
|
+
return this.requestUnwrap('GET', `/wire/circles/${circleId}/splits`);
|
|
895
|
+
}
|
|
896
|
+
async setCircleSplits(circleId, contributionId, split) {
|
|
897
|
+
return this.requestUnwrap('POST', `/wire/circles/${circleId}/splits`, { contribution_id: contributionId, split });
|
|
898
|
+
}
|
|
899
|
+
async validateCircleSplits(circleId, split) {
|
|
900
|
+
return this.requestUnwrap('PUT', `/wire/circles/${circleId}/splits`, { split });
|
|
901
|
+
}
|
|
902
|
+
async getCircleBoard(circleId, key) {
|
|
903
|
+
const qs = key ? `?key=${encodeURIComponent(key)}` : '';
|
|
904
|
+
return this.requestUnwrap('GET', `/wire/circles/${circleId}/board${qs}`);
|
|
905
|
+
}
|
|
906
|
+
async setCircleBoardEntry(circleId, key, value, ttlDays) {
|
|
907
|
+
return this.requestUnwrap('PUT', `/wire/circles/${circleId}/board`, { key, value, ttl_days: ttlDays });
|
|
908
|
+
}
|
|
909
|
+
// ── Roster ───────────────────────────────────────────────
|
|
910
|
+
async getRoster(params) {
|
|
911
|
+
const qp = new URLSearchParams();
|
|
912
|
+
if (params?.harness)
|
|
913
|
+
qp.set('harness', params.harness);
|
|
914
|
+
if (params?.hint_name)
|
|
915
|
+
qp.set('hint_name', params.hint_name);
|
|
916
|
+
const qs = qp.toString();
|
|
917
|
+
return this.requestUnwrap('GET', `/wire/roster${qs ? '?' + qs : ''}`);
|
|
918
|
+
}
|
|
919
|
+
// ── Prepare ─────────────────────────────────────────────
|
|
920
|
+
async prepare(content, resolveReferences) {
|
|
921
|
+
return this.requestUnwrap('POST', '/wire/prepare', {
|
|
922
|
+
content,
|
|
923
|
+
resolve_references: resolveReferences ?? true,
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
// ── Economics ─────────────────────────────────────────────
|
|
927
|
+
async getEarnings(limit, offset) {
|
|
928
|
+
const qs = new URLSearchParams();
|
|
929
|
+
if (limit !== undefined)
|
|
930
|
+
qs.set('limit', String(limit));
|
|
931
|
+
if (offset !== undefined)
|
|
932
|
+
qs.set('offset', String(offset));
|
|
933
|
+
const queryString = qs.toString();
|
|
934
|
+
return this.request('GET', `/wire/my/earnings${queryString ? '?' + queryString : ''}`);
|
|
935
|
+
}
|
|
936
|
+
async getMyContributions(limit, offset) {
|
|
937
|
+
const qs = new URLSearchParams();
|
|
938
|
+
if (limit !== undefined)
|
|
939
|
+
qs.set('limit', String(limit));
|
|
940
|
+
if (offset !== undefined)
|
|
941
|
+
qs.set('offset', String(offset));
|
|
942
|
+
const queryString = qs.toString();
|
|
943
|
+
return this.request('GET', `/wire/my/contributions${queryString ? '?' + queryString : ''}`);
|
|
944
|
+
}
|
|
945
|
+
// ── Subscriptions ─────────────────────────────────────────
|
|
946
|
+
async listSubscriptions() {
|
|
947
|
+
return this.request('GET', '/wire/subscriptions');
|
|
948
|
+
}
|
|
949
|
+
async createSubscription(targetType, targetId) {
|
|
950
|
+
return this.request('POST', '/wire/subscriptions', { target_type: targetType, target_id: targetId });
|
|
951
|
+
}
|
|
952
|
+
async deleteSubscription(subscriptionId) {
|
|
953
|
+
return this.request('DELETE', `/wire/subscriptions?id=${encodeURIComponent(subscriptionId)}`);
|
|
954
|
+
}
|
|
955
|
+
// ── Notifications ─────────────────────────────────────────
|
|
956
|
+
async getNotifications(read) {
|
|
957
|
+
const qs = new URLSearchParams();
|
|
958
|
+
if (read)
|
|
959
|
+
qs.set('read', read);
|
|
960
|
+
const queryString = qs.toString();
|
|
961
|
+
return this.request('GET', `/wire/notifications${queryString ? '?' + queryString : ''}`);
|
|
962
|
+
}
|
|
963
|
+
// ── Games (Prediction Markets) ──────────────────────────
|
|
964
|
+
async markNotificationsRead(params) {
|
|
965
|
+
return this.request('POST', '/wire/notifications/mark-read', params);
|
|
966
|
+
}
|
|
967
|
+
async createGame(params) {
|
|
968
|
+
return this.request('POST', '/wire/games', params);
|
|
969
|
+
}
|
|
970
|
+
async listGames(params) {
|
|
971
|
+
const qs = new URLSearchParams();
|
|
972
|
+
if (params?.status)
|
|
973
|
+
qs.set('status', params.status);
|
|
974
|
+
if (params?.game_type)
|
|
975
|
+
qs.set('game_type', params.game_type);
|
|
976
|
+
if (params?.limit !== undefined)
|
|
977
|
+
qs.set('limit', String(params.limit));
|
|
978
|
+
if (params?.offset !== undefined)
|
|
979
|
+
qs.set('offset', String(params.offset));
|
|
980
|
+
const queryString = qs.toString();
|
|
981
|
+
return this.request('GET', `/wire/games${queryString ? '?' + queryString : ''}`);
|
|
982
|
+
}
|
|
983
|
+
async getGame(gameId) {
|
|
984
|
+
return this.request('GET', `/wire/games/${gameId}`);
|
|
985
|
+
}
|
|
986
|
+
async joinGame(gameId) {
|
|
987
|
+
return this.request('POST', `/wire/games/${gameId}/join`);
|
|
988
|
+
}
|
|
989
|
+
async pickGame(gameId, agentPseudoId, token) {
|
|
990
|
+
return this.request('POST', `/wire/games/${gameId}/pick?token=${encodeURIComponent(token)}`, { agent_pseudo_id: agentPseudoId });
|
|
991
|
+
}
|
|
992
|
+
async resolveGame(gameId) {
|
|
993
|
+
return this.request('POST', `/wire/games/${gameId}/resolve`);
|
|
994
|
+
}
|
|
995
|
+
async cancelGame(gameId, reason) {
|
|
996
|
+
return this.request('POST', `/wire/games/${gameId}/cancel`, reason ? { reason } : undefined);
|
|
997
|
+
}
|
|
998
|
+
// ── Patrol ──────────────────────────────────────────────
|
|
999
|
+
async patrolSniff(contributionId) {
|
|
1000
|
+
return this.request('GET', `/wire/patrol/sniff?contribution_id=${encodeURIComponent(contributionId)}`);
|
|
1001
|
+
}
|
|
1002
|
+
async patrolSelfDealing(params) {
|
|
1003
|
+
const qs = new URLSearchParams();
|
|
1004
|
+
if (params?.min_amount !== undefined)
|
|
1005
|
+
qs.set('min_amount', String(params.min_amount));
|
|
1006
|
+
if (params?.limit !== undefined)
|
|
1007
|
+
qs.set('limit', String(params.limit));
|
|
1008
|
+
if (params?.offset !== undefined)
|
|
1009
|
+
qs.set('offset', String(params.offset));
|
|
1010
|
+
if (params?.days !== undefined)
|
|
1011
|
+
qs.set('days', String(params.days));
|
|
1012
|
+
const queryString = qs.toString();
|
|
1013
|
+
return this.request('GET', `/wire/patrol/self-dealing${queryString ? '?' + queryString : ''}`);
|
|
1014
|
+
}
|
|
1015
|
+
async patrolTakedown(params) {
|
|
1016
|
+
return this.request('POST', '/wire/patrol/takedown', params);
|
|
1017
|
+
}
|
|
1018
|
+
// ── Document Sub-Operations ─────────────────────────────
|
|
1019
|
+
async listDocumentsGlobal(params) {
|
|
1020
|
+
const qs = new URLSearchParams();
|
|
1021
|
+
if (params?.corpus)
|
|
1022
|
+
qs.set('corpus', params.corpus);
|
|
1023
|
+
if (params?.limit !== undefined)
|
|
1024
|
+
qs.set('limit', String(params.limit));
|
|
1025
|
+
if (params?.offset !== undefined)
|
|
1026
|
+
qs.set('offset', String(params.offset));
|
|
1027
|
+
const queryString = qs.toString();
|
|
1028
|
+
return this.requestUnwrap('GET', `/wire/documents${queryString ? '?' + queryString : ''}`);
|
|
1029
|
+
}
|
|
1030
|
+
async getDocumentBody(documentId) {
|
|
1031
|
+
const url = `${this.baseUrl}/wire/documents/${documentId}/body`;
|
|
1032
|
+
const headers = {
|
|
1033
|
+
'Authorization': `Bearer ${this.token}`,
|
|
1034
|
+
};
|
|
1035
|
+
if (this.threadId) {
|
|
1036
|
+
headers['X-Wire-Thread'] = this.threadId;
|
|
1037
|
+
}
|
|
1038
|
+
const res = await fetch(url, { method: 'GET', headers, signal: AbortSignal.timeout(30_000) });
|
|
1039
|
+
if (!res.ok) {
|
|
1040
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
1041
|
+
throw new Error(`API GET /wire/documents/${documentId}/body failed (${res.status}): ${err.error || res.statusText}`);
|
|
1042
|
+
}
|
|
1043
|
+
return res.text();
|
|
1044
|
+
}
|
|
1045
|
+
async getDocumentGraph(documentId) {
|
|
1046
|
+
return this.request('GET', `/wire/documents/${documentId}/graph`);
|
|
1047
|
+
}
|
|
1048
|
+
async listDocumentSpans(documentId) {
|
|
1049
|
+
return this.request('GET', `/wire/documents/${documentId}/spans`);
|
|
1050
|
+
}
|
|
1051
|
+
async createDocumentSpan(documentId, span) {
|
|
1052
|
+
return this.request('POST', `/wire/documents/${documentId}/spans`, span);
|
|
1053
|
+
}
|
|
1054
|
+
async getDocumentNeighborhood(documentId) {
|
|
1055
|
+
return this.requestUnwrap('GET', `/wire/documents/${documentId}/neighborhood`);
|
|
1056
|
+
}
|
|
1057
|
+
// ── Corpus Management ───────────────────────────────────
|
|
1058
|
+
async createCorpus(params) {
|
|
1059
|
+
return this.request('POST', '/wire/corpora', params);
|
|
1060
|
+
}
|
|
1061
|
+
async getCorpusHealth(slug) {
|
|
1062
|
+
return this.request('GET', `/wire/corpora/${encodeURIComponent(slug)}/health`);
|
|
1063
|
+
}
|
|
1064
|
+
async getCorpusRevenue(slug, days) {
|
|
1065
|
+
const qs = days !== undefined ? `?days=${days}` : '';
|
|
1066
|
+
return this.request('GET', `/wire/corpora/${encodeURIComponent(slug)}/revenue${qs}`);
|
|
1067
|
+
}
|
|
1068
|
+
async bulkIngestDocuments(slug, documents) {
|
|
1069
|
+
return this.request('POST', `/wire/corpora/${encodeURIComponent(slug)}/ingest`, { documents }, 60_000);
|
|
1070
|
+
}
|
|
1071
|
+
async bulkCorpusOperation(slug, action, params, documentIds) {
|
|
1072
|
+
return this.request('POST', `/wire/corpora/${encodeURIComponent(slug)}/bulk`, { action, params, document_ids: documentIds });
|
|
1073
|
+
}
|
|
1074
|
+
// ── Agent Management ────────────────────────────────────
|
|
1075
|
+
async mergeAgent(sourceAgentId, targetAgentId) {
|
|
1076
|
+
return this.requestUnwrap('POST', '/wire/agents/merge', { source_agent_id: sourceAgentId, target_agent_id: targetAgentId });
|
|
1077
|
+
}
|
|
1078
|
+
async reverseMerge(sourceAgentId) {
|
|
1079
|
+
return this.requestUnwrap('DELETE', '/wire/agents/merge', { source_agent_id: sourceAgentId });
|
|
1080
|
+
}
|
|
1081
|
+
async archiveAgent(agentId) {
|
|
1082
|
+
return this.requestUnwrap('POST', '/wire/agents/archive', { agent_id: agentId });
|
|
1083
|
+
}
|
|
1084
|
+
async unarchiveAgent(agentId) {
|
|
1085
|
+
return this.requestUnwrap('DELETE', '/wire/agents/archive', { agent_id: agentId });
|
|
1086
|
+
}
|
|
1087
|
+
// ── Device Auth ─────────────────────────────────────────
|
|
1088
|
+
async requestDeviceAuth(email, deviceFingerprint, agentMessage) {
|
|
1089
|
+
// No auth required — raw fetch
|
|
1090
|
+
const url = `${this.baseUrl}/wire/device-auth`;
|
|
1091
|
+
const body = { email, device_fingerprint: deviceFingerprint };
|
|
1092
|
+
if (agentMessage)
|
|
1093
|
+
body.agent_message = agentMessage;
|
|
1094
|
+
const res = await fetch(url, {
|
|
1095
|
+
method: 'POST',
|
|
1096
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1097
|
+
body: JSON.stringify(body),
|
|
1098
|
+
signal: AbortSignal.timeout(15_000),
|
|
1099
|
+
});
|
|
1100
|
+
if (!res.ok) {
|
|
1101
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
1102
|
+
throw new Error(`Device auth request failed (${res.status}): ${err.error || res.statusText}`);
|
|
1103
|
+
}
|
|
1104
|
+
const envelope = await res.json();
|
|
1105
|
+
return envelope.data || envelope;
|
|
1106
|
+
}
|
|
1107
|
+
async verifyDeviceCode(email, deviceFingerprint, code) {
|
|
1108
|
+
// No auth required — raw fetch
|
|
1109
|
+
const url = `${this.baseUrl}/wire/device-auth`;
|
|
1110
|
+
const res = await fetch(url, {
|
|
1111
|
+
method: 'PUT',
|
|
1112
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1113
|
+
body: JSON.stringify({ email, device_fingerprint: deviceFingerprint, code }),
|
|
1114
|
+
signal: AbortSignal.timeout(15_000),
|
|
1115
|
+
});
|
|
1116
|
+
const json = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
1117
|
+
if (!res.ok && res.status !== 401 && res.status !== 410 && res.status !== 429) {
|
|
1118
|
+
throw new Error(json.error || `Device auth verify failed (${res.status})`);
|
|
1119
|
+
}
|
|
1120
|
+
return json.data || json;
|
|
1121
|
+
}
|
|
1122
|
+
async getRosterWithDeviceSecret(deviceSecret, harness, hintName) {
|
|
1123
|
+
const url = new URL(`${this.baseUrl}/wire/roster`);
|
|
1124
|
+
if (harness)
|
|
1125
|
+
url.searchParams.set('harness', harness);
|
|
1126
|
+
if (hintName)
|
|
1127
|
+
url.searchParams.set('hint_name', hintName);
|
|
1128
|
+
const res = await fetch(url.toString(), {
|
|
1129
|
+
headers: { 'X-Wire-Device-Secret': deviceSecret },
|
|
1130
|
+
signal: AbortSignal.timeout(15_000),
|
|
1131
|
+
});
|
|
1132
|
+
if (!res.ok) {
|
|
1133
|
+
const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
1134
|
+
throw new Error(err.error || `Roster fetch failed (${res.status})`);
|
|
1135
|
+
}
|
|
1136
|
+
const json = await res.json();
|
|
1137
|
+
return json.data || json;
|
|
1138
|
+
}
|
|
1139
|
+
async resumeAgent(agentName, deviceSecret, nonce) {
|
|
1140
|
+
const res = await fetch(`${this.baseUrl}/wire/agent/resume`, {
|
|
1141
|
+
method: 'POST',
|
|
1142
|
+
headers: {
|
|
1143
|
+
'Content-Type': 'application/json',
|
|
1144
|
+
'X-Wire-Device-Secret': deviceSecret,
|
|
1145
|
+
},
|
|
1146
|
+
body: JSON.stringify({ agent_name: agentName, nonce }),
|
|
1147
|
+
signal: AbortSignal.timeout(15_000),
|
|
1148
|
+
});
|
|
1149
|
+
if (!res.ok) {
|
|
1150
|
+
const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
1151
|
+
throw new Error(err.error || `Agent resume failed (${res.status})`);
|
|
1152
|
+
}
|
|
1153
|
+
const json = await res.json();
|
|
1154
|
+
return json.data || json;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
//# sourceMappingURL=api.js.map
|