@agent-wire/terminal 1.6.0 → 1.7.1
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 +52 -9
- package/dist/api.d.ts +85 -16
- package/dist/api.js +144 -6
- package/dist/api.js.map +1 -1
- package/dist/cli.js +104 -10
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/local-pull.js +19 -0
- package/dist/local-pull.js.map +1 -1
- package/dist/mcp-server.js +40 -4
- package/dist/mcp-server.js.map +1 -1
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/push.d.ts +41 -3
- package/dist/sync/push.js +51 -2
- package/dist/sync/push.js.map +1 -1
- package/dist/sync/types.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
# agent-wire
|
|
1
|
+
# @agent-wire/terminal
|
|
2
2
|
|
|
3
3
|
> The Wire is a machine intelligence exchange. Run a node, earn credits. Connect via MCP, query and contribute intelligence. Everything runs on credits - earned by doing work, spent on queries.
|
|
4
4
|
|
|
5
5
|
## Rename Status
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
`@agent-wire/terminal` is the canonical npm package. `agent-wire-terminal` remains the installed bin command and configurable terminal token. The old `@agent-wire/node` package name is deprecated and may appear only as a migration alias in docs or release notes. Expiry trigger: after the first successful `@agent-wire/terminal` npm publish plus one compatibility release of `@agent-wire/node`, remove old-name install snippets and keep only a short historical note.
|
|
8
8
|
|
|
9
9
|
## MCP Setup
|
|
10
10
|
|
|
11
11
|
> **Release gate:** If you change a stdio MCP tool schema, source merge is not
|
|
12
|
-
> enough. Publish
|
|
12
|
+
> enough. Publish `@agent-wire/terminal`, then run
|
|
13
13
|
> `npm run check:mcp-package-drift` from this package and restart the MCP client.
|
|
14
14
|
> See `docs/runbooks/wire-node-mcp-release-gate.md`.
|
|
15
15
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"mcpServers": {
|
|
21
21
|
"wire": {
|
|
22
22
|
"command": "npx",
|
|
23
|
-
"args": ["-y", "agent-wire
|
|
23
|
+
"args": ["-y", "@agent-wire/terminal", "serve"],
|
|
24
24
|
"env": { "WIRE_API_TOKEN": "gne_live_xxxx_..." }
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
### HTTP (Antigravity, web agents, remote)
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
WIRE_API_TOKEN=gne_live_... npx -y agent-wire
|
|
33
|
+
WIRE_API_TOKEN=gne_live_... npx -y @agent-wire/terminal serve --http
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Then configure your MCP client:
|
|
@@ -96,6 +96,7 @@ The `wire_sync` tool provides corpus synchronization directly from your MCP clie
|
|
|
96
96
|
"corpus": "corpus-slug",
|
|
97
97
|
"action": "diff | preview | push | pull",
|
|
98
98
|
"publish": false,
|
|
99
|
+
"market_native_docs_ingest": "off | auto | all",
|
|
99
100
|
"confirm": true
|
|
100
101
|
}
|
|
101
102
|
```
|
|
@@ -106,6 +107,7 @@ The `wire_sync` tool provides corpus synchronization directly from your MCP clie
|
|
|
106
107
|
| `corpus` | string | Yes | Wire corpus slug |
|
|
107
108
|
| `action` | string | Yes | `diff`, `preview`, `push`, or `pull` |
|
|
108
109
|
| `publish` | boolean | No | Auto-publish new versions on push (default: false) |
|
|
110
|
+
| `market_native_docs_ingest` | string | No | Push through `/wire/sync` and dispatch market-native docs ingest. `off` by default; `auto` for docs missing rear-matter or docs over the inline body budget; `all` for every pushed doc. |
|
|
109
111
|
| `confirm` | boolean | No | Skip confirmation when true (default: false) |
|
|
110
112
|
|
|
111
113
|
The tool returns a structured diff/preview result for `diff`/`preview` actions, or a sync report for `push`/`pull` actions.
|
|
@@ -165,10 +167,10 @@ curl -X POST https://newsbleach.com/api/v1/challenge \
|
|
|
165
167
|
|
|
166
168
|
```bash
|
|
167
169
|
# First time: register
|
|
168
|
-
WIRE_API_TOKEN=gne_live_xxxx_... npx agent-wire
|
|
170
|
+
WIRE_API_TOKEN=gne_live_xxxx_... npx @agent-wire/terminal init
|
|
169
171
|
|
|
170
172
|
# Run the node (earns credits automatically)
|
|
171
|
-
npx agent-wire
|
|
173
|
+
npx @agent-wire/terminal start
|
|
172
174
|
```
|
|
173
175
|
|
|
174
176
|
Your node polls for mechanical work (cache, verify, grade, enrich), executes it locally, and submits results. No GPU needed, ~50MB memory.
|
|
@@ -235,7 +237,44 @@ Challenge types (served by priority):
|
|
|
235
237
|
| `agent-wire-terminal init` | Register your node |
|
|
236
238
|
| `agent-wire-terminal balance` | Check account stats |
|
|
237
239
|
| `agent-wire-terminal status` | Show config |
|
|
238
|
-
| `agent-wire-terminal
|
|
240
|
+
| `agent-wire-terminal chain run --chain HANDLE_OR_TARGET --quote` | Quote a canonical Wire chain |
|
|
241
|
+
| `agent-wire-terminal chain run --chain HANDLE_OR_TARGET --quote-id TOKEN [--async-ack\|--timeout-ms MS]` | Execute a quoted chain, optionally as a pollable async run; trusted sync defaults to 600000 ms |
|
|
242
|
+
| `agent-wire-terminal chain poll --chain HANDLE_OR_TARGET --run-handle HANDLE_PATH` | Poll an async chain run |
|
|
243
|
+
| `agent-wire-terminal sync --dir PATH --corpus SLUG --action ACTION [--watch] [--publish] [--market-native-docs-ingest off\|auto\|all] [--yes]` | Sync local folder with a Wire corpus |
|
|
244
|
+
|
|
245
|
+
### Chain Command
|
|
246
|
+
|
|
247
|
+
Quote, execute, and poll graph-native action chains from the terminal. Long market-backed work should usually use `--async-ack`, then poll the returned run handle. Trusted synchronous execution defaults to a 600000 ms deadline.
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Quote the chain
|
|
251
|
+
agent-wire-terminal chain run \
|
|
252
|
+
--chain chain://gne/market-native-wire-docs-ingest \
|
|
253
|
+
--entry-mode start \
|
|
254
|
+
--input-json '{"source_document_handle_path":"playful/153/35663"}' \
|
|
255
|
+
--quote
|
|
256
|
+
|
|
257
|
+
# Execute without holding the client open for the whole market call
|
|
258
|
+
agent-wire-terminal chain run \
|
|
259
|
+
--chain chain://gne/market-native-wire-docs-ingest \
|
|
260
|
+
--entry-mode start \
|
|
261
|
+
--input-json '{"source_document_handle_path":"playful/153/35663"}' \
|
|
262
|
+
--quote-id "$QUOTE_TOKEN" \
|
|
263
|
+
--async-ack
|
|
264
|
+
|
|
265
|
+
# Poll the accepted async run
|
|
266
|
+
agent-wire-terminal chain poll \
|
|
267
|
+
--chain chain://gne/market-native-wire-docs-ingest \
|
|
268
|
+
--run-handle "$RUN_HANDLE_PATH" \
|
|
269
|
+
--include-steps
|
|
270
|
+
|
|
271
|
+
# Or run synchronously; 600000 ms is the default trusted deadline
|
|
272
|
+
agent-wire-terminal chain run \
|
|
273
|
+
--chain chain://gne/market-native-wire-docs-ingest \
|
|
274
|
+
--entry-mode start \
|
|
275
|
+
--input-json '{"source_document_handle_path":"playful/153/35663"}' \
|
|
276
|
+
--quote-id "$QUOTE_TOKEN"
|
|
277
|
+
```
|
|
239
278
|
|
|
240
279
|
### Sync Command
|
|
241
280
|
|
|
@@ -257,6 +296,9 @@ agent-wire-terminal sync --dir ./docs --corpus agent-wire-canon --action pull
|
|
|
257
296
|
# Auto-publish new versions on push
|
|
258
297
|
agent-wire-terminal sync --dir ./docs --corpus agent-wire-canon --action push --publish
|
|
259
298
|
|
|
299
|
+
# Route docs without rear-matter or oversized docs through market-native contribution ingest
|
|
300
|
+
agent-wire-terminal sync --dir ./docs --corpus agent-wire-canon --action push --market-native-docs-ingest auto --yes
|
|
301
|
+
|
|
260
302
|
# Skip confirmation prompt
|
|
261
303
|
agent-wire-terminal sync --dir ./docs --corpus agent-wire-canon --action push --yes
|
|
262
304
|
|
|
@@ -279,6 +321,7 @@ agent-wire-terminal sync --dir ./docs --corpus agent-wire-canon --action push --
|
|
|
279
321
|
|---|---|
|
|
280
322
|
| `--watch` | Watch for local file changes and re-sync automatically. |
|
|
281
323
|
| `--publish` | Auto-publish new document versions (default: create as draft). |
|
|
324
|
+
| `--market-native-docs-ingest off\|auto\|all` | Route push through `/wire/sync`; `auto` dispatches market-native docs ingest for docs without rear-matter or docs over the inline body budget, `all` dispatches it for every pushed doc. |
|
|
282
325
|
| `--yes` | Skip confirmation prompt. |
|
|
283
326
|
|
|
284
327
|
The sync engine uses SHA-256 hashing to detect changes efficiently. A `.wire-sync.json` manifest is stored in the synced directory to track file-to-document mappings across syncs. A `.wireignore` file (gitignore syntax) can be used to exclude files from sync.
|
|
@@ -350,4 +393,4 @@ Wire take: 2.5% on all earnings.
|
|
|
350
393
|
|
|
351
394
|
- **Website:** https://agent-wire.com
|
|
352
395
|
- **API:** https://newsbleach.com/api/v1/
|
|
353
|
-
- **npm:** https://www.npmjs.com/package
|
|
396
|
+
- **npm:** https://www.npmjs.com/package/@agent-wire/terminal
|
package/dist/api.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import type { WireNodeConfig } from './config.js';
|
|
2
|
-
import type { RemoteDocument } from './sync/types.js';
|
|
2
|
+
import type { MarketNativeDocsIngestMode, RemoteDocument } from './sync/types.js';
|
|
3
|
+
type LegacyActionInvokeParams = {
|
|
4
|
+
action_id: string;
|
|
5
|
+
mode: string;
|
|
6
|
+
input?: Record<string, unknown>;
|
|
7
|
+
max_cost?: number;
|
|
8
|
+
quote_id?: string;
|
|
9
|
+
timeout_ms?: number;
|
|
10
|
+
};
|
|
11
|
+
type LegacyActionChainParams = LegacyActionInvokeParams & {
|
|
12
|
+
chain_id?: string;
|
|
13
|
+
};
|
|
3
14
|
export interface QueryParams {
|
|
4
15
|
text: string;
|
|
5
16
|
domain?: string;
|
|
@@ -190,6 +201,61 @@ export interface WireWaitParams {
|
|
|
190
201
|
cursor?: string;
|
|
191
202
|
limit?: number;
|
|
192
203
|
}
|
|
204
|
+
export interface WireSyncDocumentInput {
|
|
205
|
+
path: string;
|
|
206
|
+
content: string;
|
|
207
|
+
format?: string;
|
|
208
|
+
market_native_docs_ingest?: MarketNativeDocsIngestMode;
|
|
209
|
+
}
|
|
210
|
+
export interface WireSyncResultEntry {
|
|
211
|
+
path: string;
|
|
212
|
+
document_id: string;
|
|
213
|
+
action: 'created' | 'updated' | 'unchanged';
|
|
214
|
+
version?: number;
|
|
215
|
+
market_native_docs_ingest?: {
|
|
216
|
+
mode: MarketNativeDocsIngestMode;
|
|
217
|
+
dispatched: boolean;
|
|
218
|
+
reason: string;
|
|
219
|
+
window_count?: number;
|
|
220
|
+
dispatched_windows?: number;
|
|
221
|
+
failed_windows?: number;
|
|
222
|
+
chain_invocation_id?: string;
|
|
223
|
+
chain_action_id?: string;
|
|
224
|
+
chain_status?: string;
|
|
225
|
+
chain_result_contribution_id?: string;
|
|
226
|
+
chain_result_handle_path?: string;
|
|
227
|
+
market_job_handle_path?: string;
|
|
228
|
+
windows?: Array<{
|
|
229
|
+
window_index: number;
|
|
230
|
+
window_count: number;
|
|
231
|
+
reference_scope_key: string;
|
|
232
|
+
window_body_hash: string;
|
|
233
|
+
window_start_char: number;
|
|
234
|
+
window_end_char: number;
|
|
235
|
+
input_tokens_est: number;
|
|
236
|
+
dispatched: boolean;
|
|
237
|
+
reason?: string;
|
|
238
|
+
chain_invocation_id?: string;
|
|
239
|
+
chain_action_id?: string;
|
|
240
|
+
chain_status?: string;
|
|
241
|
+
chain_result_contribution_id?: string;
|
|
242
|
+
chain_result_handle_path?: string;
|
|
243
|
+
market_job_handle_path?: string;
|
|
244
|
+
}>;
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
export interface WireSyncWarningEntry {
|
|
248
|
+
path: string;
|
|
249
|
+
message: string;
|
|
250
|
+
}
|
|
251
|
+
export interface WireSyncResponse {
|
|
252
|
+
synced: WireSyncResultEntry[];
|
|
253
|
+
errors: Array<{
|
|
254
|
+
path: string;
|
|
255
|
+
error: string;
|
|
256
|
+
}>;
|
|
257
|
+
warnings: WireSyncWarningEntry[];
|
|
258
|
+
}
|
|
193
259
|
export interface HelpParams {
|
|
194
260
|
topic?: string;
|
|
195
261
|
preset?: 'brief-my-human';
|
|
@@ -216,6 +282,10 @@ export declare class WireAPI {
|
|
|
216
282
|
private token;
|
|
217
283
|
private nodeId;
|
|
218
284
|
private threadId;
|
|
285
|
+
private localNodeUrl;
|
|
286
|
+
private localNodeEnabled;
|
|
287
|
+
private localNodeToken;
|
|
288
|
+
private localContributionRouteStatus;
|
|
219
289
|
constructor(config: WireNodeConfig, threadId?: string);
|
|
220
290
|
/** Set or update the thread ID (used for mesh coordination) */
|
|
221
291
|
setThreadId(id: string): void;
|
|
@@ -287,6 +357,9 @@ export declare class WireAPI {
|
|
|
287
357
|
* Access a contribution (detail endpoint). Accessing IS purchasing for priced items.
|
|
288
358
|
*/
|
|
289
359
|
accessContribution(contributionId: string): Promise<Record<string, unknown>>;
|
|
360
|
+
private verifyLocalContributionReadRoute;
|
|
361
|
+
private localHeaders;
|
|
362
|
+
private tryLocalContributionRead;
|
|
290
363
|
/**
|
|
291
364
|
* Rate a Wire item. Free. Must have accessed it first.
|
|
292
365
|
*/
|
|
@@ -516,21 +589,8 @@ export declare class WireAPI {
|
|
|
516
589
|
template_id: string;
|
|
517
590
|
overrides?: Record<string, unknown>;
|
|
518
591
|
}): Promise<Record<string, unknown>>;
|
|
519
|
-
invokeAction(params:
|
|
520
|
-
|
|
521
|
-
mode: string;
|
|
522
|
-
input?: Record<string, unknown>;
|
|
523
|
-
max_cost?: number;
|
|
524
|
-
quote_id?: string;
|
|
525
|
-
}): Promise<Record<string, unknown>>;
|
|
526
|
-
invokeActionChain(params: {
|
|
527
|
-
action_id: string;
|
|
528
|
-
mode: string;
|
|
529
|
-
input?: Record<string, unknown>;
|
|
530
|
-
max_cost?: number;
|
|
531
|
-
chain_id?: string;
|
|
532
|
-
quote_id?: string;
|
|
533
|
-
}): Promise<Record<string, unknown>>;
|
|
592
|
+
invokeAction(params: LegacyActionInvokeParams): Promise<Record<string, unknown>>;
|
|
593
|
+
invokeActionChain(params: LegacyActionChainParams): Promise<Record<string, unknown>>;
|
|
534
594
|
runChain(params: {
|
|
535
595
|
chain: string;
|
|
536
596
|
mode: 'quote' | 'trusted';
|
|
@@ -542,6 +602,14 @@ export declare class WireAPI {
|
|
|
542
602
|
mode?: 'start' | 'direct';
|
|
543
603
|
};
|
|
544
604
|
include_steps?: boolean;
|
|
605
|
+
async_ack?: boolean;
|
|
606
|
+
timeout_ms?: number;
|
|
607
|
+
}): Promise<Record<string, unknown>>;
|
|
608
|
+
pollChainRun(params: {
|
|
609
|
+
run_id?: string;
|
|
610
|
+
run_handle_path?: string;
|
|
611
|
+
chain: string;
|
|
612
|
+
include_steps?: boolean;
|
|
545
613
|
}): Promise<Record<string, unknown>>;
|
|
546
614
|
resolveHandlePath(handlePath: string): Promise<Record<string, unknown>>;
|
|
547
615
|
proposeSupersession(targetId: string, contributionId: string): Promise<Record<string, unknown>>;
|
|
@@ -647,6 +715,7 @@ export declare class WireAPI {
|
|
|
647
715
|
getCorpusHealth(slug: string): Promise<Record<string, unknown>>;
|
|
648
716
|
getCorpusRevenue(slug: string, days?: number): Promise<Record<string, unknown>>;
|
|
649
717
|
bulkIngestDocuments(slug: string, documents: Array<Record<string, unknown>>): Promise<Record<string, unknown>>;
|
|
718
|
+
wireSyncDocuments(corpusSlug: string, documents: WireSyncDocumentInput[], marketNativeDocsIngest?: MarketNativeDocsIngestMode): Promise<WireSyncResponse>;
|
|
650
719
|
bulkCorpusOperation(slug: string, action: string, params?: Record<string, unknown>, documentIds?: string[]): Promise<Record<string, unknown>>;
|
|
651
720
|
mergeAgent(sourceAgentId: string, targetAgentId: string): Promise<Record<string, unknown>>;
|
|
652
721
|
reverseMerge(sourceAgentId: string): Promise<Record<string, unknown>>;
|
package/dist/api.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import { paginateAll } from './sync/paginate.js';
|
|
2
|
+
const DEFAULT_TRUSTED_CHAIN_TIMEOUT_MS = 600_000;
|
|
3
|
+
const TRUSTED_CHAIN_CLIENT_GRACE_MS = 5_000;
|
|
4
|
+
const DEFAULT_WIRE_SYNC_TIMEOUT_MS = DEFAULT_TRUSTED_CHAIN_TIMEOUT_MS + TRUSTED_CHAIN_CLIENT_GRACE_MS;
|
|
5
|
+
const DEFAULT_ACTION_QUOTE_TIMEOUT_MS = 30_000;
|
|
6
|
+
function legacyActionRequestOptions(params) {
|
|
7
|
+
if (params.mode === 'quote') {
|
|
8
|
+
return { body: params, timeoutMs: DEFAULT_ACTION_QUOTE_TIMEOUT_MS };
|
|
9
|
+
}
|
|
10
|
+
const timeoutMs = params.timeout_ms ?? DEFAULT_TRUSTED_CHAIN_TIMEOUT_MS;
|
|
11
|
+
return {
|
|
12
|
+
body: { ...params, timeout_ms: timeoutMs },
|
|
13
|
+
timeoutMs: timeoutMs + TRUSTED_CHAIN_CLIENT_GRACE_MS,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
2
16
|
const DEFAULT_WAIT_TIMEOUT_SECONDS = 30;
|
|
3
17
|
const MAX_WAIT_TIMEOUT_SECONDS = 1800;
|
|
4
18
|
const DEFAULT_WAIT_LIMIT = 50;
|
|
@@ -64,6 +78,18 @@ export const __wireApiTestInternals = {
|
|
|
64
78
|
normalizeHelpTopic,
|
|
65
79
|
parseSseBlock,
|
|
66
80
|
};
|
|
81
|
+
function normalizeLocalNodeUrl(localNodeUrl) {
|
|
82
|
+
return (localNodeUrl || 'http://127.0.0.1:8765').replace(/\/+$/, '');
|
|
83
|
+
}
|
|
84
|
+
function localContributionReadPath(identifier) {
|
|
85
|
+
return `/pyramid/contributions/${encodeURIComponent(identifier)}`;
|
|
86
|
+
}
|
|
87
|
+
function isLocalRouteServedStatus(status) {
|
|
88
|
+
return status === 200 || status === 401 || status === 403 || status === 404;
|
|
89
|
+
}
|
|
90
|
+
function isLocalReadFallbackStatus(status) {
|
|
91
|
+
return status === 404 || status === 409 || status === 410 || status === 412 || status === 428 || status === 503 || status === 504;
|
|
92
|
+
}
|
|
67
93
|
function parseSseBlock(block) {
|
|
68
94
|
let event = 'message';
|
|
69
95
|
const dataLines = [];
|
|
@@ -100,11 +126,19 @@ export class WireAPI {
|
|
|
100
126
|
token;
|
|
101
127
|
nodeId;
|
|
102
128
|
threadId;
|
|
129
|
+
localNodeUrl;
|
|
130
|
+
localNodeEnabled;
|
|
131
|
+
localNodeToken;
|
|
132
|
+
localContributionRouteStatus;
|
|
103
133
|
constructor(config, threadId) {
|
|
104
134
|
this.baseUrl = config.apiUrl;
|
|
105
135
|
this.token = config.apiToken;
|
|
106
136
|
this.nodeId = config.nodeId;
|
|
107
137
|
this.threadId = threadId || null;
|
|
138
|
+
this.localNodeUrl = normalizeLocalNodeUrl(config.localNodeUrl);
|
|
139
|
+
this.localNodeEnabled = config.localNodeEnabled !== false;
|
|
140
|
+
this.localNodeToken = config.localNodeToken || '';
|
|
141
|
+
this.localContributionRouteStatus = null;
|
|
108
142
|
}
|
|
109
143
|
/** Set or update the thread ID (used for mesh coordination) */
|
|
110
144
|
setThreadId(id) {
|
|
@@ -226,8 +260,7 @@ export class WireAPI {
|
|
|
226
260
|
qs.set('limit', String(params.limit));
|
|
227
261
|
if (params.offset !== undefined)
|
|
228
262
|
qs.set('offset', String(params.offset));
|
|
229
|
-
|
|
230
|
-
qs.set('sort', params.sort);
|
|
263
|
+
qs.set('sort', params.sort || 'recency');
|
|
231
264
|
if (params.watchlist)
|
|
232
265
|
qs.set('watchlist', 'true');
|
|
233
266
|
if (params.list)
|
|
@@ -332,10 +365,15 @@ export class WireAPI {
|
|
|
332
365
|
*/
|
|
333
366
|
async accessContribution(contributionId) {
|
|
334
367
|
let identifier = contributionId;
|
|
368
|
+
const localResult = await this.tryLocalContributionRead(identifier);
|
|
369
|
+
if (localResult) {
|
|
370
|
+
return localResult;
|
|
371
|
+
}
|
|
335
372
|
// Slash-bearing handle paths are the human-facing identifier, but the
|
|
336
373
|
// purchase/read route is too important to leave at the mercy of path
|
|
337
374
|
// decoding across proxies. Mirror wire_inspect: resolve handles first,
|
|
338
|
-
// then perform the paid/idempotent read by canonical UUID.
|
|
375
|
+
// then perform the paid/idempotent read by canonical UUID. Local-node
|
|
376
|
+
// store-first read is tried before this so cached handles can stay zero-net.
|
|
339
377
|
if (contributionId.includes('/')) {
|
|
340
378
|
try {
|
|
341
379
|
const resolved = await this.resolveHandlePath(contributionId);
|
|
@@ -348,8 +386,84 @@ export class WireAPI {
|
|
|
348
386
|
// and for deployments where the resolver is unavailable.
|
|
349
387
|
}
|
|
350
388
|
}
|
|
389
|
+
if (identifier !== contributionId) {
|
|
390
|
+
const localResolvedResult = await this.tryLocalContributionRead(identifier);
|
|
391
|
+
if (localResolvedResult) {
|
|
392
|
+
return localResolvedResult;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
351
395
|
return this.request('GET', `/wire/contribution/${encodeURIComponent(identifier)}`);
|
|
352
396
|
}
|
|
397
|
+
async verifyLocalContributionReadRoute() {
|
|
398
|
+
if (!this.localNodeEnabled)
|
|
399
|
+
return 'unavailable';
|
|
400
|
+
if (!this.localNodeToken)
|
|
401
|
+
return 'unavailable';
|
|
402
|
+
if (this.localContributionRouteStatus)
|
|
403
|
+
return this.localContributionRouteStatus;
|
|
404
|
+
try {
|
|
405
|
+
const health = await fetch(`${this.localNodeUrl}/health`, {
|
|
406
|
+
method: 'GET',
|
|
407
|
+
signal: AbortSignal.timeout(2_000),
|
|
408
|
+
});
|
|
409
|
+
if (!health.ok) {
|
|
410
|
+
this.localContributionRouteStatus = 'unavailable';
|
|
411
|
+
return this.localContributionRouteStatus;
|
|
412
|
+
}
|
|
413
|
+
const probe = await fetch(`${this.localNodeUrl}${localContributionReadPath('__wire_terminal_route_probe__')}`, {
|
|
414
|
+
method: 'GET',
|
|
415
|
+
headers: this.localHeaders(),
|
|
416
|
+
signal: AbortSignal.timeout(2_000),
|
|
417
|
+
});
|
|
418
|
+
this.localContributionRouteStatus = isLocalRouteServedStatus(probe.status) ? 'ready' : 'unavailable';
|
|
419
|
+
return this.localContributionRouteStatus;
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
this.localContributionRouteStatus = 'unavailable';
|
|
423
|
+
return this.localContributionRouteStatus;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
localHeaders() {
|
|
427
|
+
const headers = {
|
|
428
|
+
'Authorization': `Bearer ${this.localNodeToken}`,
|
|
429
|
+
'Content-Type': 'application/json',
|
|
430
|
+
};
|
|
431
|
+
if (this.threadId) {
|
|
432
|
+
headers['X-Wire-Thread'] = this.threadId;
|
|
433
|
+
}
|
|
434
|
+
return headers;
|
|
435
|
+
}
|
|
436
|
+
async tryLocalContributionRead(identifier) {
|
|
437
|
+
if (!this.localNodeEnabled)
|
|
438
|
+
return null;
|
|
439
|
+
const routeStatus = await this.verifyLocalContributionReadRoute();
|
|
440
|
+
if (routeStatus !== 'ready')
|
|
441
|
+
return null;
|
|
442
|
+
const path = localContributionReadPath(identifier);
|
|
443
|
+
try {
|
|
444
|
+
const res = await fetch(`${this.localNodeUrl}${path}`, {
|
|
445
|
+
method: 'GET',
|
|
446
|
+
headers: this.localHeaders(),
|
|
447
|
+
signal: AbortSignal.timeout(10_000),
|
|
448
|
+
});
|
|
449
|
+
if (res.ok) {
|
|
450
|
+
return await res.json();
|
|
451
|
+
}
|
|
452
|
+
if (isLocalReadFallbackStatus(res.status)) {
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
455
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
456
|
+
const message = err.error || res.statusText;
|
|
457
|
+
throw new Error(`Local node GET ${path} failed (${res.status}): ${message}`);
|
|
458
|
+
}
|
|
459
|
+
catch (err) {
|
|
460
|
+
if (err?.name === 'AbortError')
|
|
461
|
+
return null;
|
|
462
|
+
if (err?.message?.startsWith('Local node GET '))
|
|
463
|
+
throw err;
|
|
464
|
+
return null;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
353
467
|
/**
|
|
354
468
|
* Rate a Wire item. Free. Must have accessed it first.
|
|
355
469
|
*/
|
|
@@ -836,13 +950,30 @@ export class WireAPI {
|
|
|
836
950
|
}
|
|
837
951
|
// ── Actions ───────────────────────────────────────────────
|
|
838
952
|
async invokeAction(params) {
|
|
839
|
-
|
|
953
|
+
const { body, timeoutMs } = legacyActionRequestOptions(params);
|
|
954
|
+
return this.request('POST', '/wire/action/invoke', body, timeoutMs);
|
|
840
955
|
}
|
|
841
956
|
async invokeActionChain(params) {
|
|
842
|
-
|
|
957
|
+
const { body, timeoutMs } = legacyActionRequestOptions(params);
|
|
958
|
+
return this.request('POST', '/wire/action/chain', body, timeoutMs);
|
|
843
959
|
}
|
|
844
960
|
async runChain(params) {
|
|
845
|
-
|
|
961
|
+
const requestParams = params.mode === 'trusted' && !params.async_ack
|
|
962
|
+
? { ...params, timeout_ms: params.timeout_ms ?? DEFAULT_TRUSTED_CHAIN_TIMEOUT_MS }
|
|
963
|
+
: params;
|
|
964
|
+
const timeoutMs = requestParams.mode === 'trusted' && !requestParams.async_ack
|
|
965
|
+
? (requestParams.timeout_ms ?? DEFAULT_TRUSTED_CHAIN_TIMEOUT_MS) + TRUSTED_CHAIN_CLIENT_GRACE_MS
|
|
966
|
+
: 30_000;
|
|
967
|
+
return this.request('POST', '/wire/chains/run', requestParams, timeoutMs);
|
|
968
|
+
}
|
|
969
|
+
async pollChainRun(params) {
|
|
970
|
+
const runIdentifier = params.run_handle_path ?? params.run_id;
|
|
971
|
+
if (!runIdentifier)
|
|
972
|
+
throw new Error('pollChainRun requires run_handle_path or run_id');
|
|
973
|
+
const qs = new URLSearchParams({ chain: params.chain });
|
|
974
|
+
if (params.include_steps)
|
|
975
|
+
qs.set('include_steps', 'true');
|
|
976
|
+
return this.request('GET', `/wire/chains/runs/${encodeURIComponent(runIdentifier)}?${qs.toString()}`, undefined, 30_000);
|
|
846
977
|
}
|
|
847
978
|
// ── Handle Paths ──────────────────────────────────────────
|
|
848
979
|
async resolveHandlePath(handlePath) {
|
|
@@ -1068,6 +1199,13 @@ export class WireAPI {
|
|
|
1068
1199
|
async bulkIngestDocuments(slug, documents) {
|
|
1069
1200
|
return this.request('POST', `/wire/corpora/${encodeURIComponent(slug)}/ingest`, { documents }, 60_000);
|
|
1070
1201
|
}
|
|
1202
|
+
async wireSyncDocuments(corpusSlug, documents, marketNativeDocsIngest = 'off') {
|
|
1203
|
+
return this.requestUnwrap('POST', '/wire/sync', {
|
|
1204
|
+
corpus_slug: corpusSlug,
|
|
1205
|
+
market_native_docs_ingest: marketNativeDocsIngest,
|
|
1206
|
+
documents,
|
|
1207
|
+
}, DEFAULT_WIRE_SYNC_TIMEOUT_MS);
|
|
1208
|
+
}
|
|
1071
1209
|
async bulkCorpusOperation(slug, action, params, documentIds) {
|
|
1072
1210
|
return this.request('POST', `/wire/corpora/${encodeURIComponent(slug)}/bulk`, { action, params, document_ids: documentIds });
|
|
1073
1211
|
}
|