shinjuku-shielded 0.3.155 → 0.3.157
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 +6 -6
- package/manifest.json +4 -4
- package/package.json +3 -3
- package/shinjuku-wallet.mjs +285 -68
package/README.md
CHANGED
|
@@ -6,19 +6,19 @@ answers privately, in a terminal chat or for your agent app. Its `mcp`
|
|
|
6
6
|
command runs a local MCP server (stdio) for your agent. Your keys never
|
|
7
7
|
leave your machine.
|
|
8
8
|
|
|
9
|
-
This is version 0.3.
|
|
9
|
+
This is version 0.3.157. The npm packages `shinjuku-shield` and
|
|
10
10
|
`shinjuku-shielded` hold the same files. The command is `shinjuku`.
|
|
11
11
|
|
|
12
12
|
## Set up
|
|
13
13
|
|
|
14
14
|
```sh
|
|
15
|
-
npm install -g shinjuku@0.3.
|
|
15
|
+
npm install -g shinjuku@0.3.157
|
|
16
16
|
shinjuku setup
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Type the two lines as they are. `npx install shinjuku` does not work: npx
|
|
20
20
|
reads `install` as the name of another npm package. To set up without
|
|
21
|
-
installing, type `npx shinjuku@0.3.
|
|
21
|
+
installing, type `npx shinjuku@0.3.157 setup`.
|
|
22
22
|
|
|
23
23
|
Setup makes the wallet on this machine, a private passphrase file, and the
|
|
24
24
|
checked proof tools (about 191 MB), and writes `config.json`. It also writes
|
|
@@ -36,13 +36,13 @@ Every wallet command works after `shinjuku`, for example `shinjuku balance`,
|
|
|
36
36
|
Claude Code:
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
|
-
claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.
|
|
39
|
+
claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.157 mcp
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Claude Desktop (`claude_desktop_config.json`) or Cursor (`~/.cursor/mcp.json`):
|
|
43
43
|
|
|
44
44
|
```json
|
|
45
|
-
{ "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.
|
|
45
|
+
{ "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.157", "mcp"] } } }
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
On native Windows, if the host cannot find `npx`, use `"command": "cmd"` and
|
|
@@ -55,7 +55,7 @@ Codex (the Codex app and Codex CLI read the same file, `~/.codex/config.toml`):
|
|
|
55
55
|
```toml
|
|
56
56
|
[mcp_servers.shinjuku]
|
|
57
57
|
command = "npx"
|
|
58
|
-
args = ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.
|
|
58
|
+
args = ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.157", "mcp"]
|
|
59
59
|
startup_timeout_sec = 120
|
|
60
60
|
tool_timeout_sec = 300
|
|
61
61
|
```
|
package/manifest.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "carbon-shielded-wallet/bundle-manifest/v1",
|
|
3
3
|
"file": "shinjuku-wallet.mjs",
|
|
4
|
-
"sha256": "
|
|
5
|
-
"bytes":
|
|
6
|
-
"sourceCommit": "
|
|
4
|
+
"sha256": "46b6176b85190a52572566a760686111c9f01d07b8057e83a3ea1d76a20a3f5f",
|
|
5
|
+
"bytes": 9069628,
|
|
6
|
+
"sourceCommit": "4c41d8d68ac102c3b34f13def9057f631c923ce7",
|
|
7
7
|
"sourceDirty": false,
|
|
8
8
|
"installRecordMatchesLockfile": true,
|
|
9
9
|
"releaseRule": "valid only when two fresh npm ci --ignore-scripts builds on different OSes give the same sha256; installRecordMatchesLockfile true means every entry npm installed equals its package-lock.json entry and every entry not marked optional, devOptional included, is installed: an optional entry (a package for another platform) may be absent",
|
|
@@ -1038,5 +1038,5 @@
|
|
|
1038
1038
|
"version": "1.8.0"
|
|
1039
1039
|
}
|
|
1040
1040
|
],
|
|
1041
|
-
"publishedAt": "2026-11-
|
|
1041
|
+
"publishedAt": "2026-11-03T09:32:37.020Z"
|
|
1042
1042
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shinjuku-shielded",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.157",
|
|
4
4
|
"mcpName": "io.github.ShinjukuStaition/shinjuku-mcp",
|
|
5
5
|
"description": "Shinjuku Shielded, the private x402 facilitator on Solana: the self-custody wallet CLI and its MCP server. Shield, pay, and unshield USDC from any MCP agent, under caps you set.",
|
|
6
|
-
"shinjukuRelease": "
|
|
7
|
-
"shinjukuSha256": "
|
|
6
|
+
"shinjukuRelease": "46b6176b",
|
|
7
|
+
"shinjukuSha256": "46b6176b85190a52572566a760686111c9f01d07b8057e83a3ea1d76a20a3f5f",
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
9
9
|
"author": "Shinjuku Shielded",
|
|
10
10
|
"homepage": "https://github.com/ShinjukuStaition/shinjuku-shield#readme",
|
package/shinjuku-wallet.mjs
CHANGED
|
@@ -42618,6 +42618,15 @@ function markPhase(phase, outcome) {
|
|
|
42618
42618
|
} catch {
|
|
42619
42619
|
}
|
|
42620
42620
|
}
|
|
42621
|
+
function boundMarkPhase() {
|
|
42622
|
+
const write = scope.getStore();
|
|
42623
|
+
return (phase, outcome) => {
|
|
42624
|
+
try {
|
|
42625
|
+
write?.(phase, outcome);
|
|
42626
|
+
} catch {
|
|
42627
|
+
}
|
|
42628
|
+
};
|
|
42629
|
+
}
|
|
42621
42630
|
function poolReadOutcome(slot3, moved) {
|
|
42622
42631
|
let text3;
|
|
42623
42632
|
try {
|
|
@@ -42917,6 +42926,9 @@ function tunnelRefused(statusCode) {
|
|
|
42917
42926
|
}
|
|
42918
42927
|
function optimisticConnect(params, { proxyHost, proxyPort, closedInRow }) {
|
|
42919
42928
|
const target = String(params.path);
|
|
42929
|
+
const mark = boundMarkPhase();
|
|
42930
|
+
const startedAt = Date.now();
|
|
42931
|
+
let dials = 0;
|
|
42920
42932
|
const head = `CONNECT ${target} HTTP/1.1\r
|
|
42921
42933
|
${Object.entries(params.headers ?? {}).filter(([name, value2]) => value2 !== void 0 && !/[\r\n]/.test(`${name}${value2}`)).map(([name, value2]) => `${name}: ${value2}\r
|
|
42922
42934
|
`).join("")}\r
|
|
@@ -42969,6 +42981,7 @@ ${Object.entries(params.headers ?? {}).filter(([name, value2]) => value2 !== voi
|
|
|
42969
42981
|
if (first) pendingReject = reject;
|
|
42970
42982
|
reply = Buffer.alloc(0);
|
|
42971
42983
|
ready = false;
|
|
42984
|
+
dials += 1;
|
|
42972
42985
|
socket = net.connect(proxyPort, proxyHost);
|
|
42973
42986
|
socket.setNoDelay(true);
|
|
42974
42987
|
let connected = false;
|
|
@@ -42977,6 +42990,7 @@ ${Object.entries(params.headers ?? {}).filter(([name, value2]) => value2 !== voi
|
|
|
42977
42990
|
socket.write(head);
|
|
42978
42991
|
for (const chunk of sent) socket.write(chunk);
|
|
42979
42992
|
ready = true;
|
|
42993
|
+
mark("tunnel-sent", `dial${dials}`);
|
|
42980
42994
|
if (first) pendingReject = void 0;
|
|
42981
42995
|
resolve39();
|
|
42982
42996
|
});
|
|
@@ -42990,9 +43004,11 @@ ${Object.entries(params.headers ?? {}).filter(([name, value2]) => value2 !== voi
|
|
|
42990
43004
|
if (end < 0) return;
|
|
42991
43005
|
const status = Number(/^HTTP\/1\.[01] (\d{3})/.exec(reply.subarray(0, reply.indexOf("\r\n")).toString("latin1"))?.[1] ?? 0);
|
|
42992
43006
|
if (status !== 200) {
|
|
43007
|
+
mark("tunnel-refused", `http${status}`);
|
|
42993
43008
|
stream.destroy(tunnelRefused(status));
|
|
42994
43009
|
return;
|
|
42995
43010
|
}
|
|
43011
|
+
mark("tunnel-200", `ms${Date.now() - startedAt}_dial${dials}`);
|
|
42996
43012
|
open4 = true;
|
|
42997
43013
|
sent.length = 0;
|
|
42998
43014
|
closedInRow.delete(target);
|
|
@@ -43019,6 +43035,7 @@ ${Object.entries(params.headers ?? {}).filter(([name, value2]) => value2 !== voi
|
|
|
43019
43035
|
return;
|
|
43020
43036
|
}
|
|
43021
43037
|
const closed = (closedInRow.get(target) ?? 0) + 1;
|
|
43038
|
+
mark("tunnel-closed", `n${closed}`);
|
|
43022
43039
|
if (closed < TUNNEL_CLOSED_TRIES) {
|
|
43023
43040
|
closedInRow.set(target, closed);
|
|
43024
43041
|
dial(false).catch((error) => stream.destroy(error));
|
|
@@ -43042,6 +43059,7 @@ var init_tunnelGuard = __esm({
|
|
|
43042
43059
|
"wallet/src/net/tunnelGuard.mjs"() {
|
|
43043
43060
|
"use strict";
|
|
43044
43061
|
init_keepAlive();
|
|
43062
|
+
init_phaseTiming();
|
|
43045
43063
|
RUN_MARK = "SHINJUKU_WALLET_PROXIED";
|
|
43046
43064
|
TUNNEL_CLOSED_TRIES = 3;
|
|
43047
43065
|
}
|
|
@@ -67009,6 +67027,7 @@ var init_errorCodes = __esm({
|
|
|
67009
67027
|
"inference_no_provider",
|
|
67010
67028
|
"inference_origin_refused",
|
|
67011
67029
|
"inference_out_of_tokens",
|
|
67030
|
+
"inference_empty_answer",
|
|
67012
67031
|
// wallet_unshield of a balance in several accounts: the stage code while the automatic join runs (mcp/tools.mjs joiningStage).
|
|
67013
67032
|
"unshield_joining_accounts",
|
|
67014
67033
|
// unshield of a fixed amount in a terminal: its own join (joinForFixedSend, AB186) did not get the balance ready.
|
|
@@ -83564,15 +83583,19 @@ function memoryRequestMatches(record, { url, request, programId, anyProgram = fa
|
|
|
83564
83583
|
function dropOldAnswers(now) {
|
|
83565
83584
|
for (const [key, entry] of answers) if (now >= entry.atMs + MEMORY_ANSWER_KEEP_MS) answers.delete(key);
|
|
83566
83585
|
}
|
|
83567
|
-
function keepMemoryAnswer(record, resultBase64, now = Date.now()) {
|
|
83586
|
+
function keepMemoryAnswer(record, resultBase64, now = Date.now(), sellerHeaders = []) {
|
|
83568
83587
|
if (!isMemoryFingerprint(record?.fingerprint) || typeof resultBase64 !== "string") return;
|
|
83569
83588
|
dropOldAnswers(now);
|
|
83570
|
-
keepBounded(answers, record.fingerprint, { resultBase64, atMs: now });
|
|
83589
|
+
keepBounded(answers, record.fingerprint, { resultBase64, atMs: now, sellerHeaders: Array.isArray(sellerHeaders) ? sellerHeaders : [] });
|
|
83571
83590
|
}
|
|
83572
83591
|
function memoryAnswer(record, now = Date.now()) {
|
|
83573
83592
|
dropOldAnswers(now);
|
|
83574
83593
|
return isMemoryFingerprint(record?.fingerprint) ? answers.get(record.fingerprint)?.resultBase64 : void 0;
|
|
83575
83594
|
}
|
|
83595
|
+
function memoryAnswerHeaders(record, now = Date.now()) {
|
|
83596
|
+
dropOldAnswers(now);
|
|
83597
|
+
return (isMemoryFingerprint(record?.fingerprint) ? answers.get(record.fingerprint)?.sellerHeaders : void 0) ?? [];
|
|
83598
|
+
}
|
|
83576
83599
|
function forgetMemoryOnly() {
|
|
83577
83600
|
requests.clear();
|
|
83578
83601
|
answers.clear();
|
|
@@ -102203,7 +102226,7 @@ function floatOutcomeWords(code2, error, t) {
|
|
|
102203
102226
|
case "p03_float_answer_invalid_refund_pending": {
|
|
102204
102227
|
const amount = amountText(error?.paidAtomic, "the amount paid");
|
|
102205
102228
|
const fixable = floatSellerCanBeFixed(error);
|
|
102206
|
-
const seller = fixable && typeof error?.sellerReason === "string" ? ` ${p.The} refused this request (HTTP ${error.httpStatus}) and said why: ${JSON.stringify(error.sellerReason)}.` : fixable ? ` ${p.The} refused this request (HTTP ${error.httpStatus}) and said why in its first answer; the wallet does not keep ${p.the}'s words.` : typeof error?.sellerReason === "string" ? ` ${p.The} answered HTTP ${error.httpStatus}: ${JSON.stringify(error.sellerReason)}.` : Number.isInteger(error?.httpStatus) ? ` ${p.The} answered HTTP ${error.httpStatus}.` : "";
|
|
102229
|
+
const seller = fixable && error?.sellerReasonHidden === true ? ` ${p.The} refused this request (HTTP ${error.httpStatus}); its own words are not shown, because they can repeat your question.` : fixable && typeof error?.sellerReason === "string" ? ` ${p.The} refused this request (HTTP ${error.httpStatus}) and said why: ${JSON.stringify(error.sellerReason)}.` : fixable ? ` ${p.The} refused this request (HTTP ${error.httpStatus}) and said why in its first answer; the wallet does not keep ${p.the}'s words.` : typeof error?.sellerReason === "string" ? ` ${p.The} answered HTTP ${error.httpStatus}: ${JSON.stringify(error.sellerReason)}.` : Number.isInteger(error?.httpStatus) ? ` ${p.The} answered HTTP ${error.httpStatus}.` : "";
|
|
102207
102230
|
const late2 = floatChargeTooLate(error) ? ` ${p.The} worked ${error.sellerAnswerSeconds} s before it tried to charge, and its answer says the charge failed. A Solana payment expires about 30 s after it is signed, so no wallet can pay ${p.a} that works this long before it charges.` : "";
|
|
102208
102231
|
const tryAgain = fixable ? t.ai ? `${p.The} said what is wrong with the request. If ${stillWants(t)} an answer, change the question as it says, then ${t.rerun.toLowerCase()} with ${t.newId}` : `The seller said what is wrong with the request. If ${stillWants(t)} the data, fix the request as the seller says (for example add the query values, headers, or body fields it names), then ${t.rerun.toLowerCase()} with the fixed request and ${t.newId}` : late2 ? t.ai ? `${p.The} works too long before it charges. ${t.ai.other}` : "Do not pay this seller again: it works too long before it charges" : t.ai ? `If ${stillWants(t)} an answer, ${t.askNew}` : `If ${stillWants(t)} the data, try this seller again with ${t.newId}`;
|
|
102209
102232
|
const why = floatRefundWhy(error, Boolean(t.ai));
|
|
@@ -102380,7 +102403,7 @@ function floatOutcomeWords(code2, error, t) {
|
|
|
102380
102403
|
return void 0;
|
|
102381
102404
|
}
|
|
102382
102405
|
}
|
|
102383
|
-
var ATOMIC4, TRANSFER_DEAD_WORDS, payeeOf, floatSellerCanBeFixed, floatSeller4xx, answeredInstead, floatStillSettling, floatChargeTooLate, amountText, withTransaction, PAID_SELLER_FAILED_CODE, stillWants, AI_SERVER_WRONG, QUOTE_REFUSED_WHY;
|
|
102406
|
+
var ATOMIC4, TRANSFER_DEAD_WORDS, payeeOf, floatSellerCanBeFixed, withoutProviderText, floatSeller4xx, answeredInstead, floatStillSettling, floatChargeTooLate, amountText, withTransaction, PAID_SELLER_FAILED_CODE, stillWants, AI_SERVER_WRONG, QUOTE_REFUSED_WHY;
|
|
102384
102407
|
var init_floatWords = __esm({
|
|
102385
102408
|
"wallet/src/pay/floatWords.mjs"() {
|
|
102386
102409
|
"use strict";
|
|
@@ -102393,6 +102416,11 @@ var init_floatWords = __esm({
|
|
|
102393
102416
|
};
|
|
102394
102417
|
payeeOf = (ai) => ai ? { the: "the AI provider", The: "The AI provider", this: "the AI provider", a: "an AI provider" } : { the: "the seller", The: "The seller", this: "this seller", a: "a seller" };
|
|
102395
102418
|
floatSellerCanBeFixed = (error) => floatSeller4xx(error) && !floatChargeTooLate(error) && ![402, 408, 429].includes(error.httpStatus) && (typeof error?.sellerReason === "string" && error.sellerReason.trim() !== "" || error?.sellerFixable === true);
|
|
102419
|
+
withoutProviderText = (facts) => {
|
|
102420
|
+
const { sellerReason, ...rest } = facts ?? {};
|
|
102421
|
+
if (typeof sellerReason !== "string" || !sellerReason.trim()) return rest;
|
|
102422
|
+
return { ...rest, sellerReasonHidden: true, ...floatSellerCanBeFixed(facts) ? { sellerFixable: true } : {} };
|
|
102423
|
+
};
|
|
102396
102424
|
floatSeller4xx = (error) => Number.isInteger(error?.httpStatus) && error.httpStatus >= 400 && error.httpStatus < 500;
|
|
102397
102425
|
answeredInstead = (p, status, data) => `${p.the} answered HTTP ${status}${status >= 500 ? " (an error on its side)" : ""} instead of ${data}`;
|
|
102398
102426
|
floatStillSettling = (code2, error) => code2 === "p03_float_paid_finishing_retry_same_request" && error?.sellerCode === "payment_pending_retry_same_payment";
|
|
@@ -103664,10 +103692,10 @@ function markFloatRefundOutcomesShown(store, shown) {
|
|
|
103664
103692
|
}
|
|
103665
103693
|
}
|
|
103666
103694
|
function toMemoryOnly(store, walName2, record) {
|
|
103667
|
-
const { resultBase64, resultSha256: _hash, sellerReason: _reason, ...rest } = record;
|
|
103695
|
+
const { resultBase64, resultSha256: _hash, sellerReason: _reason, sellerHeaders, ...rest } = record;
|
|
103668
103696
|
const next = { ...rest, fingerprint: memoryOnlyFingerprint(), request: memoryOnlyRequest(record.request), memoryOnly: true };
|
|
103669
103697
|
store.writeWal(walName2, next);
|
|
103670
|
-
if (next.state === "receipt") keepMemoryAnswer(next, resultBase64);
|
|
103698
|
+
if (next.state === "receipt") keepMemoryAnswer(next, resultBase64, void 0, sellerHeaders);
|
|
103671
103699
|
return next;
|
|
103672
103700
|
}
|
|
103673
103701
|
function finishedAtMs(record) {
|
|
@@ -104428,7 +104456,7 @@ async function payViaFloat({
|
|
|
104428
104456
|
if (record.state === "receipt" && record.memoryOnly === true) {
|
|
104429
104457
|
const kept3 = memoryAnswer(record);
|
|
104430
104458
|
if (kept3 === void 0) finished(record);
|
|
104431
|
-
return paidResult({ ...record, resultBase64: kept3 }, true);
|
|
104459
|
+
return paidResult({ ...record, resultBase64: kept3, sellerHeaders: memoryAnswerHeaders(record) }, true);
|
|
104432
104460
|
}
|
|
104433
104461
|
if (record.state === "receipt") return paidResult(record, true);
|
|
104434
104462
|
if (record.state === "refund_pending") refundPendingAnswer(record);
|
|
@@ -104805,18 +104833,18 @@ async function payViaFloat({
|
|
|
104805
104833
|
transaction: isSolanaSignature(settled?.transaction) ? settled.transaction : null,
|
|
104806
104834
|
network: record.requirement.network
|
|
104807
104835
|
};
|
|
104836
|
+
const sellerHeaders = keptSellerHeaders(response.headers);
|
|
104808
104837
|
record = {
|
|
104809
104838
|
...record,
|
|
104810
104839
|
state: "receipt",
|
|
104811
104840
|
status: response.status,
|
|
104812
104841
|
receipt,
|
|
104813
|
-
...answerFields(record, resultBase64),
|
|
104814
|
-
sellerHeaders: keptSellerHeaders(response.headers),
|
|
104842
|
+
...answerFields(record, resultBase64, sellerHeaders),
|
|
104815
104843
|
answeredAtMs: Date.now()
|
|
104816
104844
|
};
|
|
104817
104845
|
store.writeWal(walName2, record);
|
|
104818
104846
|
mark("float-receipt");
|
|
104819
|
-
return answered(store, walName2, record, resultBase64);
|
|
104847
|
+
return answered(store, walName2, record, resultBase64, sellerHeaders);
|
|
104820
104848
|
}
|
|
104821
104849
|
const sellerReason = await sellerAnswerText(response);
|
|
104822
104850
|
if (wasKept) keptAgain(response.status, sellerReason);
|
|
@@ -105087,18 +105115,18 @@ async function selfBroadcastLeg({ store, walName: walName2, record, sendRequest,
|
|
|
105087
105115
|
transaction: isSolanaSignature(settled?.transaction) ? settled.transaction : record.broadcastSignature,
|
|
105088
105116
|
network: record.requirement.network
|
|
105089
105117
|
};
|
|
105118
|
+
const sellerHeaders = keptSellerHeaders(response.headers);
|
|
105090
105119
|
record = {
|
|
105091
105120
|
...record,
|
|
105092
105121
|
state: "receipt",
|
|
105093
105122
|
status: response.status,
|
|
105094
105123
|
receipt,
|
|
105095
|
-
...answerFields(record, resultBase64),
|
|
105096
|
-
sellerHeaders: keptSellerHeaders(response.headers),
|
|
105124
|
+
...answerFields(record, resultBase64, sellerHeaders),
|
|
105097
105125
|
answeredAtMs: Date.now()
|
|
105098
105126
|
};
|
|
105099
105127
|
store.writeWal(walName2, record);
|
|
105100
105128
|
mark("float-receipt");
|
|
105101
|
-
return answered(store, walName2, record, resultBase64);
|
|
105129
|
+
return answered(store, walName2, record, resultBase64, sellerHeaders);
|
|
105102
105130
|
}
|
|
105103
105131
|
if (response.status >= 500 || response.status === 202) {
|
|
105104
105132
|
const unansweredReason = await sellerRefusalText(response);
|
|
@@ -105170,13 +105198,13 @@ function keptSellerHeaders(headers) {
|
|
|
105170
105198
|
}
|
|
105171
105199
|
return kept3;
|
|
105172
105200
|
}
|
|
105173
|
-
function answerFields(record, resultBase64) {
|
|
105174
|
-
return record.memoryOnly === true ? {} : { resultBase64 };
|
|
105201
|
+
function answerFields(record, resultBase64, sellerHeaders) {
|
|
105202
|
+
return record.memoryOnly === true ? {} : { resultBase64, sellerHeaders };
|
|
105175
105203
|
}
|
|
105176
|
-
function answered(store, walName2, record, resultBase64) {
|
|
105204
|
+
function answered(store, walName2, record, resultBase64, sellerHeaders) {
|
|
105177
105205
|
if (record.memoryOnly !== true) return paidResult(record, false);
|
|
105178
|
-
keepMemoryAnswer(record, resultBase64);
|
|
105179
|
-
return paidResult({ ...record, resultBase64 }, false);
|
|
105206
|
+
keepMemoryAnswer(record, resultBase64, void 0, sellerHeaders);
|
|
105207
|
+
return paidResult({ ...record, resultBase64, sellerHeaders }, false);
|
|
105180
105208
|
}
|
|
105181
105209
|
function paidResult(record, replayed) {
|
|
105182
105210
|
return {
|
|
@@ -105270,7 +105298,7 @@ var init_floatPay = __esm({
|
|
|
105270
105298
|
floatPaymentWalName = (requestKey) => `${FLOAT_PAYMENT_WAL_PREFIX2}${requestKey}`;
|
|
105271
105299
|
floatRecordName = (requestId) => floatPaymentWalName(hash7(requestId));
|
|
105272
105300
|
FLOAT_KEEP_BYTES_MS = 6e5;
|
|
105273
|
-
memoryOnlyNeedsScrub = (record) => record?.memoryOnly === true && (record.resultSha256 !== void 0 || record.request?.bodySha256 !== void 0 || record.request?.headersSha256 !== void 0 || !/^memory-[0-9a-f]{64}$/.test(String(record.fingerprint ?? "")));
|
|
105301
|
+
memoryOnlyNeedsScrub = (record) => record?.memoryOnly === true && (record.resultSha256 !== void 0 || Array.isArray(record.sellerHeaders) && record.sellerHeaders.length > 0 || record.request?.bodySha256 !== void 0 || record.request?.headersSha256 !== void 0 || !/^memory-[0-9a-f]{64}$/.test(String(record.fingerprint ?? "")));
|
|
105274
105302
|
FLOAT_KEEP_OPEN_REQUEST_MS = 36e5;
|
|
105275
105303
|
configCache = /* @__PURE__ */ new Map();
|
|
105276
105304
|
configGeneration = 0;
|
|
@@ -109479,6 +109507,16 @@ function refusalSay(a, tool, again, npmVersion) {
|
|
|
109479
109507
|
const head = `${paid ? `Paid ${paid} USDC${price2 && positive(fee) ? ` (${price2} price + ${fee} Shinjuku fee)` : ""}` : "Paid"}, but`;
|
|
109480
109508
|
return firstFit(`${head} the model reached the answer's length limit before it answered.${more}`, `${head} the answer hit its length limit.${more}`);
|
|
109481
109509
|
}
|
|
109510
|
+
if (code2 === "inference_empty_answer") {
|
|
109511
|
+
const again2 = " Ask again (it pays again) or pick another model.";
|
|
109512
|
+
if (a.replayed === true && a.paid === false) return `Nothing was paid, and the stored answer is empty.${again2}`;
|
|
109513
|
+
if (a.replayed === true) return `Already paid; the stored answer is empty and nothing new was paid.${again2}`;
|
|
109514
|
+
const paid = usdcText2(a.paidAtomic);
|
|
109515
|
+
const price2 = usdcText2(a.priceAtomic);
|
|
109516
|
+
const fee = usdcText2(a.feeAtomic);
|
|
109517
|
+
const head = `${paid ? `Paid ${paid} USDC${price2 && positive(fee) ? ` (${price2} price + ${fee} Shinjuku fee)` : ""}` : "Paid"}, but`;
|
|
109518
|
+
return firstFit(`${head} the AI returned no answer, and no refund comes.${again2}`, `${head} the AI returned no answer.${again2}`);
|
|
109519
|
+
}
|
|
109482
109520
|
if (code2 === "inference_no_provider") {
|
|
109483
109521
|
return "Nothing was paid: no AI provider can take this wallet's payment for this model right now. Ask for another model, or ask again later.";
|
|
109484
109522
|
}
|
|
@@ -110935,8 +110973,8 @@ async function offeredPrice(paymentRequired, store, serviceUrl2, target, timing,
|
|
|
110935
110973
|
}
|
|
110936
110974
|
return { rail, amountAtomic: highest.toString(), priceAtomic: highest.toString() };
|
|
110937
110975
|
}
|
|
110938
|
-
function ownRecord(store, requestId) {
|
|
110939
|
-
const float = floatRecordOf(store, requestId);
|
|
110976
|
+
function ownRecord(store, requestId, { strict = false } = {}) {
|
|
110977
|
+
const float = strict ? store.readWal(floatRecordName(requestId)) : floatRecordOf(store, requestId);
|
|
110940
110978
|
if (float) return { kind: "float", record: float };
|
|
110941
110979
|
const key = sha256Hex2(Buffer.from(requestId, "utf8"));
|
|
110942
110980
|
const shielded = store.readWal(`resource-payment-${key}`);
|
|
@@ -111049,9 +111087,9 @@ async function payTurn({ session, target, method, headers, body, maxPrice, polic
|
|
|
111049
111087
|
if (session.closed) fail26("fetch_session_closed", "this payer session is closed; open a new one");
|
|
111050
111088
|
const paymentStartedAt = Date.now();
|
|
111051
111089
|
const timing = typeof opts?.timing === "function" ? opts.timing : session.timing();
|
|
111052
|
-
const mark = (phase) => {
|
|
111090
|
+
const mark = (phase, outcome) => {
|
|
111053
111091
|
try {
|
|
111054
|
-
timing?.(phase);
|
|
111092
|
+
timing?.(phase, outcome);
|
|
111055
111093
|
} catch {
|
|
111056
111094
|
}
|
|
111057
111095
|
};
|
|
@@ -111069,12 +111107,12 @@ async function payTurn({ session, target, method, headers, body, maxPrice, polic
|
|
|
111069
111107
|
warmFloatConfig({ origin: new URL(session.memoServiceUrl).origin, timing: mark });
|
|
111070
111108
|
startRecoveredPaymentTools(lazyProofTools(session));
|
|
111071
111109
|
}
|
|
111072
|
-
const response = await unpaidRequest(target, () => keepAliveInit({
|
|
111110
|
+
const response = await withPhaseScope(mark, "fetch", () => unpaidRequest(target, () => keepAliveInit({
|
|
111073
111111
|
method,
|
|
111074
111112
|
headers,
|
|
111075
111113
|
...body ? { body } : {},
|
|
111076
111114
|
redirect: "manual"
|
|
111077
|
-
}), { timeoutMs: Number.isSafeInteger(opts?.unpaidTimeoutMs) && opts.unpaidTimeoutMs > 0 ? opts.unpaidTimeoutMs : void 0, onCut: opts?.onUnpaidCut });
|
|
111115
|
+
}), { timeoutMs: Number.isSafeInteger(opts?.unpaidTimeoutMs) && opts.unpaidTimeoutMs > 0 ? opts.unpaidTimeoutMs : void 0, onCut: opts?.onUnpaidCut }));
|
|
111078
111116
|
if (response.status !== 402) return response;
|
|
111079
111117
|
const encoded = response.headers.get("PAYMENT-REQUIRED");
|
|
111080
111118
|
void drainBody(response);
|
|
@@ -111474,6 +111512,23 @@ async function paidCall({ session, target, method, headers, body, cap, maxPrice,
|
|
|
111474
111512
|
}
|
|
111475
111513
|
mark("fetch-ready");
|
|
111476
111514
|
const fresh = challenge !== void 0 && Date.now() - challenge.atMs <= PREFETCH_MAX_AGE_MS;
|
|
111515
|
+
const leftDecision = () => {
|
|
111516
|
+
let left = true;
|
|
111517
|
+
let unreadable = false;
|
|
111518
|
+
let after;
|
|
111519
|
+
try {
|
|
111520
|
+
after = ownRecord(store, requestId, { strict: true });
|
|
111521
|
+
left = after === void 0 ? own !== void 0 : committed(after, store) && !closedUnpaid(after, store) && !preparedOnly(after, store);
|
|
111522
|
+
} catch {
|
|
111523
|
+
after = void 0;
|
|
111524
|
+
unreadable = true;
|
|
111525
|
+
}
|
|
111526
|
+
const atomic4 = left ? (after === void 0 ? void 0 : paidAmount(after) ?? price2?.amountAtomic) ?? String(cap) : void 0;
|
|
111527
|
+
return Object.freeze({ left, atomic: atomic4, unreadable, before: leftBefore });
|
|
111528
|
+
};
|
|
111529
|
+
const recordLeft = (decision) => {
|
|
111530
|
+
if (policy && decision.left) policy.record({ amountAtomic: earlierRun ? "0" : decision.atomic, url: target, requestId });
|
|
111531
|
+
};
|
|
111477
111532
|
const result = await payResource({
|
|
111478
111533
|
store,
|
|
111479
111534
|
connection: session.connection,
|
|
@@ -111517,19 +111572,54 @@ async function paidCall({ session, target, method, headers, body, cap, maxPrice,
|
|
|
111517
111572
|
onCompactList: memoPrefetchOnList(session, store)
|
|
111518
111573
|
})
|
|
111519
111574
|
}
|
|
111520
|
-
}).finally(markMade)
|
|
111521
|
-
|
|
111575
|
+
}).finally(markMade).catch((error) => {
|
|
111576
|
+
const failure2 = error !== null && typeof error === "object" ? error : Object.assign(new Error(String(error)), { cause: error });
|
|
111577
|
+
try {
|
|
111578
|
+
const decision = leftDecision();
|
|
111579
|
+
try {
|
|
111580
|
+
failure2.paidLeft = decision;
|
|
111581
|
+
} catch {
|
|
111582
|
+
}
|
|
111583
|
+
recordLeft(decision);
|
|
111584
|
+
} catch {
|
|
111585
|
+
}
|
|
111586
|
+
throw failure2;
|
|
111587
|
+
});
|
|
111588
|
+
let ownAfter;
|
|
111589
|
+
let afterUnreadable = false;
|
|
111590
|
+
try {
|
|
111591
|
+
ownAfter = ownRecord(store, requestId, { strict: true });
|
|
111592
|
+
} catch {
|
|
111593
|
+
ownAfter = void 0;
|
|
111594
|
+
afterUnreadable = true;
|
|
111595
|
+
}
|
|
111596
|
+
const resultAtomic = POSITIVE_ATOMIC4.test(String(result.paidAtomic ?? "")) ? String(result.paidAtomic) : void 0;
|
|
111597
|
+
const amountAtomic = paidAmount(ownAfter) ?? resultAtomic ?? price2?.amountAtomic ?? (result.replayed ? void 0 : String(cap));
|
|
111522
111598
|
if (!result.replayed && policy && amountAtomic) policy.record({ amountAtomic: earlierRun ? "0" : amountAtomic, url: target, requestId });
|
|
111523
|
-
|
|
111524
|
-
|
|
111525
|
-
|
|
111526
|
-
|
|
111527
|
-
|
|
111528
|
-
|
|
111529
|
-
|
|
111530
|
-
|
|
111531
|
-
|
|
111532
|
-
|
|
111599
|
+
try {
|
|
111600
|
+
const bytes2 = Buffer.from(result.resultBase64 ?? "", "base64");
|
|
111601
|
+
const payment = {
|
|
111602
|
+
transaction: result.receipt?.transaction,
|
|
111603
|
+
scheme: result.scheme === "exact" ? "exact" : "shielded-exact",
|
|
111604
|
+
amountAtomic: amountAtomic ?? null,
|
|
111605
|
+
requestId,
|
|
111606
|
+
replayed: result.replayed === true,
|
|
111607
|
+
receiptFinality: result.receiptFinality ?? null
|
|
111608
|
+
};
|
|
111609
|
+
return new Response(bytes2, { status: 200, headers: paidResponseHeaders(result.sellerHeaders, sniffContentType(bytes2), payment) });
|
|
111610
|
+
} catch (error) {
|
|
111611
|
+
const failure2 = error !== null && typeof error === "object" ? error : Object.assign(new Error(String(error)), { cause: error });
|
|
111612
|
+
try {
|
|
111613
|
+
failure2.paidLeft = Object.freeze({
|
|
111614
|
+
left: true,
|
|
111615
|
+
atomic: amountAtomic ?? String(cap),
|
|
111616
|
+
unreadable: afterUnreadable,
|
|
111617
|
+
before: leftBefore || result.replayed === true
|
|
111618
|
+
});
|
|
111619
|
+
} catch {
|
|
111620
|
+
}
|
|
111621
|
+
throw failure2;
|
|
111622
|
+
}
|
|
111533
111623
|
} finally {
|
|
111534
111624
|
await release();
|
|
111535
111625
|
}
|
|
@@ -139030,6 +139120,21 @@ ${canonical5}`;
|
|
|
139030
139120
|
"inference_chat"
|
|
139031
139121
|
)), paidStore);
|
|
139032
139122
|
}
|
|
139123
|
+
if (typeof content === "string" && !content.trim()) {
|
|
139124
|
+
const paidText = usdcText3(paidAtomic ?? "");
|
|
139125
|
+
const reasonLogged = result.finishReason === void 0 || result.finishReason === null ? "none" : ["stop", "length", "content_filter", "tool_calls", "function_call"].includes(result.finishReason) ? result.finishReason : "other";
|
|
139126
|
+
log(`MCP_INFERENCE_EMPTY requestId=${requestId} finishReason=${reasonLogged}`);
|
|
139127
|
+
return withRefundNotices(json3(sayFirst(
|
|
139128
|
+
{
|
|
139129
|
+
ok: false,
|
|
139130
|
+
error: "inference_empty_answer",
|
|
139131
|
+
detail: `the AI provider returned an empty answer (finish reason ${JSON.stringify(result.finishReason ?? null)}); ` + (unpaid ? "nothing was paid: this request id's payment never landed (the pool's public history proves it)" : `this call was paid${paidText ? ` (${paidText} USDC)` : ""}${transaction ? ` in transaction ${transaction}` : ""} and no refund comes`),
|
|
139132
|
+
...paidFields,
|
|
139133
|
+
next: unpaid ? "nothing was paid, and this request id's stored answer is empty. If the user still wants an answer, call inference_chat with a NEW request_id, or another model; it pays then" : receipt.replayed === true ? "this request id was already paid and its stored answer is empty; nothing new was paid. If the user still wants an answer, call inference_chat with a NEW request_id, or another model; it pays again" : `Tell the user: the AI returned no answer, and this call paid ${paidText ? `${paidText} USDC` : "(see paidAtomic)"}; no refund comes. If the user still wants an answer, call inference_chat again with a NEW request_id (reword the question, or pick another model); it pays again. The same request_id returns this same empty answer`
|
|
139134
|
+
},
|
|
139135
|
+
"inference_chat"
|
|
139136
|
+
)), paidStore);
|
|
139137
|
+
}
|
|
139033
139138
|
return withRefundNotices(json3(sayFirst({
|
|
139034
139139
|
ok: true,
|
|
139035
139140
|
...paidFields,
|
|
@@ -145139,7 +145244,8 @@ async function runChat({ io, values, deps = {} }) {
|
|
|
145139
145244
|
empty: 0,
|
|
145140
145245
|
pending: void 0,
|
|
145141
145246
|
busy: false,
|
|
145142
|
-
interrupts: 0
|
|
145247
|
+
interrupts: 0,
|
|
145248
|
+
epoch: 0
|
|
145143
145249
|
};
|
|
145144
145250
|
const servedNow = catalogNow;
|
|
145145
145251
|
servedNow();
|
|
@@ -145514,8 +145620,15 @@ ${costLine2(picked.entry.id)}.` + (start ? "" : `
|
|
|
145514
145620
|
The next question uses it${state.mode === "talk" ? ", with the conversation so far" : ""}.`);
|
|
145515
145621
|
};
|
|
145516
145622
|
let reader;
|
|
145623
|
+
const warnPaidPending = (how) => {
|
|
145624
|
+
if (!state.pending || !state.unsure.has(state.pending) || state.dropWarned === state.pending) return false;
|
|
145625
|
+
state.dropWarned = state.pending;
|
|
145626
|
+
say3(`An answer you may have paid for (${usdcWords(state.unsure.get(state.pending))}) is not finished. Type /retry to finish it: it never pays twice. Or ${how}.`);
|
|
145627
|
+
return true;
|
|
145628
|
+
};
|
|
145517
145629
|
const onInterrupt = () => {
|
|
145518
145630
|
if (!state.busy) {
|
|
145631
|
+
if (warnPaidPending("press Ctrl+C again to end the chat and drop it")) return;
|
|
145519
145632
|
reader?.close();
|
|
145520
145633
|
return;
|
|
145521
145634
|
}
|
|
@@ -145728,6 +145841,7 @@ When it says ready, type your message here.`);
|
|
|
145728
145841
|
state.interrupts = 0;
|
|
145729
145842
|
}
|
|
145730
145843
|
state.pending = void 0;
|
|
145844
|
+
const wasUnsure = state.unsure.get(turn);
|
|
145731
145845
|
state.unsure.delete(turn);
|
|
145732
145846
|
const replayed = result.receipt?.replayed === true;
|
|
145733
145847
|
let unpaid = false;
|
|
@@ -145738,6 +145852,7 @@ When it says ready, type your message here.`);
|
|
|
145738
145852
|
}
|
|
145739
145853
|
const paid = unpaid ? 0n : typeof result.paidAtomic === "bigint" ? result.paidAtomic : void 0;
|
|
145740
145854
|
if (paid !== void 0) state.spent += paid;
|
|
145855
|
+
else if (wasUnsure !== void 0 && !unpaid) state.spent += wasUnsure;
|
|
145741
145856
|
const content = typeof result.content === "string" ? result.content : "";
|
|
145742
145857
|
const paidText = unpaid ? "nothing was paid: the earlier payment for this answer never went through" : paid === void 0 ? "paid (the amount was not reported)" : replayed ? `already paid ${usdcWords(paid)} earlier for this answer; nothing new was paid` : `paid ${usdcWords(paid)}`;
|
|
145743
145858
|
const dayRoom2 = dayRoomSentence();
|
|
@@ -145749,7 +145864,7 @@ When it says ready, type your message here.`);
|
|
|
145749
145864
|
return;
|
|
145750
145865
|
}
|
|
145751
145866
|
state.answers += 1;
|
|
145752
|
-
if (state.mode === "talk") state.history = [...turn.messages, { role: "assistant", content }];
|
|
145867
|
+
if (state.mode === "talk" && (turn.epoch ?? 0) === state.epoch) state.history = [...turn.messages, { role: "assistant", content }];
|
|
145753
145868
|
io.out(`${fitColumns(
|
|
145754
145869
|
content,
|
|
145755
145870
|
process.stdout.isTTY ? process.stdout.columns : 0,
|
|
@@ -145770,28 +145885,45 @@ When it says ready, type your message here.`);
|
|
|
145770
145885
|
const failed = async (error, turn) => {
|
|
145771
145886
|
const code2 = errorCodeOf(error);
|
|
145772
145887
|
const surelyNothing = nothingPaid(error);
|
|
145888
|
+
const paidLeft = [error, error?.cause].map((one) => one?.paidLeft).find((one) => one && typeof one === "object" && typeof one.left === "boolean");
|
|
145889
|
+
const leftAtomic = paidLeft?.left === true && /^[1-9][0-9]{0,30}$/.test(String(paidLeft.atomic ?? "")) ? BigInt(paidLeft.atomic) : void 0;
|
|
145773
145890
|
const paidAtomic = error?.details?.receipt ? error.details.paidAtomic : void 0;
|
|
145891
|
+
const wasUnsure = state.unsure.get(turn);
|
|
145774
145892
|
state.pending = void 0;
|
|
145775
145893
|
if (error?.details?.receipt) {
|
|
145894
|
+
state.unsure.delete(turn);
|
|
145776
145895
|
if (typeof paidAtomic === "bigint") state.spent += paidAtomic;
|
|
145896
|
+
else if (wasUnsure !== void 0) state.spent += wasUnsure;
|
|
145777
145897
|
state.empty += 1;
|
|
145778
145898
|
say3(`This answer was paid${typeof paidAtomic === "bigint" ? ` (${usdcWords(paidAtomic)})` : ""}, but no usable answer came back from the AI provider. A new question pays again: ask again, or /model to try another model (${modelIds2}). This chat paid ${paidSoFar()} so far.`);
|
|
145779
145899
|
return;
|
|
145780
145900
|
}
|
|
145781
145901
|
if (code2 === "p03_resource_payment_answer_not_kept") {
|
|
145902
|
+
const earlier = error?.earlierPaymentAtomic ?? error?.cause?.earlierPaymentAtomic;
|
|
145903
|
+
state.unsure.delete(turn);
|
|
145904
|
+
if (/^[1-9][0-9]{0,30}$/.test(String(earlier ?? ""))) state.spent += BigInt(earlier);
|
|
145905
|
+
else if (wasUnsure !== void 0) state.spent += wasUnsure;
|
|
145782
145906
|
state.empty += 1;
|
|
145783
145907
|
say3(`${answerNotKeptWords(error?.earlierPaymentAtomic ?? error?.cause?.earlierPaymentAtomic)} This chat paid ${paidSoFar()} so far.`);
|
|
145784
145908
|
return;
|
|
145785
145909
|
}
|
|
145786
|
-
if (/another_request_unresolved$/.test(code2 ?? "") && (error?.memoryOnlyOpen ?? error?.cause?.memoryOnlyOpen) === true) {
|
|
145910
|
+
if (paidLeft?.left !== true && /another_request_unresolved$/.test(code2 ?? "") && (error?.memoryOnlyOpen ?? error?.cause?.memoryOnlyOpen) === true) {
|
|
145787
145911
|
say3(memoryOnlyOpenWords(error?.closesAtUnix ?? error?.cause?.closesAtUnix));
|
|
145788
145912
|
return;
|
|
145789
145913
|
}
|
|
145790
145914
|
if (code2 === "fetch_proof_tools_unavailable") {
|
|
145915
|
+
const earlier = error?.earlierPaymentAtomic ?? error?.cause?.earlierPaymentAtomic;
|
|
145916
|
+
const heldAtomic = /^[1-9][0-9]{0,30}$/.test(String(earlier ?? "")) ? BigInt(earlier) : leftAtomic ?? wasUnsure;
|
|
145917
|
+
if (heldAtomic !== void 0) {
|
|
145918
|
+
state.unsure.set(turn, heldAtomic);
|
|
145919
|
+
state.pending = turn;
|
|
145920
|
+
say3(`This wallet is missing some setup files, so this try sent nothing and paid nothing new. The earlier payment for this answer (${usdcWords(heldAtomic)}) may be paid already: type /retry to try again (it never pays twice). If you end the chat to run ${commandLine("setup")}, the wallet closes that payment by itself: if it never reached the AI provider, the money comes back.`);
|
|
145921
|
+
return;
|
|
145922
|
+
}
|
|
145791
145923
|
say3(`This wallet is missing some setup files, so nothing was paid. End the chat (/exit), run ${commandLine("setup")} to install them, then start the chat again: ${commandLine("chat")}`);
|
|
145792
145924
|
return;
|
|
145793
145925
|
}
|
|
145794
|
-
if (localErrorCodes(error).includes(SPLIT_CODE)) {
|
|
145926
|
+
if (paidLeft?.left !== true && localErrorCodes(error).includes(SPLIT_CODE)) {
|
|
145795
145927
|
state.pending = turn;
|
|
145796
145928
|
const why = joinOutcome === "stale" ? "the wallet could not read your balance again just now" : joinOutcome === "unfinished" ? "the wallet did not finish getting it ready in this turn" : joinOutcome === "files" ? void 0 : "part of it is not ready to spend yet (another payment of this wallet, or its change, is not final yet)";
|
|
145797
145929
|
say3(why === void 0 ? `Your private balance covers this answer in total, but not yet in one payment. Nothing was paid. Get it ready in another terminal: ${commandLine("prepare")}, then type /retry: it asks the same question again.` : `Your private balance covers this answer in total, but ${why}. Nothing was paid. Type /retry in a minute: it gets the balance ready by itself when it needs to, and never pays twice.`);
|
|
@@ -145843,14 +145975,36 @@ When it says ready, type /retry: it asks the same question again.` : receivedOnl
|
|
|
145843
145975
|
say3(held2 !== void 0 && facts.preparedNotSent === true ? `Nothing was paid: a payment of ${usdcWords(held2)} is prepared for an earlier try of this question and not sent, and the wallet never pays twice for one question. This chat cannot send it. ${closeFirst}` : held2 !== void 0 ? `This question already has a payment of ${usdcWords(held2)} from an earlier try, made with other details, and the wallet never pays twice for one question; nothing more was paid. This chat cannot finish that payment, and the same question typed again is a new question that pays again.` : open4 ? `Nothing was paid: an earlier try of this question was made with other details and is not finished; nothing of it was sent, and it blocks every new question until it is closed. ${closeFirst}` : "Nothing was paid: an earlier try of this question was made with other details. If you still want an answer, type the question again: it goes out as a new question.");
|
|
145844
145976
|
return;
|
|
145845
145977
|
}
|
|
145846
|
-
const float = typeof code2 === "string" && !CAP_CODES.test(code2) ? floatOutcomeWords(code2, facts, chatFloatTerms()) : void 0;
|
|
145978
|
+
const float = typeof code2 === "string" && !CAP_CODES.test(code2) ? floatOutcomeWords(code2, withoutProviderText(facts), chatFloatTerms()) : void 0;
|
|
145847
145979
|
if (float) {
|
|
145848
|
-
const
|
|
145849
|
-
|
|
145850
|
-
|
|
145851
|
-
|
|
145852
|
-
|
|
145853
|
-
|
|
145980
|
+
const keptAmount = () => {
|
|
145981
|
+
try {
|
|
145982
|
+
const kept3 = keptPayment(session.openStore(), turn.requestId);
|
|
145983
|
+
return kept3?.committed === true && kept3.cancelled !== true && /^[1-9][0-9]{0,30}$/.test(String(kept3.amountAtomic ?? "")) ? BigInt(kept3.amountAtomic) : void 0;
|
|
145984
|
+
} catch {
|
|
145985
|
+
return typeof turn.capAtomic === "bigint" && turn.capAtomic > 0n ? turn.capAtomic : void 0;
|
|
145986
|
+
}
|
|
145987
|
+
};
|
|
145988
|
+
const amount = /^[1-9][0-9]{0,30}$/.test(String(facts.paidAtomic ?? "")) ? BigInt(facts.paidAtomic) : paidLeft ? leftAtomic : FLOAT_NOT_PAID.has(code2) ? void 0 : keptAmount();
|
|
145989
|
+
const paidForSure = floatSpent(code2, facts) || code2 === PAID_SELLER_FAILED_CODE;
|
|
145990
|
+
const spent = paidForSure && (amount !== void 0 || wasUnsure !== void 0);
|
|
145991
|
+
if (paidLeft?.left === true && !paidForSure && (FLOAT_NOT_PAID.has(code2) || NOTHING_PAID.test(`${float[1]} ${float[2]}`))) {
|
|
145992
|
+
const held3 = amount ?? leftAtomic ?? (typeof turn.capAtomic === "bigint" && turn.capAtomic > 0n ? turn.capAtomic : void 0);
|
|
145993
|
+
if (held3 !== void 0) state.unsure.set(turn, held3);
|
|
145994
|
+
state.pending = turn;
|
|
145995
|
+
try {
|
|
145996
|
+
(typeof session.timing === "function" ? session.timing() : void 0)?.("chat-answer-failed", code2);
|
|
145997
|
+
} catch {
|
|
145998
|
+
}
|
|
145999
|
+
say3(`The answer did not come back, and the wallet cannot prove this payment${held3 !== void 0 ? ` (${usdcWords(held3)})` : ""} stayed unpaid: it may be paid already. Type /retry to finish it (it never pays twice). This chat counts it until it is certain.`);
|
|
146000
|
+
return;
|
|
146001
|
+
}
|
|
146002
|
+
if (paidForSure) {
|
|
146003
|
+
state.unsure.delete(turn);
|
|
146004
|
+
if (spent) state.spent += amount ?? wasUnsure;
|
|
146005
|
+
} else if (FLOAT_NOT_PAID.has(code2)) state.unsure.delete(turn);
|
|
146006
|
+
else if (amount !== void 0) state.unsure.set(turn, amount);
|
|
146007
|
+
if (paidForSure) state.empty += 1;
|
|
145854
146008
|
if (floatRetry(code2, facts)) state.pending = turn;
|
|
145855
146009
|
try {
|
|
145856
146010
|
const mark = typeof session.timing === "function" ? session.timing() : void 0;
|
|
@@ -145863,17 +146017,33 @@ When it says ready, type /retry: it asks the same question again.` : receivedOnl
|
|
|
145863
146017
|
}
|
|
145864
146018
|
let prepared;
|
|
145865
146019
|
let neverLeft = false;
|
|
145866
|
-
|
|
146020
|
+
let keptAtomic;
|
|
146021
|
+
if (paidLeft) {
|
|
146022
|
+
if (paidLeft.left) keptAtomic = leftAtomic ?? (typeof turn.capAtomic === "bigint" && turn.capAtomic > 0n ? turn.capAtomic : void 0);
|
|
146023
|
+
else {
|
|
146024
|
+
let kept3;
|
|
146025
|
+
try {
|
|
146026
|
+
kept3 = keptPayment(session.openStore(), turn.requestId);
|
|
146027
|
+
} catch {
|
|
146028
|
+
kept3 = void 0;
|
|
146029
|
+
}
|
|
146030
|
+
if (kept3?.prepared === true) prepared = /^[1-9][0-9]{0,30}$/.test(String(kept3.amountAtomic ?? "")) ? ` of ${usdcWords(BigInt(kept3.amountAtomic))}` : "";
|
|
146031
|
+
else neverLeft = true;
|
|
146032
|
+
}
|
|
146033
|
+
} else if (!surelyNothing) {
|
|
145867
146034
|
try {
|
|
145868
146035
|
const kept3 = keptPayment(session.openStore(), turn.requestId);
|
|
146036
|
+
if (/^[1-9][0-9]{0,30}$/.test(String(kept3?.amountAtomic ?? ""))) keptAtomic = BigInt(kept3.amountAtomic);
|
|
145869
146037
|
if (kept3 === void 0 || kept3.committed !== true || kept3.cancelled === true) neverLeft = true;
|
|
145870
|
-
else if (kept3.prepared === true) prepared =
|
|
146038
|
+
else if (kept3.prepared === true) prepared = keptAtomic !== void 0 ? ` of ${usdcWords(keptAtomic)}` : "";
|
|
145871
146039
|
} catch {
|
|
145872
146040
|
prepared = void 0;
|
|
145873
146041
|
neverLeft = false;
|
|
146042
|
+
if (typeof turn.capAtomic === "bigint" && turn.capAtomic > 0n) keptAtomic = turn.capAtomic;
|
|
145874
146043
|
}
|
|
145875
146044
|
}
|
|
145876
|
-
const nothing = surelyNothing || neverLeft;
|
|
146045
|
+
const nothing = paidLeft ? neverLeft : surelyNothing || neverLeft;
|
|
146046
|
+
if (!nothing && prepared === void 0 && keptAtomic !== void 0) state.unsure.set(turn, keptAtomic);
|
|
145877
146047
|
const again = nothing ? "ask again" : prepared !== void 0 ? "type /retry (it sends that same payment, never a second one)" : "type /retry (it finishes the same payment and never pays twice)";
|
|
145878
146048
|
if (!nothing) state.pending = turn;
|
|
145879
146049
|
const paidWords = nothing ? "Nothing was paid." : prepared !== void 0 ? `Nothing was paid: a payment${prepared} is prepared for this question and not sent yet.` : "It may be paid already.";
|
|
@@ -145915,8 +146085,10 @@ When it says ready, type /retry: it asks the same question again.` : receivedOnl
|
|
|
145915
146085
|
const command = async (text3) => {
|
|
145916
146086
|
const [name, ...rest] = text3.split(/\s+/);
|
|
145917
146087
|
const arg = rest.join(" ").trim();
|
|
145918
|
-
if (name === "/exit" || name === "/quit" || name === "/q") return
|
|
146088
|
+
if (name === "/exit" || name === "/quit" || name === "/q") return !warnPaidPending(`${name} again ends the chat and drops it`);
|
|
145919
146089
|
if (name === "/new") {
|
|
146090
|
+
if (warnPaidPending("/new again starts a new conversation and drops it")) return false;
|
|
146091
|
+
state.epoch += 1;
|
|
145920
146092
|
state.history = [];
|
|
145921
146093
|
state.pending = void 0;
|
|
145922
146094
|
forgetMemoryOnly();
|
|
@@ -145930,10 +146102,10 @@ When it says ready, type /retry: it asks the same question again.` : receivedOnl
|
|
|
145930
146102
|
if (!next) say3("Type /mode 1 for one question at a time, or /mode 2 for a conversation.");
|
|
145931
146103
|
else {
|
|
145932
146104
|
state.mode = next;
|
|
146105
|
+
state.epoch += 1;
|
|
145933
146106
|
state.history = [];
|
|
145934
|
-
state.pending
|
|
145935
|
-
|
|
145936
|
-
say3(next === "each" ? "Mode now: one question at a time. Each question goes alone, and the chat names each payment." : "Mode now: a conversation. The AI remembers from your next question on, and the running total shows beside you.");
|
|
146107
|
+
if (!state.pending) forgetMemoryOnly();
|
|
146108
|
+
say3((next === "each" ? "Mode now: one question at a time. Each question goes alone, and the chat names each payment." : "Mode now: a conversation. The AI remembers from your next question on, and the running total shows beside you.") + (state.pending ? " Your unfinished answer is kept: /retry finishes it." : ""));
|
|
145937
146109
|
}
|
|
145938
146110
|
} else if (name === "/model" || name === "/provider") {
|
|
145939
146111
|
const now = await servedNow();
|
|
@@ -146022,6 +146194,7 @@ When it says ready, type /retry: it asks the same question again.` : receivedOnl
|
|
|
146022
146194
|
if (text3.startsWith("/")) {
|
|
146023
146195
|
if (await command(text3)) break;
|
|
146024
146196
|
} else {
|
|
146197
|
+
if (warnPaidPending("type your new question again to drop it and ask the new one")) continue;
|
|
146025
146198
|
if (state.pending) say3("(The unfinished answer is dropped; this is a new question.)");
|
|
146026
146199
|
state.pending = void 0;
|
|
146027
146200
|
const now = await servedNow();
|
|
@@ -146033,12 +146206,16 @@ When it says ready, type /retry: it asks the same question again.` : receivedOnl
|
|
|
146033
146206
|
requestId: `chat-${randomBytes29(8).toString("hex")}`,
|
|
146034
146207
|
model: state.model,
|
|
146035
146208
|
liveEntry: liveOf(state.model),
|
|
146209
|
+
epoch: state.epoch,
|
|
146036
146210
|
messages: state.mode === "each" ? [{ role: "user", content: text3 }] : [...state.history, { role: "user", content: text3 }],
|
|
146037
146211
|
capAtomic: void 0
|
|
146038
146212
|
});
|
|
146039
146213
|
}
|
|
146040
146214
|
}
|
|
146041
146215
|
}
|
|
146216
|
+
if (state.pending && state.unsure.has(state.pending)) {
|
|
146217
|
+
say3(`An answer you may have paid for (${usdcWords(state.unsure.get(state.pending))}) was not finished, and the chat keeps no copy of it. The wallet closes that payment by itself: if it never reached the AI provider, the money comes back to your private balance; if it did, your next private question tells you that it was paid.`);
|
|
146218
|
+
}
|
|
146042
146219
|
say3([
|
|
146043
146220
|
`Chat ended. It paid ${paidSoFar()} for ${questionsWords()}. The conversation is gone from memory.`,
|
|
146044
146221
|
...chatEndLines({ color, columns: process.stderr.columns ?? 0 })
|
|
@@ -146051,7 +146228,7 @@ When it says ready, type /retry: it asks the same question again.` : receivedOnl
|
|
|
146051
146228
|
await session.close();
|
|
146052
146229
|
}
|
|
146053
146230
|
}
|
|
146054
|
-
var SPLIT_CODE, DEFAULT_MODEL2, CHAT_DEFAULT_MODEL, CHAT_MAX_TOKENS, CHAT_SHORT_TOKENS, DEFAULT_ANSWER_CAP_ATOMIC, DEFAULT_CHAT_CAP_ATOMIC, CHEAPEST_MODEL, PICK_PAGE, PICK_MOST_BROWSED, PICK_MATCHES, PICK_COLUMNS, PICK_ID_COLUMNS, PICK_NAME_COLUMNS, STILL_WAITING_MS, higherCap, shortInChat, POSITIVE_ATOMIC9, SHORT_QUESTION, SHORT_QUESTION_TOKENS, PASTE_JOIN_MS, CAP_CODES, WAIT_CODES, NO_ANSWER_CODES, HISTORY_CODES, chatFloatTerms, floatRetry, floatSpent, asSentence, upFirst, lowFirst, NOTHING_PAID, CAP_FROM, PROGRESS_LINE, SHOWN_PROGRESS, isProgressLine, fail46, nothingPaid;
|
|
146231
|
+
var SPLIT_CODE, DEFAULT_MODEL2, CHAT_DEFAULT_MODEL, CHAT_MAX_TOKENS, CHAT_SHORT_TOKENS, DEFAULT_ANSWER_CAP_ATOMIC, DEFAULT_CHAT_CAP_ATOMIC, CHEAPEST_MODEL, PICK_PAGE, PICK_MOST_BROWSED, PICK_MATCHES, PICK_COLUMNS, PICK_ID_COLUMNS, PICK_NAME_COLUMNS, STILL_WAITING_MS, higherCap, shortInChat, POSITIVE_ATOMIC9, SHORT_QUESTION, SHORT_QUESTION_TOKENS, PASTE_JOIN_MS, CAP_CODES, WAIT_CODES, NO_ANSWER_CODES, HISTORY_CODES, chatFloatTerms, floatRetry, floatSpent, FLOAT_NOT_PAID, asSentence, upFirst, lowFirst, NOTHING_PAID, CAP_FROM, PROGRESS_LINE, SHOWN_PROGRESS, isProgressLine, fail46, nothingPaid;
|
|
146055
146232
|
var init_chat = __esm({
|
|
146056
146233
|
"wallet/src/inference/chat.mjs"() {
|
|
146057
146234
|
"use strict";
|
|
@@ -146133,6 +146310,7 @@ var init_chat = __esm({
|
|
|
146133
146310
|
});
|
|
146134
146311
|
floatRetry = (code2, facts) => /_retry_same_request$|_retry_later$/.test(code2) || ["p03_float_already_paid", "p03_float_config_unreadable"].includes(code2) || code2 === "p03_float_request_refused" && facts.floatCode === "float_quote_in_progress" || code2 === "p03_float_seller_kept_payment" && facts.resent !== true && facts.pruned !== true && facts.httpStatus !== 402;
|
|
146135
146312
|
floatSpent = (code2, facts) => code2 === "p03_float_receipt_pruned" || code2 === "p03_float_seller_kept_payment" && !floatRetry(code2, facts);
|
|
146313
|
+
FLOAT_NOT_PAID = /* @__PURE__ */ new Set(["p03_float_request_expired_nothing_paid"]);
|
|
146136
146314
|
asSentence = (text3) => `${text3.charAt(0).toUpperCase()}${text3.slice(1).replace(/[.;\s]+$/, "")}.`;
|
|
146137
146315
|
upFirst = (text3) => `${text3.charAt(0).toUpperCase()}${text3.slice(1)}`;
|
|
146138
146316
|
lowFirst = (text3) => `${text3.charAt(0).toLowerCase()}${text3.slice(1)}`;
|
|
@@ -153380,7 +153558,7 @@ var INFER_MODEL_IDS = ["claude-opus-5", "deepseek-v4-1-flash", "qwen3-8-flash"];
|
|
|
153380
153558
|
var INFER_EXAMPLE_TAIL = `--max-tokens 512 --max-payment 0.02 --max-session 0.1 ${PAYER_SESSION_BASE} --tor`;
|
|
153381
153559
|
var INFER_COST_LINE = "The AI provider charges its quoted cap for --max-tokens a request (often far below 0.01 USDC; 0.01 USDC on its standard offer, so --max-payment must cover that) and keeps what the answer does not use (no refund of the rest); the wallet pays the AI provider's price plus Shinjuku's fee (Shinjuku pays the AI provider for you), never more than --max-payment a request; the AI provider and the company that runs the model see your prompt and the answer. The chain shows one private payment, not who paid";
|
|
153382
153560
|
var INFER_STDIN_MAX_BYTES = 1024 * 1024;
|
|
153383
|
-
var INFER_STDIN_EXAMPLE = `
|
|
153561
|
+
var INFER_STDIN_EXAMPLE = `cat question.txt | ${CLI_WORD} infer -`;
|
|
153384
153562
|
var CURL_USEPOD_NEXT = `use \`${CLI_WORD} infer\` for the AI provider: it sends the prompt only through --tor or --proxy`;
|
|
153385
153563
|
function unshieldArgs(command, args) {
|
|
153386
153564
|
if (args.includes("--amount")) return args;
|
|
@@ -153411,6 +153589,7 @@ function inferArgs(command, args) {
|
|
|
153411
153589
|
index += 1;
|
|
153412
153590
|
}
|
|
153413
153591
|
}
|
|
153592
|
+
if (!out.includes("--prompt") && !out.includes("--help") && !out.includes("-h") && process.stdin.isTTY) out.push("--prompt", "-");
|
|
153414
153593
|
return out;
|
|
153415
153594
|
}
|
|
153416
153595
|
function inferTorGate(env) {
|
|
@@ -153430,7 +153609,7 @@ function validateInfer(values, env) {
|
|
|
153430
153609
|
}
|
|
153431
153610
|
if (values.has("--max-tokens") && Number(values.get("--max-tokens")) < 1) throw new UsageError("--max-tokens must be at least 1 (give 256 or more, 512 answers a short question: a reasoning model like qwen3-8-flash thinks first, and with fewer tokens it can stop before it answers, still paid): it sets the most the request can cost");
|
|
153432
153611
|
if (!values.get("--prompt").trim()) {
|
|
153433
|
-
throw new UsageError(`the prompt is empty:
|
|
153612
|
+
throw new UsageError(`the prompt is empty: run ${CLI_WORD} infer alone in a terminal and type the question when it asks, or pipe it in from a file, like ${INFER_STDIN_EXAMPLE}`);
|
|
153434
153613
|
}
|
|
153435
153614
|
if (!values.has(WALLET_FROM_SETUP) && (values.has("--pool") || values.has("--wallet"))) inferTorGate(env);
|
|
153436
153615
|
}
|
|
@@ -153466,6 +153645,22 @@ async function readStdinBytes({ maxBytes }) {
|
|
|
153466
153645
|
async function inferPrompt(values, deps) {
|
|
153467
153646
|
const given = values.get("--prompt");
|
|
153468
153647
|
if (given !== "-") return given;
|
|
153648
|
+
if (!deps.readStdin && process.stdin.isTTY) {
|
|
153649
|
+
const asker = createInterface2({ input: process.stdin, output: process.stderr, terminal: true });
|
|
153650
|
+
let line;
|
|
153651
|
+
try {
|
|
153652
|
+
line = await new Promise((resolveLine) => {
|
|
153653
|
+
asker.once("close", () => resolveLine(null));
|
|
153654
|
+
asker.question("Type your question, then press Enter: ", resolveLine);
|
|
153655
|
+
});
|
|
153656
|
+
} finally {
|
|
153657
|
+
asker.close();
|
|
153658
|
+
}
|
|
153659
|
+
if (line === null || !String(line).trim()) {
|
|
153660
|
+
throw new UsageError(`no question was typed, so nothing was sent or paid. Run ${cli4()} infer again and type your question, or use ${cli4()} chat`);
|
|
153661
|
+
}
|
|
153662
|
+
return String(line);
|
|
153663
|
+
}
|
|
153469
153664
|
const raw = await (deps.readStdin ?? readStdinBytes)({ maxBytes: INFER_STDIN_MAX_BYTES });
|
|
153470
153665
|
const bytes2 = typeof raw === "string" ? Buffer.from(raw, "utf8") : Buffer.from(raw ?? []);
|
|
153471
153666
|
if (bytes2.length > INFER_STDIN_MAX_BYTES) {
|
|
@@ -153625,10 +153820,13 @@ function inferOutput(result, { values, io, model: model2, quiet, requestId, held
|
|
|
153625
153820
|
` : `paid ${paidText}${quiet ? "" : ` request-id ${result.requestId ?? requestId}`}${stopped}
|
|
153626
153821
|
`);
|
|
153627
153822
|
}
|
|
153823
|
+
const empty = !String(result.content ?? "").trim();
|
|
153824
|
+
const emptyWords = result.finishReason === "length" ? `The model used all its tokens before its answer started, so no answer came back (${replayed || held ? "paid earlier" : `paid ${paidText}`}). Ask again with a higher --max-tokens, or use another model (${cli4()} infer models).` : `The model sent an empty answer (${replayed || held ? "paid earlier" : `paid ${paidText}`}). Ask again: that is a new question and pays again.`;
|
|
153628
153825
|
if (values.has("--json")) {
|
|
153629
153826
|
io.out(`${JSON.stringify(
|
|
153630
153827
|
{
|
|
153631
|
-
ok:
|
|
153828
|
+
ok: !empty,
|
|
153829
|
+
...empty ? { error: "inference_empty_answer", message: emptyWords } : {},
|
|
153632
153830
|
model: result.model ?? model2,
|
|
153633
153831
|
content: result.content,
|
|
153634
153832
|
finishReason: result.finishReason,
|
|
@@ -153643,10 +153841,16 @@ function inferOutput(result, { values, io, model: model2, quiet, requestId, held
|
|
|
153643
153841
|
(key, value2) => typeof value2 === "bigint" ? value2.toString() : value2
|
|
153644
153842
|
)}
|
|
153645
153843
|
`);
|
|
153844
|
+
if (empty) throw new PrintedFailure("inference_empty_answer");
|
|
153646
153845
|
return;
|
|
153647
153846
|
}
|
|
153648
153847
|
for (const line of paidNotices) io.err(`${line}
|
|
153649
153848
|
`);
|
|
153849
|
+
if (empty) {
|
|
153850
|
+
io.err(`${emptyWords}${quiet ? "" : ` request-id ${result.requestId ?? requestId}`}
|
|
153851
|
+
`);
|
|
153852
|
+
throw new PrintedFailure("inference_empty_answer");
|
|
153853
|
+
}
|
|
153650
153854
|
io.out(`${result.content ?? ""}
|
|
153651
153855
|
`);
|
|
153652
153856
|
if (plainPaid) {
|
|
@@ -154225,6 +154429,13 @@ var RanBehindTorFailed = class extends Error {
|
|
|
154225
154429
|
this.exitCode = code2;
|
|
154226
154430
|
}
|
|
154227
154431
|
};
|
|
154432
|
+
var PrintedFailure = class extends Error {
|
|
154433
|
+
constructor(code2) {
|
|
154434
|
+
super(code2);
|
|
154435
|
+
this.code = code2;
|
|
154436
|
+
this.exitCode = 1;
|
|
154437
|
+
}
|
|
154438
|
+
};
|
|
154228
154439
|
function chatBeforeValidate(values, deps, args) {
|
|
154229
154440
|
values.set(CHAT_RAW_ARGS, args);
|
|
154230
154441
|
if (values.has("--wallet") || values.has("--pool")) return void 0;
|
|
@@ -156392,7 +156603,7 @@ var COMMANDS = [
|
|
|
156392
156603
|
summary: "Ask an AI model one question and pay for the answer from your private balance (Shielded Inference, through the AI provider's x402 route).",
|
|
156393
156604
|
env: [],
|
|
156394
156605
|
flags: [
|
|
156395
|
-
flag2("--prompt", "<text>", `what to ask; write - to read it from stdin (
|
|
156606
|
+
flag2("--prompt", "<text>", `what to ask; with no question in a terminal, infer asks for it (the words stay out of your shell history); write - to read it from stdin (a file or a script), or write it alone, in quotes (${CLI_WORD} infer "Summarize x402 in one line" ...)`, { required: true }),
|
|
156396
156607
|
flag2("--model", "<id>", `the model (default ${DEFAULT_MODEL2}): ${INFER_MODEL_IDS.join(", ")} (${CLI_WORD} infer models lists their prices)`),
|
|
156397
156608
|
flag2("--max-tokens", "<n>", "the longest answer to pay for, in tokens; default 4096, 512 for claude-opus-5 (give 256 or more; 512 answers a short question: a reasoning model like qwen3-8-flash thinks first, and with fewer tokens it can stop before it answers, still paid); it sets the most this request can cost", { check: "count" }),
|
|
156398
156609
|
flag2("--max-payment", "<usdc>", `the most this request may pay in all, in USDC (0.02 = 2 cents). It must be at least 0.011: the wallet never sets a call's ceiling below the AI provider's 0.01 USDC floor on its standard offer, and a call also pays Shinjuku's 0.001 USDC fee, so 0.02 covers it. What a call pays is the AI provider's quote for --max-tokens plus Shinjuku's fee: with ${DEFAULT_MODEL2} and the default ${DEFAULT_MAX_TOKENS} tokens, a short question costs about ${usdcOr(DEFAULT_ANSWER_PAID_ATOMIC)}, at most 0.011 USDC: 0.01 USDC plus the fee when the AI provider offers only its standard payment. A higher ceiling is refused before anything is paid. Default: from your limits (setup or limits sets them), else 0.05`, { check: "atomic", usdc: true }),
|
|
@@ -156405,12 +156616,12 @@ var COMMANDS = [
|
|
|
156405
156616
|
],
|
|
156406
156617
|
examples: [
|
|
156407
156618
|
`${CLI_WORD} infer "Say hello in three words"`,
|
|
156408
|
-
|
|
156409
|
-
`
|
|
156619
|
+
`${CLI_WORD} infer`,
|
|
156620
|
+
`cat question.txt | ${CLI_WORD} infer - --model claude-opus-5 --json ${INFER_EXAMPLE_TAIL}`
|
|
156410
156621
|
],
|
|
156411
156622
|
notes: [
|
|
156412
156623
|
`After setup it needs no flags, as chat: config.json gives the wallet, the model is ${DEFAULT_MODEL2}, the caps are from your limits (setup or limits sets them; else 0.05 USDC a call and 1 USDC a run), and it runs behind Tor by itself (Tor must run, as setup recorded it). A flag you give still wins. With --pool or --wallet the command line is the whole config: then add --tor (or --proxy <url>).`,
|
|
156413
|
-
`Private form (recommended):
|
|
156624
|
+
`Private form (recommended): type ${CLI_WORD} infer alone in a terminal, and type the question when it asks: the words are not in the command line, the process list or your shell history. A question typed on the command line (in quotes) is saved in your shell history. For a file or a script, write - and pipe the question in: ${INFER_STDIN_EXAMPLE}; stdin is read until it ends (UTF-8, at most 1 MiB); an empty one is refused before anything is paid.`,
|
|
156414
156625
|
"It runs only through Tor (or --proxy <url>), never a direct connection: the AI provider would see your IP address next to your prompt, so the command refuses before anything is sent.",
|
|
156415
156626
|
`${INFER_COST_LINE}. stderr says this before the payment, with the most the request can cost.`,
|
|
156416
156627
|
"stdout holds the answer; stderr says paid <amount> USDC request-id <id>. An answer cut short by --max-tokens says so. The wallet's own progress lines (Tor, the RPC relay, the pool history walk, the memo reads) show only with --verbose; warnings and failures always show.",
|
|
@@ -156435,7 +156646,7 @@ var COMMANDS = [
|
|
|
156435
156646
|
flags: [bool2("--json", "print the list as one JSON line (prices in atomic USDC per 1M tokens)")],
|
|
156436
156647
|
examples: [`${CLI_WORD} infer models`, `${CLI_WORD} infer models --json`],
|
|
156437
156648
|
notes: [`${INFER_COST_LINE}.`],
|
|
156438
|
-
next: `ask one:
|
|
156649
|
+
next: `ask one: ${CLI_WORD} infer (it asks for the question), or chat: ${CLI_WORD} chat`,
|
|
156439
156650
|
run: (args, values, deps, io) => deps.inferModelsMain(values, { ...deps, io })
|
|
156440
156651
|
},
|
|
156441
156652
|
{
|
|
@@ -159815,7 +160026,7 @@ function failureHint(command, reason, deps, values, floatError) {
|
|
|
159815
160026
|
}
|
|
159816
160027
|
const floatCode = /\b(p03_float_[a-z_]+|wallet_quote_refused_[a-z0-9_]+|p03_resource_paid_seller_failed)\b/.exec(reason)?.[1];
|
|
159817
160028
|
const facts = REQUEST_ID_TAKEN2.test(reason) ? { ...floatError, ...conflictRecordFacts(reason, values, deps) } : floatError;
|
|
159818
|
-
const float = floatCode ? floatOutcomeWords(floatCode, facts, CLI_FLOAT_TERMS(values, deps, command)) : void 0;
|
|
160029
|
+
const float = floatCode ? floatOutcomeWords(floatCode, command?.name === "infer" ? withoutProviderText(facts) : facts, CLI_FLOAT_TERMS(values, deps, command)) : void 0;
|
|
159819
160030
|
if (float) return `${float[1].replace(/[.;\s]+$/, "")}. ${float[2]}`;
|
|
159820
160031
|
const pocketHint = pocketFailureHint(reason, command);
|
|
159821
160032
|
if (pocketHint) return pocketHint;
|
|
@@ -160643,12 +160854,14 @@ This copy: ${walletVersionLine(deps.walletVersion())}
|
|
|
160643
160854
|
}
|
|
160644
160855
|
if (isFamily(name)) {
|
|
160645
160856
|
if (INTERNAL_FAMILIES.has(name) && args.length === 0) throw new UsageError("Unknown command.");
|
|
160646
|
-
|
|
160857
|
+
const aloneInTerminal = args.length === 0 && COMMAND_BY_NAME.has(name) && process.stdin.isTTY === true;
|
|
160858
|
+
if (args.length === 0 && !aloneInTerminal) {
|
|
160647
160859
|
io.out(familyOverviewText(name));
|
|
160648
160860
|
return 0;
|
|
160649
160861
|
}
|
|
160650
160862
|
const three = `${name} ${args[0]} ${args[1]}`;
|
|
160651
|
-
if (
|
|
160863
|
+
if (aloneInTerminal) command = COMMAND_BY_NAME.get(name);
|
|
160864
|
+
else if (COMMAND_BY_NAME.has(name) && !COMMAND_BY_NAME.has(`${name} ${args[0]}`) && !COMMAND_BY_NAME.has(three)) command = COMMAND_BY_NAME.get(name);
|
|
160652
160865
|
else command = COMMAND_BY_NAME.has(three) ? (args.splice(0, 2), COMMAND_BY_NAME.get(three)) : COMMAND_BY_NAME.get(`${name} ${args.shift()}`);
|
|
160653
160866
|
if (!command && INTERNAL_FAMILIES.has(name)) throw new UsageError("Unknown command.");
|
|
160654
160867
|
if (!command) {
|
|
@@ -160724,6 +160937,10 @@ This copy: ${walletVersionLine(deps.walletVersion())}
|
|
|
160724
160937
|
if (endsProcess) showProgressAgain = () => {
|
|
160725
160938
|
};
|
|
160726
160939
|
if (error instanceof RanBehindTorFailed) return error.exitCode;
|
|
160940
|
+
if (error instanceof PrintedFailure) {
|
|
160941
|
+
writeRunResult(deps, command, error.exitCode, error);
|
|
160942
|
+
return error.exitCode;
|
|
160943
|
+
}
|
|
160727
160944
|
if (error instanceof UsageError) {
|
|
160728
160945
|
let setUp = false;
|
|
160729
160946
|
try {
|
|
@@ -160843,7 +161060,7 @@ Next: fund that address, then rerun the same command; it continues where it stop
|
|
|
160843
161060
|
const blockingLine = typeof blocking === "string" && /^[A-Za-z0-9._:-]{1,128}$/.test(blocking) ? `earlier payment: --request-id ${blocking}
|
|
160844
161061
|
` : "";
|
|
160845
161062
|
const payee = command.name === "infer" ? "the AI provider" : "the seller";
|
|
160846
|
-
const sellerSaid = error?.sellerReason ?? error?.cause?.sellerReason;
|
|
161063
|
+
const sellerSaid = command.name === "infer" ? void 0 : error?.sellerReason ?? error?.cause?.sellerReason;
|
|
160847
161064
|
const sellerLine = typeof sellerSaid === "string" && sellerSaid ? `${payee === "the seller" ? "seller" : payee} answered HTTP ${error?.httpStatus ?? error?.cause?.httpStatus}: ${JSON.stringify(sellerSaid)}
|
|
160848
161065
|
` : "";
|
|
160849
161066
|
const landedTx = error?.transaction ?? error?.cause?.transaction;
|