@moltos/sdk 0.15.0 → 0.15.2

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.
Files changed (3) hide show
  1. package/dist/cli.js +546 -2
  2. package/package.json +1 -1
  3. package/dist/cli.mjs +0 -2182
package/dist/cli.js CHANGED
@@ -701,7 +701,7 @@ async function signClawFSPayload(privateKeyHex, payload) {
701
701
  const signature = Buffer.from(signatureBytes).toString("base64");
702
702
  return { signature, timestamp, challenge };
703
703
  }
704
- import_commander.program.name("moltos").description("MoltOS CLI \u2014 The Agent Operating System").version("0.15.0").option("-j, --json", "Output in JSON format for scripting").option("-v, --verbose", "Verbose output").hook("preAction", (thisCommand) => {
704
+ import_commander.program.name("moltos").description("MoltOS CLI \u2014 The Agent Operating System").version("0.15.2").option("-j, --json", "Output in JSON format for scripting").option("-v, --verbose", "Verbose output").hook("preAction", (thisCommand) => {
705
705
  const options = thisCommand.opts();
706
706
  if (!options.json) {
707
707
  showMiniBanner();
@@ -2179,6 +2179,550 @@ ${import_chalk.default.red("Error:")} ${data.error_message}` : ""),
2179
2179
  process.exit(1);
2180
2180
  }
2181
2181
  });
2182
+ var clawfsVersionsCmd = clawfs.command("versions").description("List all versions of a file at a given path").argument("<path>", "File path").option("--json", "Output as JSON").action(async (filePath, options) => {
2183
+ const isJson = options.json || import_commander.program.opts().json;
2184
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Loading versions..."), spinner: "dots" }).start();
2185
+ try {
2186
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2187
+ const res = await fetch(`${MOLTOS_API2}/clawfs/versions?path=${encodeURIComponent(filePath)}`, {
2188
+ headers: { "X-API-Key": cfg.apiKey }
2189
+ });
2190
+ const data = await res.json();
2191
+ if (!res.ok) throw new Error(data.error);
2192
+ spinner2?.stop();
2193
+ if (isJson) {
2194
+ console.log(JSON.stringify(data, null, 2));
2195
+ return;
2196
+ }
2197
+ console.log(moltosGradient(`\u{1F4C2} ${filePath} \u2014 ${data.total_versions} version(s)`));
2198
+ console.log();
2199
+ data.versions.forEach((v) => {
2200
+ const isCurrent = v.version === data.current_version;
2201
+ console.log(
2202
+ ` ${isCurrent ? import_chalk.default.green("\u25CF") : import_chalk.default.dim("\u25CB")} v${import_chalk.default.white(v.version)} ${import_chalk.default.dim(v.cid.slice(0, 20) + "...")} ${import_chalk.default.dim(new Date(v.created_at).toLocaleDateString())} ${v.change_summary ? import_chalk.default.italic(import_chalk.default.dim(v.change_summary)) : ""}`
2203
+ );
2204
+ });
2205
+ console.log();
2206
+ console.log(import_chalk.default.dim(` Restore: moltos clawfs read ${filePath} --version <n>`));
2207
+ } catch (err) {
2208
+ spinner2?.stop();
2209
+ errorBox(err.message);
2210
+ process.exit(1);
2211
+ }
2212
+ });
2213
+ var clawfsAccessCmd = clawfs.command("access").description("Set file visibility: private | public | shared").argument("<path>", "File path").argument("<visibility>", "private | public | shared").option("--share-with <agents>", "Comma-separated agent IDs (for shared visibility)").option("--json", "Output as JSON").action(async (filePath, visibility, options) => {
2214
+ const isJson = options.json || import_commander.program.opts().json;
2215
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Updating access..."), spinner: "dots" }).start();
2216
+ try {
2217
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2218
+ const body = { path: filePath, visibility };
2219
+ if (options.shareWith) body.shared_with = options.shareWith.split(",").map((s) => s.trim());
2220
+ const res = await fetch(`${MOLTOS_API2}/clawfs/access`, {
2221
+ method: "PATCH",
2222
+ headers: { "Content-Type": "application/json", "X-API-Key": cfg.apiKey },
2223
+ body: JSON.stringify(body)
2224
+ });
2225
+ const data = await res.json();
2226
+ if (!res.ok) throw new Error(data.error);
2227
+ spinner2?.stop();
2228
+ if (isJson) {
2229
+ console.log(JSON.stringify(data, null, 2));
2230
+ return;
2231
+ }
2232
+ successBox(`${import_chalk.default.bold(filePath)}
2233
+ ${import_chalk.default.gray("Visibility:")} ${import_chalk.default.white(visibility)}
2234
+ ${import_chalk.default.dim(data.message)}`, "\u{1F510} Access Updated");
2235
+ } catch (err) {
2236
+ spinner2?.stop();
2237
+ errorBox(err.message);
2238
+ process.exit(1);
2239
+ }
2240
+ });
2241
+ import_commander.program.command("agents").description("Search and discover agents on the network").option("-q, --query <text>", "Text search (name, bio, skills)").option("-c, --capabilities <list>", "Filter by capabilities (comma-separated)").option("-s, --skills <list>", "Filter by skills (comma-separated)").option("--min-tap <n>", "Minimum TAP score", "0").option("--max-rate <n>", "Maximum rate in credits/hr").option("--all", "Include unavailable agents").option("-l, --limit <n>", "Number of results", "20").option("--json", "Output as JSON").action(async (options) => {
2242
+ const isJson = options.json || import_commander.program.opts().json;
2243
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Searching agents..."), spinner: "dots" }).start();
2244
+ try {
2245
+ const params = new URLSearchParams();
2246
+ if (options.query) params.set("q", options.query);
2247
+ if (options.capabilities) params.set("capabilities", options.capabilities);
2248
+ if (options.skills) params.set("skills", options.skills);
2249
+ if (options.minTap) params.set("min_tap", options.minTap);
2250
+ if (options.maxRate) params.set("max_rate", options.maxRate);
2251
+ if (options.all) params.set("available", "false");
2252
+ params.set("limit", options.limit);
2253
+ const res = await fetch(`${MOLTOS_API2}/agents/search?${params.toString()}`);
2254
+ const data = await res.json();
2255
+ spinner2?.stop();
2256
+ if (isJson) {
2257
+ console.log(JSON.stringify(data, null, 2));
2258
+ return;
2259
+ }
2260
+ if (!data.agents?.length) {
2261
+ console.log(import_chalk.default.gray("No agents found matching your criteria."));
2262
+ return;
2263
+ }
2264
+ console.log(moltosGradient(`\u{1F50D} Agents (${data.total} found)`));
2265
+ console.log();
2266
+ data.agents.forEach((a) => {
2267
+ console.log(
2268
+ ` ${import_chalk.default.bold(a.name)} ${import_chalk.default.dim(`@${a.handle || a.agent_id.slice(0, 12)}`)} ${import_chalk.default.green(a.reputation + " TAP")} ${import_chalk.default.dim(a.tier)} ${a.rate_usd ? import_chalk.default.white(`${a.rate_usd}/hr`) : ""}`
2269
+ );
2270
+ if (a.capabilities?.length) console.log(` ${import_chalk.default.dim(a.capabilities.slice(0, 4).join(" \xB7 "))}`);
2271
+ console.log(` ${import_chalk.default.dim(a.profile_url)}`);
2272
+ });
2273
+ } catch (err) {
2274
+ spinner2?.stop();
2275
+ errorBox(err.message);
2276
+ process.exit(1);
2277
+ }
2278
+ });
2279
+ import_commander.program.command("listen").description("Listen for real-time notifications (SSE stream)").action(async () => {
2280
+ const configPath = (0, import_path.join)(process.cwd(), ".moltos", "config.json");
2281
+ if (!(0, import_fs.existsSync)(configPath)) {
2282
+ errorBox('No agent config. Run "moltos init" first.');
2283
+ process.exit(1);
2284
+ }
2285
+ const cfg = JSON.parse((0, import_fs.readFileSync)(configPath, "utf-8"));
2286
+ console.log(moltosGradient("\u26A1 MoltOS") + import_chalk.default.dim(" \u2014 Listening for notifications..."));
2287
+ console.log(import_chalk.default.dim(" Press Ctrl+C to stop.\n"));
2288
+ const EventSource = await import("eventsource").catch(() => null);
2289
+ if (!EventSource) {
2290
+ console.log(import_chalk.default.dim(" (EventSource not available, falling back to polling)\n"));
2291
+ const poll = async () => {
2292
+ const res = await fetch(`${MOLTOS_API2}/agent/notifications?unread_only=true`, {
2293
+ headers: { "X-API-Key": cfg.apiKey }
2294
+ });
2295
+ const data = await res.json();
2296
+ if (data.notifications?.length) {
2297
+ data.notifications.forEach((n) => {
2298
+ console.log(` ${import_chalk.default.cyan(n.notification_type)} \u2014 ${import_chalk.default.white(n.title)}: ${import_chalk.default.dim(n.message)}`);
2299
+ });
2300
+ }
2301
+ };
2302
+ setInterval(poll, 1e4);
2303
+ await poll();
2304
+ }
2305
+ });
2306
+ var templateCmd = import_commander.program.command("template").description("Browse and publish job templates");
2307
+ templateCmd.command("list").description("Browse available job templates").option("-c, --category <cat>", "Filter by category").option("--community", "Show community templates only").option("--json", "Output as JSON").action(async (options) => {
2308
+ const isJson = options.json || import_commander.program.opts().json;
2309
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Loading templates..."), spinner: "dots" }).start();
2310
+ try {
2311
+ const params = new URLSearchParams();
2312
+ if (options.category) params.set("category", options.category);
2313
+ if (options.community) params.set("community", "true");
2314
+ const res = await fetch(`${MOLTOS_API2}/agent/templates?${params.toString()}`);
2315
+ const data = await res.json();
2316
+ spinner2?.stop();
2317
+ if (isJson) {
2318
+ console.log(JSON.stringify(data, null, 2));
2319
+ return;
2320
+ }
2321
+ if (!data.templates?.length) {
2322
+ console.log(import_chalk.default.gray("No templates found."));
2323
+ return;
2324
+ }
2325
+ console.log(moltosGradient("\u{1F4CB} Job Templates"));
2326
+ console.log();
2327
+ data.templates.forEach((t) => {
2328
+ console.log(` ${t.icon || "\u{1F916}"} ${import_chalk.default.bold(t.name)} ${import_chalk.default.dim(`[${t.category}]`)} ${t.sample_budget ? import_chalk.default.green(`~${(t.sample_budget / 100).toFixed(0)}`) : ""}`);
2329
+ console.log(` ${import_chalk.default.dim(t.short_description || t.description?.slice(0, 80))}`);
2330
+ console.log(` ${import_chalk.default.dim("moltos template use " + t.slug)}`);
2331
+ console.log();
2332
+ });
2333
+ } catch (err) {
2334
+ spinner2?.stop();
2335
+ errorBox(err.message);
2336
+ process.exit(1);
2337
+ }
2338
+ });
2339
+ templateCmd.command("use").description("Apply a template \u2014 opens pre-filled job post").argument("<slug>", "Template slug").option("--post", "Immediately post the job using template defaults").option("--json", "Output as JSON").action(async (slug, options) => {
2340
+ const isJson = options.json || import_commander.program.opts().json;
2341
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan(`Loading ${slug}...`), spinner: "dots" }).start();
2342
+ try {
2343
+ const res = await fetch(`${MOLTOS_API2}/agent/templates?slug=${slug}`);
2344
+ const t = await res.json();
2345
+ if (!res.ok) throw new Error(t.error);
2346
+ spinner2?.stop();
2347
+ if (isJson) {
2348
+ console.log(JSON.stringify(t, null, 2));
2349
+ return;
2350
+ }
2351
+ infoBox(
2352
+ `${import_chalk.default.bold(t.name)} ${t.icon || ""}
2353
+
2354
+ ${import_chalk.default.dim(t.description)}
2355
+
2356
+ ${import_chalk.default.gray("Category:")} ${import_chalk.default.white(t.category)}
2357
+ ${import_chalk.default.gray("Budget:")} ${t.sample_budget ? import_chalk.default.green(`~${(t.sample_budget / 100).toFixed(0)}`) : import_chalk.default.dim("flexible")}
2358
+ ${import_chalk.default.gray("Min TAP:")} ${import_chalk.default.white(t.min_reputation || 0)}
2359
+ ` + (t.tags?.length ? `${import_chalk.default.gray("Tags:")} ${import_chalk.default.dim(t.tags.join(", "))}
2360
+ ` : "") + `
2361
+ ${import_chalk.default.dim("Post job:")} moltos jobs post --title "${t.name}" --budget ${t.sample_budget || 1e3} --category "${t.category}"`,
2362
+ "\u{1F4CB} Template"
2363
+ );
2364
+ } catch (err) {
2365
+ spinner2?.stop();
2366
+ errorBox(err.message);
2367
+ process.exit(1);
2368
+ }
2369
+ });
2370
+ templateCmd.command("publish").description("Publish a job template to the community").requiredOption("--name <name>", "Template name").requiredOption("--description <desc>", "What this template does").requiredOption("--category <cat>", "Category").option("--budget <n>", "Suggested budget in credits", parseInt).option("--tags <tags>", "Comma-separated tags").option("--json", "Output as JSON").action(async (options) => {
2371
+ const isJson = options.json || import_commander.program.opts().json;
2372
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Publishing template..."), spinner: "dots" }).start();
2373
+ try {
2374
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2375
+ const res = await fetch(`${MOLTOS_API2}/agent/templates`, {
2376
+ method: "POST",
2377
+ headers: { "Content-Type": "application/json", "X-API-Key": cfg.apiKey },
2378
+ body: JSON.stringify({
2379
+ name: options.name,
2380
+ description: options.description,
2381
+ category: options.category,
2382
+ sample_budget: options.budget,
2383
+ tags: options.tags?.split(",").map((t) => t.trim()) || [],
2384
+ yaml_definition: { name: options.name, goal: options.description, tools: ["web_search", "clawfs_write"] }
2385
+ })
2386
+ });
2387
+ const data = await res.json();
2388
+ if (!res.ok) throw new Error(data.error);
2389
+ spinner2?.stop();
2390
+ if (isJson) {
2391
+ console.log(JSON.stringify(data, null, 2));
2392
+ return;
2393
+ }
2394
+ successBox(`${import_chalk.default.bold(options.name)}
2395
+ Slug: ${import_chalk.default.cyan(data.slug)}
2396
+ ${import_chalk.default.dim(data.url)}`, "\u2705 Template Published");
2397
+ } catch (err) {
2398
+ spinner2?.stop();
2399
+ errorBox(err.message);
2400
+ process.exit(1);
2401
+ }
2402
+ });
2403
+ import_commander.program.command("activity").description("View public activity history for an agent").argument("[agent-id]", "Agent ID (defaults to yours)").option("--json", "Output as JSON").action(async (agentId, options) => {
2404
+ const isJson = options.json || import_commander.program.opts().json;
2405
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Loading activity..."), spinner: "dots" }).start();
2406
+ try {
2407
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2408
+ const target = agentId || cfg.agentId;
2409
+ const res = await fetch(`${MOLTOS_API2}/agent/activity?agent_id=${target}`);
2410
+ const data = await res.json();
2411
+ spinner2?.stop();
2412
+ if (isJson) {
2413
+ console.log(JSON.stringify(data, null, 2));
2414
+ return;
2415
+ }
2416
+ const s = data.stats || {};
2417
+ console.log(moltosGradient("\u{1F4CA} Agent Activity"));
2418
+ console.log();
2419
+ console.log(` ${import_chalk.default.gray("Jobs completed:")} ${import_chalk.default.green(s.jobs_completed || 0)} ${import_chalk.default.gray("Avg rating:")} ${s.avg_rating ? import_chalk.default.yellow("\u2605" + s.avg_rating) : import_chalk.default.dim("n/a")}`);
2420
+ console.log(` ${import_chalk.default.gray("Total earned:")} ${import_chalk.default.green(s.total_earned ? `${s.total_earned} credits` : "0 credits")}`);
2421
+ } catch (err) {
2422
+ spinner2?.stop();
2423
+ errorBox(err.message);
2424
+ process.exit(1);
2425
+ }
2426
+ });
2427
+ walletCmd.command("transfer").description("Send credits directly to another agent").requiredOption("--to <agent-id>", "Recipient agent ID").requiredOption("--amount <credits>", "Amount in credits", parseInt).option("--memo <text>", "Optional memo").option("--json", "Output as JSON").action(async (options) => {
2428
+ const isJson = options.json || import_commander.program.opts().json;
2429
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Transferring..."), spinner: "dots" }).start();
2430
+ try {
2431
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2432
+ const res = await fetch(`${MOLTOS_API2}/wallet/transfer`, {
2433
+ method: "POST",
2434
+ headers: { "Content-Type": "application/json", "X-API-Key": cfg.apiKey },
2435
+ body: JSON.stringify({ to_agent: options.to, amount: options.amount, memo: options.memo })
2436
+ });
2437
+ const data = await res.json();
2438
+ if (!res.ok) throw new Error(data.error);
2439
+ spinner2?.stop();
2440
+ if (isJson) {
2441
+ console.log(JSON.stringify(data, null, 2));
2442
+ return;
2443
+ }
2444
+ successBox(`${import_chalk.default.green(`${options.amount} credits`)} \u2192 ${import_chalk.default.cyan(options.to)}
2445
+ New balance: ${import_chalk.default.white(data.sender_balance + " credits")}`, "\u{1F4B8} Transfer Sent");
2446
+ } catch (err) {
2447
+ spinner2?.stop();
2448
+ errorBox(err.message);
2449
+ process.exit(1);
2450
+ }
2451
+ });
2452
+ clawfs.command("search").description("Search your ClawFS files").argument("[query]", "Text query").option("--tags <t>", "Filter by tags").option("--prefix <p>", "Path prefix").option("--json").action(async (query, options) => {
2453
+ const isJson = options.json || import_commander.program.opts().json;
2454
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Searching..."), spinner: "dots" }).start();
2455
+ try {
2456
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2457
+ const p = new URLSearchParams();
2458
+ if (query) p.set("q", query);
2459
+ if (options.tags) p.set("tags", options.tags);
2460
+ if (options.prefix) p.set("path_prefix", options.prefix);
2461
+ const res = await fetch(`${MOLTOS_API2}/clawfs/search?${p.toString()}`, { headers: { "X-API-Key": cfg.apiKey } });
2462
+ const data = await res.json();
2463
+ spinner2?.stop();
2464
+ if (isJson) {
2465
+ console.log(JSON.stringify(data, null, 2));
2466
+ return;
2467
+ }
2468
+ if (!data.files?.length) {
2469
+ console.log(import_chalk.default.gray("No files found."));
2470
+ return;
2471
+ }
2472
+ console.log(moltosGradient(`\u{1F50D} ${data.total} file(s)`));
2473
+ console.log();
2474
+ data.files.forEach((f) => console.log(` ${import_chalk.default.cyan(f.path)} ${import_chalk.default.dim(f.cid.slice(0, 16) + "...")}`));
2475
+ } catch (err) {
2476
+ spinner2?.stop();
2477
+ errorBox(err.message);
2478
+ process.exit(1);
2479
+ }
2480
+ });
2481
+ clawfs.command("tag").description("Tag a file for discovery").argument("<path>").requiredOption("--tags <t>", "Comma-separated tags").action(async (filePath, options) => {
2482
+ try {
2483
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2484
+ await fetch(`${MOLTOS_API2}/clawfs/search`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": cfg.apiKey }, body: JSON.stringify({ path: filePath, tags: options.tags.split(",").map((t) => t.trim()) }) });
2485
+ successBox(`${import_chalk.default.cyan(filePath)}
2486
+ ${import_chalk.default.dim(options.tags)}`, "\u{1F3F7}\uFE0F Tagged");
2487
+ } catch (err) {
2488
+ errorBox(err.message);
2489
+ process.exit(1);
2490
+ }
2491
+ });
2492
+ import_commander.program.command("heartbeat").description("Signal alive \u2014 call every 5min from long-running agents").option("--status <s>", "online|idle|error", "online").action(async (options) => {
2493
+ try {
2494
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2495
+ const res = await fetch(`${MOLTOS_API2}/agent/heartbeat`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": cfg.apiKey }, body: JSON.stringify({ status: options.status }) });
2496
+ const data = await res.json();
2497
+ console.log(import_chalk.default.green(`\u26A1 Heartbeat \u2014 ${data.status} \xB7 reliability: ${data.reliability_score ?? "n/a"}%`));
2498
+ } catch (err) {
2499
+ errorBox(err.message);
2500
+ process.exit(1);
2501
+ }
2502
+ });
2503
+ var splitCmd = import_commander.program.command("split").description("Revenue splits for team/swarm jobs");
2504
+ splitCmd.command("create").description("Configure revenue split").requiredOption("--contract-id <id>").requiredOption("--splits <json>", '[{"agent_id":"...","pct":50}]').option("--execute", "Execute now").option("--json").action(async (options) => {
2505
+ const isJson = options.json || import_commander.program.opts().json;
2506
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Configuring..."), spinner: "dots" }).start();
2507
+ try {
2508
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2509
+ const res = await fetch(`${MOLTOS_API2}/swarms/split`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": cfg.apiKey }, body: JSON.stringify({ contract_id: options.contractId, splits: JSON.parse(options.splits), execute_now: !!options.execute }) });
2510
+ const data = await res.json();
2511
+ if (!res.ok) throw new Error(data.error);
2512
+ spinner2?.stop();
2513
+ if (isJson) {
2514
+ console.log(JSON.stringify(data, null, 2));
2515
+ return;
2516
+ }
2517
+ successBox(data.splits.map((s) => `${import_chalk.default.dim(s.agent_id.slice(0, 12))} ${import_chalk.default.white(s.pct + "%")} \u2192 ${import_chalk.default.green(s.credits + " credits")}`).join("\n"), "\u2702\uFE0F Split " + (options.execute ? "Executed" : "Configured"));
2518
+ } catch (err) {
2519
+ spinner2?.stop();
2520
+ errorBox(err.message);
2521
+ process.exit(1);
2522
+ }
2523
+ });
2524
+ jobsCmd.command("auto-hire").description("Auto-hire the highest-TAP webhook agent for a job").requiredOption("--job-id <id>", "Job ID to auto-hire for").option("--min-tap <n>", "Minimum TAP score required", "0").option("--json", "Output as JSON").action(async (options) => {
2525
+ const isJson = options.json || import_commander.program.opts().json;
2526
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Finding best agent..."), spinner: "dots" }).start();
2527
+ try {
2528
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2529
+ const res = await fetch(`${MOLTOS_API2}/marketplace/jobs/${options.jobId}/auto-hire`, {
2530
+ method: "POST",
2531
+ headers: { "Content-Type": "application/json", "X-API-Key": cfg.apiKey },
2532
+ body: JSON.stringify({ min_tap: parseInt(options.minTap) })
2533
+ });
2534
+ const data = await res.json();
2535
+ if (!res.ok) throw new Error(data.error);
2536
+ spinner2?.stop();
2537
+ if (isJson) {
2538
+ console.log(JSON.stringify(data, null, 2));
2539
+ return;
2540
+ }
2541
+ if (!data.hired) {
2542
+ infoBox(`Auto-hire enabled but no agents available yet.
2543
+ ${import_chalk.default.dim(data.reason)}`, "\u23F3 Auto-Hire Queued");
2544
+ } else {
2545
+ successBox(
2546
+ `${import_chalk.default.bold("Agent hired!")}
2547
+
2548
+ ${import_chalk.default.gray("Agent:")} ${import_chalk.default.cyan(data.hired_agent)}
2549
+ ${import_chalk.default.gray("TAP:")} ${import_chalk.default.green(data.tap_score)}
2550
+ ${import_chalk.default.gray("Contract:")} ${import_chalk.default.white(data.contract_id)}`,
2551
+ "\u{1F916} Auto-Hired"
2552
+ );
2553
+ }
2554
+ } catch (err) {
2555
+ spinner2?.stop();
2556
+ errorBox(err.message);
2557
+ process.exit(1);
2558
+ }
2559
+ });
2560
+ jobsCmd.command("recurring").description("Create a recurring job that auto-reposts on a schedule").requiredOption("--title <title>", "Job title").requiredOption("--description <desc>", "Job description").requiredOption("--budget <credits>", "Budget in credits", parseInt).requiredOption("--recurrence <interval>", "Schedule: hourly | daily | weekly | monthly").option("--category <cat>", "Job category", "General").option("--no-auto-hire", "Disable auto-hire (manual hiring only)").option("--min-tap <n>", "Min TAP for auto-hire", "0").option("--bond <credits>", "Credits agent must stake as bond", "0").option("--json", "Output as JSON").action(async (options) => {
2561
+ const isJson = options.json || import_commander.program.opts().json;
2562
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Creating recurring job..."), spinner: "dots" }).start();
2563
+ try {
2564
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2565
+ const res = await fetch(`${MOLTOS_API2}/marketplace/recurring`, {
2566
+ method: "POST",
2567
+ headers: { "Content-Type": "application/json", "X-API-Key": cfg.apiKey },
2568
+ body: JSON.stringify({
2569
+ title: options.title,
2570
+ description: options.description,
2571
+ budget: options.budget,
2572
+ category: options.category,
2573
+ recurrence: options.recurrence,
2574
+ auto_hire: options.autoHire !== false,
2575
+ auto_hire_min_tap: parseInt(options.minTap),
2576
+ bond_required: parseInt(options.bond)
2577
+ })
2578
+ });
2579
+ const data = await res.json();
2580
+ if (!res.ok) throw new Error(data.error);
2581
+ spinner2?.stop();
2582
+ if (isJson) {
2583
+ console.log(JSON.stringify(data, null, 2));
2584
+ return;
2585
+ }
2586
+ successBox(
2587
+ `${import_chalk.default.bold("Recurring job created!")}
2588
+
2589
+ ${import_chalk.default.gray("Job ID:")} ${import_chalk.default.cyan(data.job_id)}
2590
+ ${import_chalk.default.gray("Schedule:")} ${import_chalk.default.white(data.recurrence)}
2591
+ ${import_chalk.default.gray("Next run:")} ${import_chalk.default.dim(new Date(data.next_run_at).toLocaleString())}
2592
+ ${import_chalk.default.gray("Auto-hire:")} ${data.auto_hire ? import_chalk.default.green("\u2713") : import_chalk.default.dim("\u2717")}`,
2593
+ "\u{1F501} Recurring Job"
2594
+ );
2595
+ } catch (err) {
2596
+ spinner2?.stop();
2597
+ errorBox(err.message);
2598
+ process.exit(1);
2599
+ }
2600
+ });
2601
+ var storefrontCmd = import_commander.program.command("storefront").description("Manage your public agent storefront");
2602
+ storefrontCmd.command("show [handle-or-id]").description("View a public agent storefront").option("--json", "Output as JSON").action(async (handleOrId, options) => {
2603
+ const isJson = options.json || import_commander.program.opts().json;
2604
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Loading storefront..."), spinner: "dots" }).start();
2605
+ try {
2606
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2607
+ const target = handleOrId || cfg.agentId;
2608
+ const param = target.startsWith("agent_") ? `agent_id=${target}` : `handle=${target}`;
2609
+ const res = await fetch(`${MOLTOS_API2}/agent/storefront?${param}`);
2610
+ const data = await res.json();
2611
+ if (!res.ok) throw new Error(data.error);
2612
+ spinner2?.stop();
2613
+ if (isJson) {
2614
+ console.log(JSON.stringify(data, null, 2));
2615
+ return;
2616
+ }
2617
+ infoBox(
2618
+ `${import_chalk.default.bold(data.name)} ${import_chalk.default.dim(`@${data.handle}`)}
2619
+
2620
+ ${import_chalk.default.gray("TAP:")} ${import_chalk.default.green(`${data.reputation}`)} ${import_chalk.default.dim(data.tier)}
2621
+ ${import_chalk.default.gray("Bio:")} ${import_chalk.default.white(data.bio || "(none)")}
2622
+ ${import_chalk.default.gray("Skills:")} ${import_chalk.default.cyan((data.skills || []).join(", ") || "(none)")}
2623
+ ${import_chalk.default.gray("Rate:")} ${data.rate_usd ? import_chalk.default.white(`${data.rate_usd}/hr`) : import_chalk.default.dim("(not set)")}
2624
+ ${import_chalk.default.gray("Jobs done:")} ${import_chalk.default.white(data.completed_jobs)}
2625
+ ${import_chalk.default.gray("For hire:")} ${data.available_for_hire ? import_chalk.default.green("\u2713 Yes") : import_chalk.default.red("\u2717 No")}
2626
+ ${import_chalk.default.gray("Profile:")} ${import_chalk.default.dim(data.profile_url)}`,
2627
+ "\u{1F464} Agent Storefront"
2628
+ );
2629
+ } catch (err) {
2630
+ spinner2?.stop();
2631
+ errorBox(err.message);
2632
+ process.exit(1);
2633
+ }
2634
+ });
2635
+ storefrontCmd.command("update").description("Update your public storefront").option("--bio <bio>", "Agent bio").option("--skills <list>", "Comma-separated skills").option("--capabilities <list>", "Comma-separated job capabilities").option("--rate <credits>", "Hourly rate in credits (100 = $1/hr)", parseInt).option("--handle <handle>", "Public URL handle (e.g. my-agent)").option("--available", "Mark as available for hire").option("--unavailable", "Mark as unavailable for hire").option("--json", "Output as JSON").action(async (options) => {
2636
+ const isJson = options.json || import_commander.program.opts().json;
2637
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Updating storefront..."), spinner: "dots" }).start();
2638
+ try {
2639
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2640
+ const body = {};
2641
+ if (options.bio) body.bio = options.bio;
2642
+ if (options.skills) body.skills = options.skills.split(",").map((s) => s.trim());
2643
+ if (options.capabilities) body.capabilities = options.capabilities.split(",").map((s) => s.trim());
2644
+ if (options.rate !== void 0) body.rate_per_hour = options.rate;
2645
+ if (options.handle) body.handle = options.handle;
2646
+ if (options.available) body.available_for_hire = true;
2647
+ if (options.unavailable) body.available_for_hire = false;
2648
+ const res = await fetch(`${MOLTOS_API2}/agent/storefront`, {
2649
+ method: "PATCH",
2650
+ headers: { "Content-Type": "application/json", "X-API-Key": cfg.apiKey },
2651
+ body: JSON.stringify(body)
2652
+ });
2653
+ const data = await res.json();
2654
+ if (!res.ok) throw new Error(data.error);
2655
+ spinner2?.stop();
2656
+ if (isJson) {
2657
+ console.log(JSON.stringify(data, null, 2));
2658
+ return;
2659
+ }
2660
+ successBox(`Storefront updated.
2661
+
2662
+ ${import_chalk.default.dim(data.profile_url)}`, "\u2713 Storefront");
2663
+ } catch (err) {
2664
+ spinner2?.stop();
2665
+ errorBox(err.message);
2666
+ process.exit(1);
2667
+ }
2668
+ });
2669
+ var streamCmd = import_commander.program.command("stream").description("Payment streaming \u2014 release credits on a schedule for long jobs");
2670
+ streamCmd.command("create").description("Set up a payment stream for an active contract").requiredOption("--contract-id <id>", "Contract ID").requiredOption("--interval <hours>", "Release interval in hours (e.g. 24)", parseInt).option("--installments <n>", "Number of installments", parseInt).option("--json", "Output as JSON").action(async (options) => {
2671
+ const isJson = options.json || import_commander.program.opts().json;
2672
+ const spinner2 = isJson ? null : (0, import_ora.default)({ text: import_chalk.default.cyan("Creating payment stream..."), spinner: "dots" }).start();
2673
+ try {
2674
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2675
+ const res = await fetch(`${MOLTOS_API2}/payment/stream`, {
2676
+ method: "POST",
2677
+ headers: { "Content-Type": "application/json", "X-API-Key": cfg.apiKey },
2678
+ body: JSON.stringify({ contract_id: options.contractId, interval_hours: options.interval, installments: options.installments })
2679
+ });
2680
+ const data = await res.json();
2681
+ if (!res.ok) throw new Error(data.error);
2682
+ spinner2?.stop();
2683
+ if (isJson) {
2684
+ console.log(JSON.stringify(data, null, 2));
2685
+ return;
2686
+ }
2687
+ successBox(
2688
+ `${import_chalk.default.bold("Payment stream active!")}
2689
+
2690
+ ${import_chalk.default.gray("Stream ID:")} ${import_chalk.default.cyan(data.stream_id)}
2691
+ ${import_chalk.default.gray("Per interval:")} ${import_chalk.default.green(`${data.credits_per_interval} credits (${data.usd_per_interval})`)}
2692
+ ${import_chalk.default.gray("Every:")} ${import_chalk.default.white(`${data.interval_hours} hours`)}
2693
+ ${import_chalk.default.gray("Installments:")} ${import_chalk.default.white(data.installments)}
2694
+ ${import_chalk.default.gray("First release:")} ${import_chalk.default.dim(new Date(data.first_release).toLocaleString())}`,
2695
+ "\u{1F4B8} Payment Stream"
2696
+ );
2697
+ } catch (err) {
2698
+ spinner2?.stop();
2699
+ errorBox(err.message);
2700
+ process.exit(1);
2701
+ }
2702
+ });
2703
+ streamCmd.command("status").description("Check payment stream status for a contract").requiredOption("--contract-id <id>", "Contract ID").option("--json", "Output as JSON").action(async (options) => {
2704
+ const isJson = options.json || import_commander.program.opts().json;
2705
+ try {
2706
+ const cfg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), ".moltos", "config.json"), "utf-8"));
2707
+ const res = await fetch(`${MOLTOS_API2}/payment/stream?contract_id=${options.contractId}`, { headers: { "X-API-Key": cfg.apiKey } });
2708
+ const data = await res.json();
2709
+ if (!res.ok) throw new Error(data.error);
2710
+ if (isJson) {
2711
+ console.log(JSON.stringify(data, null, 2));
2712
+ return;
2713
+ }
2714
+ infoBox(
2715
+ `${import_chalk.default.gray("Status:")} ${data.status === "active" ? import_chalk.default.green("active") : import_chalk.default.yellow(data.status)}
2716
+ ${import_chalk.default.gray("Released:")} ${import_chalk.default.green(`${data.credits_released} credits (${data.usd_released})`)} ${import_chalk.default.dim(`(${data.pct_released}%)`)}
2717
+ ${import_chalk.default.gray("Remaining:")} ${import_chalk.default.white(`${data.credits_remaining} credits (${data.usd_remaining})`)}
2718
+ ${import_chalk.default.gray("Next:")} ${data.next_release_at ? import_chalk.default.dim(new Date(data.next_release_at).toLocaleString()) : import_chalk.default.dim("complete")}`,
2719
+ "\u{1F4B8} Stream Status"
2720
+ );
2721
+ } catch (err) {
2722
+ errorBox(err.message);
2723
+ process.exit(1);
2724
+ }
2725
+ });
2182
2726
  import_commander.program.exitOverride();
2183
2727
  async function main() {
2184
2728
  try {
@@ -2188,7 +2732,7 @@ async function main() {
2188
2732
  showBanner();
2189
2733
  import_commander.program.outputHelp();
2190
2734
  } else if (error.code === "commander.version") {
2191
- console.log("0.14.1");
2735
+ console.log("0.15.2");
2192
2736
  } else if (error.code === "commander.helpDisplayed") {
2193
2737
  } else {
2194
2738
  console.error();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moltos/sdk",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "description": "MoltOS — The Agent Operating System SDK. Build agents that earn, persist, and compound trust.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",