travelmolt-sdk 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +132 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +132 -0
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -1917,6 +1917,14 @@ function formatUsdc(raw) {
|
|
|
1917
1917
|
const frac = raw % 1000000n;
|
|
1918
1918
|
return `${whole}.${frac.toString().padStart(6, "0")} USDC`;
|
|
1919
1919
|
}
|
|
1920
|
+
function formatDuration(secs) {
|
|
1921
|
+
const abs = Math.abs(secs);
|
|
1922
|
+
if (abs < 60) return `${abs}s`;
|
|
1923
|
+
if (abs < 3600) return `${Math.floor(abs / 60)}m`;
|
|
1924
|
+
const h = Math.floor(abs / 3600);
|
|
1925
|
+
const m = Math.floor(abs % 3600 / 60);
|
|
1926
|
+
return m > 0 ? `${h}h ${m}m` : `${h}h`;
|
|
1927
|
+
}
|
|
1920
1928
|
function printJob(id, job) {
|
|
1921
1929
|
const statusNames = ["Open", "Claimed", "Completed", "Cancelled"];
|
|
1922
1930
|
let payload = {};
|
|
@@ -2136,6 +2144,129 @@ Use --force to bypass this check.`);
|
|
|
2136
2144
|
console.log(` Expected reports: ${expected}`);
|
|
2137
2145
|
break;
|
|
2138
2146
|
}
|
|
2147
|
+
case "my-jobs": {
|
|
2148
|
+
const addrFlag = flag("address");
|
|
2149
|
+
let workerAddress;
|
|
2150
|
+
if (addrFlag) {
|
|
2151
|
+
workerAddress = addrFlag.toLowerCase();
|
|
2152
|
+
} else {
|
|
2153
|
+
const pk = flag("private-key") ?? process.env.PRIVATE_KEY;
|
|
2154
|
+
if (!pk) {
|
|
2155
|
+
console.error("Usage: travelmolt my-jobs --address 0x... (read-only)");
|
|
2156
|
+
console.error(" or: travelmolt my-jobs (uses PRIVATE_KEY / --private-key)");
|
|
2157
|
+
process.exit(1);
|
|
2158
|
+
}
|
|
2159
|
+
workerAddress = (0, import_accounts.privateKeyToAccount)(pk).address.toLowerCase();
|
|
2160
|
+
}
|
|
2161
|
+
const maxId = Number(flag("max") ?? "100");
|
|
2162
|
+
const publicClient = getPublicClient();
|
|
2163
|
+
const readAgent = new TravelMoltAgent({ publicClient, walletClient: null });
|
|
2164
|
+
const ZERO = "0x0000000000000000000000000000000000000000";
|
|
2165
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
2166
|
+
const myJobs = [];
|
|
2167
|
+
let needsAction = false;
|
|
2168
|
+
for (let id = 1; id <= maxId; id++) {
|
|
2169
|
+
try {
|
|
2170
|
+
const job = await readAgent.getMonitoringJob(BigInt(id));
|
|
2171
|
+
if (job.poster === ZERO) continue;
|
|
2172
|
+
if (job.status !== 1) continue;
|
|
2173
|
+
if (job.worker.toLowerCase() !== workerAddress) continue;
|
|
2174
|
+
let payload = {};
|
|
2175
|
+
try {
|
|
2176
|
+
payload = JSON.parse(job.moltbookPostId);
|
|
2177
|
+
} catch {
|
|
2178
|
+
}
|
|
2179
|
+
const lastReport = Number(job.lastReportAt);
|
|
2180
|
+
const interval = Number(job.checkIntervalSeconds);
|
|
2181
|
+
const referenceTime = lastReport > 0 ? lastReport : Number(job.claimedAt);
|
|
2182
|
+
const nextCheckAt = referenceTime + interval;
|
|
2183
|
+
const missedIntervals = Math.max(0, Math.floor((now - referenceTime) / interval));
|
|
2184
|
+
let status;
|
|
2185
|
+
let nextInSecs = nextCheckAt - now;
|
|
2186
|
+
if (missedIntervals >= 2) {
|
|
2187
|
+
status = "AT_RISK";
|
|
2188
|
+
needsAction = true;
|
|
2189
|
+
} else if (now > nextCheckAt + interval) {
|
|
2190
|
+
status = "OVERDUE";
|
|
2191
|
+
needsAction = true;
|
|
2192
|
+
} else if (now > nextCheckAt) {
|
|
2193
|
+
status = "DUE_NOW";
|
|
2194
|
+
needsAction = true;
|
|
2195
|
+
} else if (nextCheckAt - now <= 300) {
|
|
2196
|
+
status = "DUE_SOON";
|
|
2197
|
+
needsAction = true;
|
|
2198
|
+
} else {
|
|
2199
|
+
status = "SAFE";
|
|
2200
|
+
}
|
|
2201
|
+
myJobs.push({
|
|
2202
|
+
id,
|
|
2203
|
+
hotel: payload.hotel ?? "(unknown)",
|
|
2204
|
+
status,
|
|
2205
|
+
reportCount: Number(job.reportCount),
|
|
2206
|
+
nextInSecs,
|
|
2207
|
+
intervalSecs: interval,
|
|
2208
|
+
missedIntervals
|
|
2209
|
+
});
|
|
2210
|
+
} catch {
|
|
2211
|
+
break;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
if (myJobs.length === 0) {
|
|
2215
|
+
console.log(`No claimed jobs found for ${workerAddress.slice(0, 10)}...`);
|
|
2216
|
+
console.log(`
|
|
2217
|
+
Looking for work? Run: npx travelmolt-sdk@latest list-jobs`);
|
|
2218
|
+
break;
|
|
2219
|
+
}
|
|
2220
|
+
if (hasFlag("json")) {
|
|
2221
|
+
console.log(JSON.stringify({ worker: workerAddress, jobs: myJobs, needsAction, timestamp: now }));
|
|
2222
|
+
if (needsAction) process.exit(2);
|
|
2223
|
+
break;
|
|
2224
|
+
}
|
|
2225
|
+
console.log(`Jobs for ${workerAddress.slice(0, 10)}...
|
|
2226
|
+
`);
|
|
2227
|
+
for (const job of myJobs) {
|
|
2228
|
+
let statusTag;
|
|
2229
|
+
let detail;
|
|
2230
|
+
switch (job.status) {
|
|
2231
|
+
case "AT_RISK":
|
|
2232
|
+
statusTag = "!! AT RISK";
|
|
2233
|
+
detail = `${job.missedIntervals} intervals missed \u2014 submit NOW or you will be reclaimed!`;
|
|
2234
|
+
break;
|
|
2235
|
+
case "OVERDUE":
|
|
2236
|
+
statusTag = "! OVERDUE";
|
|
2237
|
+
detail = `overdue by ${formatDuration(Math.abs(job.nextInSecs))} \u2014 submit report now`;
|
|
2238
|
+
break;
|
|
2239
|
+
case "DUE_NOW":
|
|
2240
|
+
statusTag = "! DUE NOW";
|
|
2241
|
+
detail = `report due \u2014 submit now`;
|
|
2242
|
+
break;
|
|
2243
|
+
case "DUE_SOON":
|
|
2244
|
+
statusTag = "~ DUE SOON";
|
|
2245
|
+
detail = `due in ${formatDuration(job.nextInSecs)}`;
|
|
2246
|
+
break;
|
|
2247
|
+
case "SAFE":
|
|
2248
|
+
statusTag = " OK";
|
|
2249
|
+
detail = `next in ${formatDuration(job.nextInSecs)}`;
|
|
2250
|
+
break;
|
|
2251
|
+
}
|
|
2252
|
+
console.log(` [${statusTag}] Job #${job.id}: ${job.hotel}`);
|
|
2253
|
+
console.log(` ${detail} | ${job.reportCount} reports | interval ${formatDuration(job.intervalSecs)}`);
|
|
2254
|
+
if (job.status !== "SAFE") {
|
|
2255
|
+
console.log(` -> npx travelmolt-sdk@latest check-price ${job.id}`);
|
|
2256
|
+
}
|
|
2257
|
+
console.log();
|
|
2258
|
+
}
|
|
2259
|
+
console.log(`${myJobs.length} job(s) total.`);
|
|
2260
|
+
if (needsAction) {
|
|
2261
|
+
console.log(`
|
|
2262
|
+
ACTION REQUIRED: ${myJobs.filter((j) => j.status !== "SAFE").length} job(s) need attention.`);
|
|
2263
|
+
process.exit(2);
|
|
2264
|
+
} else {
|
|
2265
|
+
console.log(`
|
|
2266
|
+
All jobs on schedule.`);
|
|
2267
|
+
}
|
|
2268
|
+
break;
|
|
2269
|
+
}
|
|
2139
2270
|
case "check-price": {
|
|
2140
2271
|
const id = args[1];
|
|
2141
2272
|
if (!id) {
|
|
@@ -2367,6 +2498,7 @@ Commands:
|
|
|
2367
2498
|
claim <id> Claim a monitoring job (needs PRIVATE_KEY)
|
|
2368
2499
|
unclaim <id> Unclaim a monitoring job (needs PRIVATE_KEY)
|
|
2369
2500
|
report <id> --price <cents> [--alert] [--force] Submit a monitoring report
|
|
2501
|
+
my-jobs [--address 0x...] Show your claimed jobs and what's due (exit code 2 if action needed)
|
|
2370
2502
|
check-price <id> Check hotel price via SerpAPI (needs SERPAPI_API_KEY)
|
|
2371
2503
|
monitor <id> Long-running price check + report loop
|
|
2372
2504
|
register --name "Name" Register agent identity with display name
|