@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
|
@@ -0,0 +1,351 @@
|
|
|
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
|
+
attemptsUsed,
|
|
4
|
+
computeAllocationId,
|
|
5
|
+
fileActiveTaskStore,
|
|
6
|
+
loadDeliverableRecord,
|
|
7
|
+
readComputeView,
|
|
8
|
+
taskStage
|
|
9
|
+
} from "./chunk-3FF6JAMK.js";
|
|
10
|
+
import {
|
|
11
|
+
activeClaim,
|
|
12
|
+
captureProblem,
|
|
13
|
+
killedSession,
|
|
14
|
+
loadSyncState,
|
|
15
|
+
orphanOf
|
|
16
|
+
} from "./chunk-ONYTKAHC.js";
|
|
17
|
+
import {
|
|
18
|
+
allocationViews,
|
|
19
|
+
channelView,
|
|
20
|
+
getAgentPolicyPath,
|
|
21
|
+
openAgentChannels,
|
|
22
|
+
uncertainPurchases,
|
|
23
|
+
withdrawalHatch
|
|
24
|
+
} from "./chunk-LEVAZYR5.js";
|
|
25
|
+
import {
|
|
26
|
+
SandboxListOutputSchema,
|
|
27
|
+
apiUrl,
|
|
28
|
+
selectedNetwork
|
|
29
|
+
} from "./chunk-YB2B5DPR.js";
|
|
30
|
+
import {
|
|
31
|
+
AGENT_VIEW_VERSION,
|
|
32
|
+
blockingPurchases,
|
|
33
|
+
channelLines,
|
|
34
|
+
computeLines,
|
|
35
|
+
formatUsdc
|
|
36
|
+
} from "./chunk-EB6OJBF5.js";
|
|
37
|
+
import {
|
|
38
|
+
AgentLaunchError
|
|
39
|
+
} from "./chunk-YM4S6IE4.js";
|
|
40
|
+
|
|
41
|
+
// src/lib/agent/status.ts
|
|
42
|
+
import { promises as fs } from "fs";
|
|
43
|
+
async function readTaskStatus(wallet) {
|
|
44
|
+
const network = selectedNetwork();
|
|
45
|
+
const record = await fileActiveTaskStore(wallet, network.chainId).load();
|
|
46
|
+
if (!record) return null;
|
|
47
|
+
const spec = record.workspace?.spec;
|
|
48
|
+
const deliverable = spec ? await loadDeliverableRecord(record.taskId).catch(() => void 0) : void 0;
|
|
49
|
+
return {
|
|
50
|
+
taskId: record.taskId,
|
|
51
|
+
chainId: record.chainId,
|
|
52
|
+
network: network.name,
|
|
53
|
+
stage: taskStage(record),
|
|
54
|
+
claimId: record.claimId ?? null,
|
|
55
|
+
workspace: record.workspace?.state === "ready" ? record.workspace.path : null,
|
|
56
|
+
validation: spec ? {
|
|
57
|
+
attemptsUsed: deliverable ? attemptsUsed(deliverable) : 0,
|
|
58
|
+
maxAttempts: spec.maxAttempts,
|
|
59
|
+
deadline: spec.deadline
|
|
60
|
+
} : null,
|
|
61
|
+
deliverableId: record.deliverable?.deliverableId ?? record.submission?.deliverableId ?? null,
|
|
62
|
+
submissionId: record.submission?.submissionId ?? null,
|
|
63
|
+
updatedAt: record.updatedAt,
|
|
64
|
+
source: "saved_state"
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async function readSyncStatus(cwd = process.cwd()) {
|
|
68
|
+
const view = {
|
|
69
|
+
project: null,
|
|
70
|
+
approved: false,
|
|
71
|
+
approvedAt: null,
|
|
72
|
+
sessionRunning: false,
|
|
73
|
+
lastUploadAt: null,
|
|
74
|
+
uploadedFiles: null,
|
|
75
|
+
lastPullAt: null,
|
|
76
|
+
pending: null,
|
|
77
|
+
captureFailed: null,
|
|
78
|
+
orphanSandboxId: null,
|
|
79
|
+
source: "saved_state"
|
|
80
|
+
};
|
|
81
|
+
let state;
|
|
82
|
+
try {
|
|
83
|
+
view.project = await fs.realpath(cwd);
|
|
84
|
+
state = await loadSyncState(view.project);
|
|
85
|
+
} catch {
|
|
86
|
+
return view;
|
|
87
|
+
}
|
|
88
|
+
view.approved = state.approval !== void 0;
|
|
89
|
+
view.approvedAt = state.approval?.approvedAt ?? null;
|
|
90
|
+
const session = state.session;
|
|
91
|
+
const claim = activeClaim(state);
|
|
92
|
+
view.sessionRunning = claim?.purpose === "session" || !!session && !session.endedAt && !killedSession(state);
|
|
93
|
+
if (session) {
|
|
94
|
+
view.lastUploadAt = session.lastUploadAt ?? null;
|
|
95
|
+
view.uploadedFiles = session.uploadedFiles ?? null;
|
|
96
|
+
view.lastPullAt = session.lastPullAt ?? null;
|
|
97
|
+
}
|
|
98
|
+
if (state.capture?.state === "saved") {
|
|
99
|
+
view.pending = { ...state.capture.pending, checkedAt: state.capture.capturedAt, saved: true };
|
|
100
|
+
} else if (session?.pending) {
|
|
101
|
+
view.pending = { ...session.pending, saved: false };
|
|
102
|
+
}
|
|
103
|
+
const problem = captureProblem(state);
|
|
104
|
+
view.orphanSandboxId = problem ? null : orphanOf(state)?.sandboxId ?? null;
|
|
105
|
+
if (problem) {
|
|
106
|
+
view.captureFailed = {
|
|
107
|
+
kind: problem.kind,
|
|
108
|
+
at: problem.at,
|
|
109
|
+
reason: problem.reason,
|
|
110
|
+
sandboxId: problem.sandboxId ?? null
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return view;
|
|
114
|
+
}
|
|
115
|
+
async function listSandboxes(credentials, fetchImpl = fetch) {
|
|
116
|
+
const response = await fetchImpl(`${apiUrl().replace(/\/+$/, "")}/api/sandboxes/list`, {
|
|
117
|
+
method: "POST",
|
|
118
|
+
redirect: "error",
|
|
119
|
+
headers: { "content-type": "application/json" },
|
|
120
|
+
body: JSON.stringify(credentials),
|
|
121
|
+
signal: AbortSignal.timeout(15e3)
|
|
122
|
+
});
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
await response.body?.cancel().catch(() => void 0);
|
|
125
|
+
throw new Error(`the sandbox broker answered ${response.status}`);
|
|
126
|
+
}
|
|
127
|
+
const parsed = SandboxListOutputSchema.safeParse(await response.json());
|
|
128
|
+
if (!parsed.success) throw new Error("the sandbox list is malformed");
|
|
129
|
+
return parsed.data.sandboxes.map((s) => ({
|
|
130
|
+
sandboxId: s.sandboxId,
|
|
131
|
+
purpose: s.purpose,
|
|
132
|
+
state: s.state,
|
|
133
|
+
meteredSeconds: s.meteredSeconds,
|
|
134
|
+
lastActiveAt: s.lastActiveAt,
|
|
135
|
+
expiresAt: s.expiresAt,
|
|
136
|
+
creditWarning: s.creditWarning,
|
|
137
|
+
creditGraceUntil: s.creditGraceUntil
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
function message(error) {
|
|
141
|
+
return error.code ?? error.message;
|
|
142
|
+
}
|
|
143
|
+
async function collectAgentStatus(deps = {}) {
|
|
144
|
+
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
145
|
+
const view = {
|
|
146
|
+
version: AGENT_VIEW_VERSION,
|
|
147
|
+
kind: "taskmarket.agent.status",
|
|
148
|
+
generatedAt: now().toISOString(),
|
|
149
|
+
wallet: null,
|
|
150
|
+
policy: { state: "missing", path: getAgentPolicyPath(), models: [] },
|
|
151
|
+
channels: [],
|
|
152
|
+
purchases: { uncertain: [] },
|
|
153
|
+
inference: { blocked: false, reasons: [] },
|
|
154
|
+
allocations: [],
|
|
155
|
+
sandbox: { state: "no_wallet", sandboxes: [] },
|
|
156
|
+
compute: {
|
|
157
|
+
configured: false,
|
|
158
|
+
availableCredits: null,
|
|
159
|
+
reservedCredits: null,
|
|
160
|
+
burnCreditsPerHour: null,
|
|
161
|
+
low: false,
|
|
162
|
+
warning: null,
|
|
163
|
+
pendingPurchases: 0,
|
|
164
|
+
autoTopUp: null
|
|
165
|
+
},
|
|
166
|
+
sync: {
|
|
167
|
+
project: null,
|
|
168
|
+
approved: false,
|
|
169
|
+
approvedAt: null,
|
|
170
|
+
sessionRunning: false,
|
|
171
|
+
lastUploadAt: null,
|
|
172
|
+
uploadedFiles: null,
|
|
173
|
+
lastPullAt: null,
|
|
174
|
+
pending: null,
|
|
175
|
+
captureFailed: null,
|
|
176
|
+
orphanSandboxId: null,
|
|
177
|
+
source: "saved_state"
|
|
178
|
+
},
|
|
179
|
+
task: null
|
|
180
|
+
};
|
|
181
|
+
const reasons = view.inference.reasons;
|
|
182
|
+
let credentials;
|
|
183
|
+
try {
|
|
184
|
+
const opened = await (deps.openChannels ?? openAgentChannels)();
|
|
185
|
+
view.wallet = { address: opened.keystore.walletAddress };
|
|
186
|
+
credentials = { deviceId: opened.keystore.deviceId, apiToken: opened.keystore.apiToken };
|
|
187
|
+
view.policy = { state: "approved", path: view.policy.path, models: [...opened.policy.models] };
|
|
188
|
+
const statuses = /* @__PURE__ */ new Map();
|
|
189
|
+
for (const rail of opened.rails) {
|
|
190
|
+
const status = await rail.payer.channelStatus();
|
|
191
|
+
statuses.set(rail.rail.id, status);
|
|
192
|
+
const channel = await channelView(rail, status);
|
|
193
|
+
view.channels.push({ ...channel, withdrawal: withdrawalHatch(channel) });
|
|
194
|
+
}
|
|
195
|
+
for (const rail of opened.retired ?? []) {
|
|
196
|
+
const channel = await channelView(rail, void 0, { retired: true });
|
|
197
|
+
view.channels.push({ ...channel, withdrawal: withdrawalHatch(channel) });
|
|
198
|
+
}
|
|
199
|
+
view.purchases.uncertain = [
|
|
200
|
+
...await uncertainPurchases(opened.rails, statuses),
|
|
201
|
+
...await uncertainPurchases(opened.retired ?? [])
|
|
202
|
+
];
|
|
203
|
+
view.allocations = await allocationViews(opened.rails, [
|
|
204
|
+
await (deps.computeAllocation ?? computeAllocationId)()
|
|
205
|
+
]);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
if (error instanceof AgentLaunchError && error.code === "wallet_required") {
|
|
208
|
+
reasons.push("no wallet: run taskmarket wallet import");
|
|
209
|
+
} else if (error instanceof AgentLaunchError && error.code === "setup_required") {
|
|
210
|
+
reasons.push("no approved spending policy");
|
|
211
|
+
} else {
|
|
212
|
+
view.policy = { ...view.policy, state: "invalid", error: message(error) };
|
|
213
|
+
reasons.push(`the spending policy cannot be used: ${message(error)}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const active = view.channels.filter((channel) => !channel.retired);
|
|
217
|
+
for (const id of blockingPurchases({ channels: active, unresolved: [] })) {
|
|
218
|
+
reasons.push(`purchase ${id} is unresolved: taskmarket agent reconcile ${id}`);
|
|
219
|
+
}
|
|
220
|
+
for (const channel of active) {
|
|
221
|
+
if (channel.state !== "open") reasons.push(`channel ${channel.rail} is ${channel.state}`);
|
|
222
|
+
}
|
|
223
|
+
if (credentials) {
|
|
224
|
+
try {
|
|
225
|
+
view.sandbox = {
|
|
226
|
+
state: "ok",
|
|
227
|
+
sandboxes: await (deps.listSandboxes ?? listSandboxes)(credentials)
|
|
228
|
+
};
|
|
229
|
+
} catch (error) {
|
|
230
|
+
view.sandbox = { state: "unavailable", sandboxes: [], error: message(error) };
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const warning = view.sandbox.sandboxes.find((s) => s.purpose === "interactive" && s.creditWarning)?.creditWarning ?? null;
|
|
234
|
+
view.compute = await (deps.readCompute ?? readComputeView)({ warning });
|
|
235
|
+
view.sync = await (deps.readSync ?? readSyncStatus)();
|
|
236
|
+
if (view.wallet) {
|
|
237
|
+
try {
|
|
238
|
+
view.task = await (deps.readTask ?? readTaskStatus)(view.wallet.address);
|
|
239
|
+
} catch (error) {
|
|
240
|
+
view.taskError = message(error);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
view.inference.blocked = reasons.length > 0;
|
|
244
|
+
return view;
|
|
245
|
+
}
|
|
246
|
+
function statusLines(view) {
|
|
247
|
+
const lines = [
|
|
248
|
+
`taskmarket agent status (view v${view.version}, ${view.generatedAt})`,
|
|
249
|
+
view.wallet ? `Wallet: ${view.wallet.address}` : "Wallet: none",
|
|
250
|
+
`Spending policy: ${view.policy.state}${view.policy.models.length ? ` (${view.policy.models.join(", ")})` : ""}${view.policy.error ? `: ${view.policy.error}` : ""}`
|
|
251
|
+
];
|
|
252
|
+
for (const channel of view.channels) {
|
|
253
|
+
lines.push(...channelLines(channel));
|
|
254
|
+
if (channel.state === "blocked" || channel.state === "withdrawal_pending") {
|
|
255
|
+
lines.push(` ${channel.withdrawal.note}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (view.purchases.uncertain.length === 0) {
|
|
259
|
+
lines.push("Purchases with an unknown outcome: none");
|
|
260
|
+
} else {
|
|
261
|
+
lines.push("Purchases with an unknown outcome (never resent; reconcile them):");
|
|
262
|
+
for (const purchase of view.purchases.uncertain) {
|
|
263
|
+
lines.push(
|
|
264
|
+
` ${purchase.invocationId} on ${purchase.rail}: ${purchase.state}, at most ${formatUsdc(purchase.authorizedAtomic)}${purchase.blocking ? ", blocks new turns" : ""}`
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
lines.push(
|
|
269
|
+
view.inference.blocked ? `New inference: blocked (${view.inference.reasons.join("; ")})` : "New inference: ready"
|
|
270
|
+
);
|
|
271
|
+
if (view.sandbox.state === "ok") {
|
|
272
|
+
lines.push(
|
|
273
|
+
view.sandbox.sandboxes.length === 0 ? "Sandbox: none" : `Sandbox: ${view.sandbox.sandboxes.map(
|
|
274
|
+
(s) => `${s.sandboxId} ${s.purpose} ${s.state}${s.creditWarning ? ` (${s.creditWarning})` : ""}`
|
|
275
|
+
).join("; ")}`
|
|
276
|
+
);
|
|
277
|
+
} else if (view.sandbox.state === "unavailable") {
|
|
278
|
+
lines.push(`Sandbox: unavailable (${view.sandbox.error})`);
|
|
279
|
+
}
|
|
280
|
+
lines.push(...computeLines(view.compute));
|
|
281
|
+
lines.push(...syncLines(view.sync));
|
|
282
|
+
lines.push(...taskLines(view.task, view.taskError));
|
|
283
|
+
return lines;
|
|
284
|
+
}
|
|
285
|
+
var STAGES = {
|
|
286
|
+
claiming: "claiming (a claim may have been sent; the next session confirms it before anything else)",
|
|
287
|
+
claimed: "claimed (the task workspace is not set up yet)",
|
|
288
|
+
working: "working (workspace ready, not validated yet)",
|
|
289
|
+
frozen: "frozen (validated, waiting for your approval to submit)",
|
|
290
|
+
submitting: "submitting (sent; the next session looks it up before anything is sent again)",
|
|
291
|
+
submitted: "submitted (not yet accepted or paid)",
|
|
292
|
+
stopped: "stopped"
|
|
293
|
+
};
|
|
294
|
+
function taskLines(task, error) {
|
|
295
|
+
if (error) return [`Marketplace task: the run state cannot be read (${error})`];
|
|
296
|
+
if (!task) return ["Marketplace task: none"];
|
|
297
|
+
const lines = [`Marketplace task ${task.taskId} on ${task.network}: ${STAGES[task.stage]}`];
|
|
298
|
+
if (task.claimId) lines.push(` Claim: ${task.claimId}`);
|
|
299
|
+
if (task.workspace) lines.push(` Workspace (in the sandbox): ${task.workspace}`);
|
|
300
|
+
if (task.validation) {
|
|
301
|
+
lines.push(
|
|
302
|
+
` Validation: ${task.validation.attemptsUsed} of ${task.validation.maxAttempts} attempt(s) used, until ${task.validation.deadline}`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
if (task.deliverableId) lines.push(` Deliverable: ${task.deliverableId}`);
|
|
306
|
+
if (task.submissionId) lines.push(` Submission: ${task.submissionId}`);
|
|
307
|
+
lines.push(` As recorded ${task.updatedAt}`);
|
|
308
|
+
return lines;
|
|
309
|
+
}
|
|
310
|
+
function syncLines(sync) {
|
|
311
|
+
if (!sync.project) return ["Workspace sync: this directory cannot be read"];
|
|
312
|
+
const lines = [
|
|
313
|
+
`Workspace sync (${sync.project}): ${sync.approved ? `upload approved ${sync.approvedAt}` : "upload not approved yet"}${sync.sessionRunning ? "; a session is running here" : ""}`
|
|
314
|
+
];
|
|
315
|
+
if (sync.lastUploadAt) {
|
|
316
|
+
lines.push(` Last upload: ${sync.lastUploadAt} (${sync.uploadedFiles ?? 0} file(s))`);
|
|
317
|
+
}
|
|
318
|
+
if (sync.lastPullAt) lines.push(` Last pull: ${sync.lastPullAt}`);
|
|
319
|
+
if (sync.pending) {
|
|
320
|
+
const { clean, conflict, blocked } = sync.pending;
|
|
321
|
+
const notSaved = sync.pending.notSaved ?? 0;
|
|
322
|
+
const tooDeep = sync.pending.tooDeep ?? 0;
|
|
323
|
+
const waiting = `${clean + conflict} change(s) to pull${conflict ? ` (${conflict} in conflict)` : ""}${notSaved ? `, ${notSaved} too large to have been saved` : ""}${tooDeep ? `, ${tooDeep} director(ies) nested too deep to have been saved (taskmarket agent pull --keep-local <dir> acknowledges one, --discard all)` : ""}${blocked ? `, ${blocked} blocked` : ""}`;
|
|
324
|
+
lines.push(
|
|
325
|
+
sync.pending.saved ? ` Saved from the last session: ${waiting}; review them with taskmarket agent pull` : ` In the sandbox: ${waiting}, as counted ${sync.pending.checkedAt} (not checked live, which would resume the sandbox)`
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
if (sync.orphanSandboxId) {
|
|
329
|
+
lines.push(
|
|
330
|
+
` A killed --no-sync session left sandbox ${sync.orphanSandboxId}: taskmarket agent pull --recover brings back what the agent made there, until it stops once idle.`
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
if (sync.captureFailed) {
|
|
334
|
+
const failed = sync.captureFailed;
|
|
335
|
+
const where = failed.sandboxId ? ` (sandbox ${failed.sandboxId})` : "";
|
|
336
|
+
lines.push(
|
|
337
|
+
failed.kind === "interrupted" ? ` The last session ended at ${failed.at} before its changes were saved${where}: recover them with taskmarket agent pull --recover, or drop them with taskmarket agent pull --discard. New sessions wait until then.` : ` The last session's changes could not be saved${where}: ${failed.reason}. Recover them with taskmarket agent pull --recover, or drop them with taskmarket agent pull --discard. New sessions wait until then.`
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
return lines;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export {
|
|
344
|
+
readTaskStatus,
|
|
345
|
+
readSyncStatus,
|
|
346
|
+
listSandboxes,
|
|
347
|
+
collectAgentStatus,
|
|
348
|
+
statusLines,
|
|
349
|
+
taskLines,
|
|
350
|
+
syncLines
|
|
351
|
+
};
|