@lucid-agents/taskmarket 1.17.2 → 1.18.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/dist/THIRD_PARTY_NOTICES.md +54 -27
- package/dist/agent-compatibility.json +1 -1
- package/dist/{budget-view-XKZC3GY5.js → budget-view-JPZ7HWR2.js} +1 -1
- package/dist/{channels-JF4Q5KG3.js → channels-KCDZ5REF.js} +4 -3
- package/dist/chunk-3FF6JAMK.js +868 -0
- package/dist/{chunk-52Q2DCZN.js → chunk-3LNZ766H.js} +23 -23
- package/dist/chunk-5VMWXDNO.js +7518 -0
- package/dist/{chunk-73RXOYME.js → chunk-EB6OJBF5.js} +5 -0
- package/dist/chunk-HEGWADBV.js +447 -0
- package/dist/{chunk-GJQUALXN.js → chunk-LEVAZYR5.js} +106 -29
- package/dist/{launch-2U3KFTFD.js → chunk-ONYTKAHC.js} +4977 -2385
- package/dist/chunk-RHUDL5WA.js +351 -0
- package/dist/chunk-RQTJZYFV.js +831 -0
- package/dist/chunk-YB2B5DPR.js +10320 -0
- package/dist/chunk-ZIC2YCLV.js +65 -0
- package/dist/{doctor-7TWLIJWW.js → doctor-TB3KKAZB.js} +13 -10
- package/dist/index.js +2065 -712
- package/dist/launch-ZV6OLBFM.js +6364 -0
- package/dist/pi-extensions/remote-tools.cjs +74 -3
- package/dist/pi-extensions/xgate.cjs +1039 -25
- package/dist/{status-5IMULBQQ.js → prompter-LSICEYSQ.js} +3 -12
- package/dist/reconcile-UXL65RRT.js +194 -0
- package/dist/status-FHZ3UGEB.js +28 -0
- package/dist/sync-pull-YECZ4PJA.js +409 -0
- package/package.json +1 -1
- package/dist/chunk-FRV3ZHUR.js +0 -16141
- package/dist/chunk-LDCFKFF6.js +0 -154
- package/dist/chunk-XXD7TWLP.js +0 -181
- package/dist/reconcile-XZR2UYSW.js +0 -83
package/dist/chunk-LDCFKFF6.js
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { createRequire as __tmCreateRequire } from 'node:module'; import { fileURLToPath as __tmFileURLToPath } from 'node:url'; import { dirname as __tmDirname } from 'node:path'; const require = __tmCreateRequire(import.meta.url); const __tmFilename = __tmFileURLToPath(import.meta.url); const __tmDirnameValue = __tmDirname(__tmFilename);
|
|
2
|
-
import {
|
|
3
|
-
buyComputeCredit,
|
|
4
|
-
fetchComputePricing,
|
|
5
|
-
listPendingComputePurchases,
|
|
6
|
-
loadComputeCreditConfig,
|
|
7
|
-
onComputeBalanceObserved,
|
|
8
|
-
readComputeCreditStatus
|
|
9
|
-
} from "./chunk-52Q2DCZN.js";
|
|
10
|
-
import {
|
|
11
|
-
AgentLaunchError
|
|
12
|
-
} from "./chunk-YM4S6IE4.js";
|
|
13
|
-
import {
|
|
14
|
-
burnRate,
|
|
15
|
-
computeLow
|
|
16
|
-
} from "./chunk-73RXOYME.js";
|
|
17
|
-
|
|
18
|
-
// ../../packages/remote-tools/dist/backend.js
|
|
19
|
-
var SANDBOX_TOOL_USER = "agent";
|
|
20
|
-
var SandboxUnavailableError = class extends Error {
|
|
21
|
-
reason;
|
|
22
|
-
constructor(reason, options) {
|
|
23
|
-
super(`Sandbox unavailable, tools are disabled (no local fallback): ${reason}`, options);
|
|
24
|
-
this.name = "SandboxUnavailableError";
|
|
25
|
-
this.reason = reason;
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
// src/lib/agent/compute.ts
|
|
30
|
-
async function readComputeView(options = {}) {
|
|
31
|
-
const warning = options.warning ?? null;
|
|
32
|
-
const empty = {
|
|
33
|
-
availableCredits: null,
|
|
34
|
-
reservedCredits: null,
|
|
35
|
-
burnCreditsPerHour: null,
|
|
36
|
-
low: warning === "low_credit" || warning === "credit_exhausted",
|
|
37
|
-
warning,
|
|
38
|
-
pendingPurchases: 0,
|
|
39
|
-
autoTopUp: null
|
|
40
|
-
};
|
|
41
|
-
let config;
|
|
42
|
-
try {
|
|
43
|
-
config = await loadComputeCreditConfig();
|
|
44
|
-
} catch (error) {
|
|
45
|
-
return { configured: false, ...empty, error: error.message };
|
|
46
|
-
}
|
|
47
|
-
if (!config) return { configured: false, ...empty };
|
|
48
|
-
try {
|
|
49
|
-
let status = await readComputeCreditStatus();
|
|
50
|
-
if (options.observe && await options.observe({ availableCredits: status.balance.availableCredits })) {
|
|
51
|
-
status = await readComputeCreditStatus();
|
|
52
|
-
}
|
|
53
|
-
const burn = burnRate(status.debits);
|
|
54
|
-
const autoTopUp = config.autoTopUp ? {
|
|
55
|
-
thresholdCredits: config.autoTopUp.thresholdCredits,
|
|
56
|
-
amountUsd: config.autoTopUp.amountUsd,
|
|
57
|
-
maxChunksPerDay: config.autoTopUp.maxChunksPerDay
|
|
58
|
-
} : null;
|
|
59
|
-
return {
|
|
60
|
-
configured: true,
|
|
61
|
-
availableCredits: status.balance.availableCredits,
|
|
62
|
-
reservedCredits: status.balance.reservedCredits,
|
|
63
|
-
burnCreditsPerHour: burn,
|
|
64
|
-
low: computeLow({
|
|
65
|
-
availableCredits: status.balance.availableCredits,
|
|
66
|
-
burnCreditsPerHour: burn,
|
|
67
|
-
warning,
|
|
68
|
-
...autoTopUp ? { thresholdCredits: autoTopUp.thresholdCredits } : {}
|
|
69
|
-
}),
|
|
70
|
-
warning,
|
|
71
|
-
pendingPurchases: (await listPendingComputePurchases()).length,
|
|
72
|
-
autoTopUp
|
|
73
|
-
};
|
|
74
|
-
} catch (error) {
|
|
75
|
-
return {
|
|
76
|
-
configured: true,
|
|
77
|
-
...empty,
|
|
78
|
-
error: error.code ?? error.message
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
async function computeAllocationId() {
|
|
83
|
-
return (await loadComputeCreditConfig().catch(() => void 0))?.allocationId;
|
|
84
|
-
}
|
|
85
|
-
async function computeCreditOffer() {
|
|
86
|
-
const pricing = await fetchComputePricing();
|
|
87
|
-
return {
|
|
88
|
-
usdPerCredit: pricing.usdPerCredit,
|
|
89
|
-
denominations: pricing.denominations.map((entry) => ({
|
|
90
|
-
amountUsd: entry.amountUsd,
|
|
91
|
-
credits: entry.credits,
|
|
92
|
-
default: entry.default
|
|
93
|
-
}))
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
async function buyComputeChunk(amountUsd) {
|
|
97
|
-
const pricing = await fetchComputePricing();
|
|
98
|
-
const size = amountUsd ?? (pricing.denominations.find((entry) => entry.default) ?? pricing.denominations[0])?.amountUsd;
|
|
99
|
-
if (size === void 0) {
|
|
100
|
-
throw new AgentLaunchError("invalid_amount", "The API sells no compute credit sizes");
|
|
101
|
-
}
|
|
102
|
-
const bought = await buyComputeCredit({ amountUsd: size });
|
|
103
|
-
return { purchase: bought.purchase, balance: bought.balance, amountUsd: size };
|
|
104
|
-
}
|
|
105
|
-
function computeCreditObserver(log) {
|
|
106
|
-
return async (observation) => {
|
|
107
|
-
try {
|
|
108
|
-
const { topUp } = await onComputeBalanceObserved(observation);
|
|
109
|
-
if (topUp.action === "bought") log("Compute credit auto-top-up bought one chunk");
|
|
110
|
-
else if (topUp.action === "skipped")
|
|
111
|
-
log(`Compute credit auto-top-up skipped: ${topUp.reason}`);
|
|
112
|
-
return topUp.action === "bought";
|
|
113
|
-
} catch (error) {
|
|
114
|
-
log(
|
|
115
|
-
`Compute credit auto-top-up failed: ${error.code ?? error.message}`
|
|
116
|
-
);
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
function insufficientCredit(error) {
|
|
122
|
-
return error instanceof SandboxUnavailableError && /\binsufficient_credit\b/.test(error.reason);
|
|
123
|
-
}
|
|
124
|
-
async function openSandbox(createBroker, observe) {
|
|
125
|
-
const first = createBroker();
|
|
126
|
-
try {
|
|
127
|
-
await first.connect("start");
|
|
128
|
-
return first;
|
|
129
|
-
} catch (error) {
|
|
130
|
-
if (!insufficientCredit(error)) throw error;
|
|
131
|
-
if (!await observe({ creditWarning: "credit_exhausted" })) {
|
|
132
|
-
throw new AgentLaunchError("insufficient_credit", error.reason);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
const retry = createBroker();
|
|
136
|
-
try {
|
|
137
|
-
await retry.connect("start");
|
|
138
|
-
return retry;
|
|
139
|
-
} catch (error) {
|
|
140
|
-
if (insufficientCredit(error)) throw new AgentLaunchError("insufficient_credit", error.reason);
|
|
141
|
-
throw error;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export {
|
|
146
|
-
SANDBOX_TOOL_USER,
|
|
147
|
-
SandboxUnavailableError,
|
|
148
|
-
readComputeView,
|
|
149
|
-
computeAllocationId,
|
|
150
|
-
computeCreditOffer,
|
|
151
|
-
buyComputeChunk,
|
|
152
|
-
computeCreditObserver,
|
|
153
|
-
openSandbox
|
|
154
|
-
};
|
package/dist/chunk-XXD7TWLP.js
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import { createRequire as __tmCreateRequire } from 'node:module'; import { fileURLToPath as __tmFileURLToPath } from 'node:url'; import { dirname as __tmDirname } from 'node:path'; const require = __tmCreateRequire(import.meta.url); const __tmFilename = __tmFileURLToPath(import.meta.url); const __tmDirnameValue = __tmDirname(__tmFilename);
|
|
2
|
-
import {
|
|
3
|
-
computeAllocationId,
|
|
4
|
-
readComputeView
|
|
5
|
-
} from "./chunk-LDCFKFF6.js";
|
|
6
|
-
import {
|
|
7
|
-
allocationViews,
|
|
8
|
-
channelView,
|
|
9
|
-
getAgentPolicyPath,
|
|
10
|
-
openAgentChannels,
|
|
11
|
-
uncertainPurchases,
|
|
12
|
-
withdrawalHatch
|
|
13
|
-
} from "./chunk-GJQUALXN.js";
|
|
14
|
-
import {
|
|
15
|
-
SandboxListOutputSchema,
|
|
16
|
-
apiUrl
|
|
17
|
-
} from "./chunk-FRV3ZHUR.js";
|
|
18
|
-
import {
|
|
19
|
-
AgentLaunchError
|
|
20
|
-
} from "./chunk-YM4S6IE4.js";
|
|
21
|
-
import {
|
|
22
|
-
AGENT_VIEW_VERSION,
|
|
23
|
-
blockingPurchases,
|
|
24
|
-
channelLines,
|
|
25
|
-
computeLines,
|
|
26
|
-
formatUsdc
|
|
27
|
-
} from "./chunk-73RXOYME.js";
|
|
28
|
-
|
|
29
|
-
// src/lib/agent/status.ts
|
|
30
|
-
async function listSandboxes(credentials, fetchImpl = fetch) {
|
|
31
|
-
const response = await fetchImpl(`${apiUrl().replace(/\/+$/, "")}/api/sandboxes/list`, {
|
|
32
|
-
method: "POST",
|
|
33
|
-
redirect: "error",
|
|
34
|
-
headers: { "content-type": "application/json" },
|
|
35
|
-
body: JSON.stringify(credentials),
|
|
36
|
-
signal: AbortSignal.timeout(15e3)
|
|
37
|
-
});
|
|
38
|
-
if (!response.ok) {
|
|
39
|
-
await response.body?.cancel().catch(() => void 0);
|
|
40
|
-
throw new Error(`the sandbox broker answered ${response.status}`);
|
|
41
|
-
}
|
|
42
|
-
const parsed = SandboxListOutputSchema.safeParse(await response.json());
|
|
43
|
-
if (!parsed.success) throw new Error("the sandbox list is malformed");
|
|
44
|
-
return parsed.data.sandboxes.map((s) => ({
|
|
45
|
-
sandboxId: s.sandboxId,
|
|
46
|
-
purpose: s.purpose,
|
|
47
|
-
state: s.state,
|
|
48
|
-
meteredSeconds: s.meteredSeconds,
|
|
49
|
-
lastActiveAt: s.lastActiveAt,
|
|
50
|
-
expiresAt: s.expiresAt,
|
|
51
|
-
creditWarning: s.creditWarning,
|
|
52
|
-
creditGraceUntil: s.creditGraceUntil
|
|
53
|
-
}));
|
|
54
|
-
}
|
|
55
|
-
function message(error) {
|
|
56
|
-
return error.code ?? error.message;
|
|
57
|
-
}
|
|
58
|
-
async function collectAgentStatus(deps = {}) {
|
|
59
|
-
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
60
|
-
const view = {
|
|
61
|
-
version: AGENT_VIEW_VERSION,
|
|
62
|
-
kind: "taskmarket.agent.status",
|
|
63
|
-
generatedAt: now().toISOString(),
|
|
64
|
-
wallet: null,
|
|
65
|
-
policy: { state: "missing", path: getAgentPolicyPath(), models: [] },
|
|
66
|
-
channels: [],
|
|
67
|
-
purchases: { uncertain: [] },
|
|
68
|
-
inference: { blocked: false, reasons: [] },
|
|
69
|
-
allocations: [],
|
|
70
|
-
sandbox: { state: "no_wallet", sandboxes: [] },
|
|
71
|
-
compute: {
|
|
72
|
-
configured: false,
|
|
73
|
-
availableCredits: null,
|
|
74
|
-
reservedCredits: null,
|
|
75
|
-
burnCreditsPerHour: null,
|
|
76
|
-
low: false,
|
|
77
|
-
warning: null,
|
|
78
|
-
pendingPurchases: 0,
|
|
79
|
-
autoTopUp: null
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
const reasons = view.inference.reasons;
|
|
83
|
-
let credentials;
|
|
84
|
-
try {
|
|
85
|
-
const opened = await (deps.openChannels ?? openAgentChannels)();
|
|
86
|
-
view.wallet = { address: opened.keystore.walletAddress };
|
|
87
|
-
credentials = { deviceId: opened.keystore.deviceId, apiToken: opened.keystore.apiToken };
|
|
88
|
-
view.policy = { state: "approved", path: view.policy.path, models: [...opened.policy.models] };
|
|
89
|
-
const statuses = /* @__PURE__ */ new Map();
|
|
90
|
-
for (const rail of opened.rails) {
|
|
91
|
-
const status = await rail.payer.channelStatus();
|
|
92
|
-
statuses.set(rail.rail.id, status);
|
|
93
|
-
const channel = await channelView(rail, status);
|
|
94
|
-
view.channels.push({ ...channel, withdrawal: withdrawalHatch(channel) });
|
|
95
|
-
}
|
|
96
|
-
for (const rail of opened.retired ?? []) {
|
|
97
|
-
const channel = await channelView(rail, void 0, { retired: true });
|
|
98
|
-
view.channels.push({ ...channel, withdrawal: withdrawalHatch(channel) });
|
|
99
|
-
}
|
|
100
|
-
view.purchases.uncertain = [
|
|
101
|
-
...await uncertainPurchases(opened.rails, statuses),
|
|
102
|
-
...await uncertainPurchases(opened.retired ?? [])
|
|
103
|
-
];
|
|
104
|
-
view.allocations = await allocationViews(opened.rails, [
|
|
105
|
-
await (deps.computeAllocation ?? computeAllocationId)()
|
|
106
|
-
]);
|
|
107
|
-
} catch (error) {
|
|
108
|
-
if (error instanceof AgentLaunchError && error.code === "wallet_required") {
|
|
109
|
-
reasons.push("no wallet: run taskmarket wallet import");
|
|
110
|
-
} else if (error instanceof AgentLaunchError && error.code === "setup_required") {
|
|
111
|
-
reasons.push("no approved spending policy");
|
|
112
|
-
} else {
|
|
113
|
-
view.policy = { ...view.policy, state: "invalid", error: message(error) };
|
|
114
|
-
reasons.push(`the spending policy cannot be used: ${message(error)}`);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
const active = view.channels.filter((channel) => !channel.retired);
|
|
118
|
-
for (const id of blockingPurchases({ channels: active, unresolved: [] })) {
|
|
119
|
-
reasons.push(`purchase ${id} is unresolved: taskmarket agent reconcile ${id}`);
|
|
120
|
-
}
|
|
121
|
-
for (const channel of active) {
|
|
122
|
-
if (channel.state !== "open") reasons.push(`channel ${channel.rail} is ${channel.state}`);
|
|
123
|
-
}
|
|
124
|
-
if (credentials) {
|
|
125
|
-
try {
|
|
126
|
-
view.sandbox = {
|
|
127
|
-
state: "ok",
|
|
128
|
-
sandboxes: await (deps.listSandboxes ?? listSandboxes)(credentials)
|
|
129
|
-
};
|
|
130
|
-
} catch (error) {
|
|
131
|
-
view.sandbox = { state: "unavailable", sandboxes: [], error: message(error) };
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
const warning = view.sandbox.sandboxes.find((s) => s.purpose === "interactive" && s.creditWarning)?.creditWarning ?? null;
|
|
135
|
-
view.compute = await (deps.readCompute ?? readComputeView)({ warning });
|
|
136
|
-
view.inference.blocked = reasons.length > 0;
|
|
137
|
-
return view;
|
|
138
|
-
}
|
|
139
|
-
function statusLines(view) {
|
|
140
|
-
const lines = [
|
|
141
|
-
`taskmarket agent status (view v${view.version}, ${view.generatedAt})`,
|
|
142
|
-
view.wallet ? `Wallet: ${view.wallet.address}` : "Wallet: none",
|
|
143
|
-
`Spending policy: ${view.policy.state}${view.policy.models.length ? ` (${view.policy.models.join(", ")})` : ""}${view.policy.error ? `: ${view.policy.error}` : ""}`
|
|
144
|
-
];
|
|
145
|
-
for (const channel of view.channels) {
|
|
146
|
-
lines.push(...channelLines(channel));
|
|
147
|
-
if (channel.state === "blocked" || channel.state === "withdrawal_pending") {
|
|
148
|
-
lines.push(` ${channel.withdrawal.note}`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (view.purchases.uncertain.length === 0) {
|
|
152
|
-
lines.push("Purchases with an unknown outcome: none");
|
|
153
|
-
} else {
|
|
154
|
-
lines.push("Purchases with an unknown outcome (never resent; reconcile them):");
|
|
155
|
-
for (const purchase of view.purchases.uncertain) {
|
|
156
|
-
lines.push(
|
|
157
|
-
` ${purchase.invocationId} on ${purchase.rail}: ${purchase.state}, at most ${formatUsdc(purchase.authorizedAtomic)}${purchase.blocking ? ", blocks new turns" : ""}`
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
lines.push(
|
|
162
|
-
view.inference.blocked ? `New inference: blocked (${view.inference.reasons.join("; ")})` : "New inference: ready"
|
|
163
|
-
);
|
|
164
|
-
if (view.sandbox.state === "ok") {
|
|
165
|
-
lines.push(
|
|
166
|
-
view.sandbox.sandboxes.length === 0 ? "Sandbox: none" : `Sandbox: ${view.sandbox.sandboxes.map(
|
|
167
|
-
(s) => `${s.sandboxId} ${s.purpose} ${s.state}${s.creditWarning ? ` (${s.creditWarning})` : ""}`
|
|
168
|
-
).join("; ")}`
|
|
169
|
-
);
|
|
170
|
-
} else if (view.sandbox.state === "unavailable") {
|
|
171
|
-
lines.push(`Sandbox: unavailable (${view.sandbox.error})`);
|
|
172
|
-
}
|
|
173
|
-
lines.push(...computeLines(view.compute));
|
|
174
|
-
return lines;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export {
|
|
178
|
-
listSandboxes,
|
|
179
|
-
collectAgentStatus,
|
|
180
|
-
statusLines
|
|
181
|
-
};
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { createRequire as __tmCreateRequire } from 'node:module'; import { fileURLToPath as __tmFileURLToPath } from 'node:url'; import { dirname as __tmDirname } from 'node:path'; const require = __tmCreateRequire(import.meta.url); const __tmFilename = __tmFileURLToPath(import.meta.url); const __tmDirnameValue = __tmDirname(__tmFilename);
|
|
2
|
-
import {
|
|
3
|
-
openAgentChannels
|
|
4
|
-
} from "./chunk-GJQUALXN.js";
|
|
5
|
-
import {
|
|
6
|
-
X402_INVOCATION_ID_PATTERN
|
|
7
|
-
} from "./chunk-FRV3ZHUR.js";
|
|
8
|
-
import {
|
|
9
|
-
AgentLaunchError
|
|
10
|
-
} from "./chunk-YM4S6IE4.js";
|
|
11
|
-
import {
|
|
12
|
-
AGENT_VIEW_VERSION,
|
|
13
|
-
LOST_RESPONSE_TEXT,
|
|
14
|
-
formatUsdc
|
|
15
|
-
} from "./chunk-73RXOYME.js";
|
|
16
|
-
import "./chunk-S7SJMJ2I.js";
|
|
17
|
-
|
|
18
|
-
// src/lib/agent/reconcile.ts
|
|
19
|
-
function outcomeOf(status) {
|
|
20
|
-
if (status.state === "in_progress") return "in_progress";
|
|
21
|
-
if (status.charge === "manually_resolved") return "resolved_manually";
|
|
22
|
-
if (status.uncertain) return "uncertain";
|
|
23
|
-
if (status.charge === "settled") return "charged";
|
|
24
|
-
if (status.charge === "none" || status.charge === "released") return "not_charged";
|
|
25
|
-
return "uncertain";
|
|
26
|
-
}
|
|
27
|
-
function messageFor(outcome, status) {
|
|
28
|
-
const charged = status.payment?.settledAmount;
|
|
29
|
-
switch (outcome) {
|
|
30
|
-
case "charged":
|
|
31
|
-
return `Charged ${charged !== void 0 ? formatUsdc(charged) : "an amount the router committed"}. If its response did not reach you: ${LOST_RESPONSE_TEXT}`;
|
|
32
|
-
case "not_charged":
|
|
33
|
-
return "Nothing was charged. The request is not sent again; ask again in the agent if you still want an answer.";
|
|
34
|
-
case "in_progress":
|
|
35
|
-
return "It is still being sent by another process; reconcile it again once that finishes.";
|
|
36
|
-
case "resolved_manually":
|
|
37
|
-
return "It was resolved by hand; its recorded amount stands.";
|
|
38
|
-
default:
|
|
39
|
-
return "Its outcome is still unknown. It keeps its maximum counted and blocks new turns on its channel; reconcile it again later. It is never sent again.";
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
async function railFor(rails, invocationId) {
|
|
43
|
-
for (const rail of rails) {
|
|
44
|
-
try {
|
|
45
|
-
await rail.payer.status(invocationId);
|
|
46
|
-
return rail;
|
|
47
|
-
} catch (error) {
|
|
48
|
-
if (error.code !== "invocation_not_found") throw error;
|
|
49
|
-
}
|
|
50
|
-
const lease = (await rail.payer.channelStatus()).pendingOperation;
|
|
51
|
-
if (lease?.kind === "payment" && lease.id === invocationId) return rail;
|
|
52
|
-
}
|
|
53
|
-
throw new AgentLaunchError(
|
|
54
|
-
"invocation_not_found",
|
|
55
|
-
`No agent purchase ${invocationId} is recorded on this device`
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
async function reconcileInvocation(invocationId, deps = {}) {
|
|
59
|
-
if (!X402_INVOCATION_ID_PATTERN.test(invocationId)) {
|
|
60
|
-
throw new AgentLaunchError("invalid_invocation_id", `Not an invocation ID: ${invocationId}`);
|
|
61
|
-
}
|
|
62
|
-
const opened = await (deps.openChannels ?? openAgentChannels)();
|
|
63
|
-
const rail = await railFor([...opened.rails, ...opened.retired ?? []], invocationId);
|
|
64
|
-
const status = await rail.payer.reconcile(invocationId);
|
|
65
|
-
const lease = (await rail.payer.channelStatus()).pendingOperation;
|
|
66
|
-
const outcome = outcomeOf(status);
|
|
67
|
-
return {
|
|
68
|
-
version: AGENT_VIEW_VERSION,
|
|
69
|
-
kind: "taskmarket.agent.reconcile",
|
|
70
|
-
invocationId,
|
|
71
|
-
rail: rail.rail.id,
|
|
72
|
-
outcome,
|
|
73
|
-
state: status.state,
|
|
74
|
-
charge: status.charge,
|
|
75
|
-
authorizedAtomic: status.payment?.authorizedAmount ?? null,
|
|
76
|
-
chargedAtomic: status.payment?.settledAmount ?? null,
|
|
77
|
-
blocksChannel: lease?.kind === "payment" && lease.id === invocationId,
|
|
78
|
-
message: messageFor(outcome, status)
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
export {
|
|
82
|
-
reconcileInvocation
|
|
83
|
-
};
|