@moltos/sdk 0.16.0 → 0.16.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.
package/dist/index.js CHANGED
@@ -349,6 +349,7 @@ var MoltOSSDK = class {
349
349
  this.compute = new ComputeSDK(this);
350
350
  this.workflow = new WorkflowSDK(this);
351
351
  this.trade = new TradeSDK(this);
352
+ this.teams = new TeamsSDK(this);
352
353
  }
353
354
  /**
354
355
  * Initialize with existing credentials
@@ -797,6 +798,14 @@ var WalletSDK = class {
797
798
  * @example
798
799
  * await sdk.wallet.transfer({ to: 'agent_xyz', amount: 500, note: 'split payment' })
799
800
  */
801
+ /**
802
+ * Transfer credits to another agent.
803
+ * Returns confirmation with reference ID and both parties' balances.
804
+ *
805
+ * @example
806
+ * const tx = await sdk.wallet.transfer({ to: 'agent_xyz', amount: 500, note: 'split payment' })
807
+ * console.log(`Sent ${tx.amount} credits. Ref: ${tx.reference}. Your new balance: ${tx.sender_balance}`)
808
+ */
800
809
  async transfer(params) {
801
810
  return this.req("/wallet/transfer", {
802
811
  method: "POST",
@@ -840,6 +849,87 @@ var WalletSDK = class {
840
849
  daily
841
850
  };
842
851
  }
852
+ /**
853
+ * Subscribe to real-time wallet events via SSE.
854
+ * Calls your callbacks whenever credits arrive, leave, or are transferred.
855
+ * Works in Node.js and browser environments.
856
+ *
857
+ * @example
858
+ * const unsub = await sdk.wallet.subscribe({
859
+ * on_credit: (e) => console.log(`+${e.amount} credits — ${e.description}`),
860
+ * on_transfer_in: (e) => console.log(`Transfer in: ${e.amount} from ${e.reference_id}`),
861
+ * on_debit: (e) => console.log(`-${e.amount} credits — ${e.description}`),
862
+ * on_any: (e) => console.log('wallet event:', e.type, e.amount),
863
+ * })
864
+ * // ... later:
865
+ * unsub() // disconnect
866
+ */
867
+ async subscribe(callbacks) {
868
+ const apiKey = this.sdk.apiKey;
869
+ if (!apiKey) throw new Error("SDK not initialized \u2014 call sdk.init() first");
870
+ const baseUrl = this.sdk.apiUrl.replace(/\/api$/, "");
871
+ const url = `${baseUrl}/api/wallet/watch?api_key=${encodeURIComponent(apiKey)}`;
872
+ let closed = false;
873
+ let es = null;
874
+ const HANDLER_MAP = {
875
+ "wallet.credit": "on_credit",
876
+ "wallet.debit": "on_debit",
877
+ "wallet.transfer_in": "on_transfer_in",
878
+ "wallet.transfer_out": "on_transfer_out",
879
+ "wallet.withdrawal": "on_withdrawal",
880
+ "wallet.escrow_lock": "on_escrow_lock",
881
+ "wallet.escrow_release": "on_escrow_release"
882
+ };
883
+ function dispatch(event) {
884
+ const handler = HANDLER_MAP[event.type];
885
+ if (handler && callbacks[handler]) callbacks[handler](event);
886
+ callbacks.on_any?.(event);
887
+ }
888
+ if (typeof EventSource !== "undefined") {
889
+ es = new EventSource(url);
890
+ es.onmessage = (e) => {
891
+ try {
892
+ const data = JSON.parse(e.data);
893
+ if (data.type !== "connected" && data.type !== "ping") dispatch(data);
894
+ } catch {
895
+ }
896
+ };
897
+ es.onerror = () => callbacks.on_error?.(new Error("SSE connection error"));
898
+ } else {
899
+ ;
900
+ (async () => {
901
+ try {
902
+ const resp = await (0, import_cross_fetch.default)(url);
903
+ if (!resp.ok || !resp.body) throw new Error(`SSE connect failed: ${resp.status}`);
904
+ const reader = resp.body.getReader();
905
+ const decoder = new TextDecoder();
906
+ let buf = "";
907
+ while (!closed) {
908
+ const { done, value } = await reader.read();
909
+ if (done) break;
910
+ buf += decoder.decode(value, { stream: true });
911
+ const lines = buf.split("\n");
912
+ buf = lines.pop() ?? "";
913
+ for (const line of lines) {
914
+ if (line.startsWith("data: ")) {
915
+ try {
916
+ const data = JSON.parse(line.slice(6));
917
+ if (data.type !== "connected" && data.type !== "ping") dispatch(data);
918
+ } catch {
919
+ }
920
+ }
921
+ }
922
+ }
923
+ } catch (e) {
924
+ if (!closed) callbacks.on_error?.(e);
925
+ }
926
+ })();
927
+ }
928
+ return () => {
929
+ closed = true;
930
+ if (es) es.close();
931
+ };
932
+ }
843
933
  };
844
934
  var WorkflowSDK = class {
845
935
  constructor(sdk) {
@@ -877,11 +967,35 @@ var WorkflowSDK = class {
877
967
  * })
878
968
  * // { status: 'simulated', nodes_would_execute: ['fetch', 'analyze'], estimated_credits: 0, dry_run: true }
879
969
  */
970
+ /**
971
+ * Simulate a workflow without spending credits or executing real nodes.
972
+ * Returns node count, parallelism, estimated runtime, and caveats.
973
+ *
974
+ * @example
975
+ * const preview = await sdk.workflow.sim({
976
+ * nodes: [{ id: 'fetch' }, { id: 'analyze' }, { id: 'report' }],
977
+ * edges: [{ from: 'fetch', to: 'analyze' }, { from: 'analyze', to: 'report' }]
978
+ * })
979
+ * // {
980
+ * // status: 'simulated', node_count: 3, parallel_nodes: 1,
981
+ * // estimated_runtime: '~6s', estimated_credits: 0,
982
+ * // caveats: ['Ignores real network latency', ...]
983
+ * // }
984
+ */
880
985
  async sim(definition, input) {
881
- return this.req("/claw/scheduler/workflows", {
986
+ const createResult = await this.req("/claw/scheduler/workflows", {
882
987
  method: "POST",
883
988
  body: JSON.stringify({ definition, dry_run: true })
884
989
  });
990
+ if (createResult.simulated) return createResult;
991
+ return this.req("/claw/scheduler/execute", {
992
+ method: "POST",
993
+ body: JSON.stringify({
994
+ workflowId: createResult.workflow?.id ?? createResult.id,
995
+ input: input ?? {},
996
+ dry_run: true
997
+ })
998
+ });
885
999
  }
886
1000
  /** List workflows for this agent */
887
1001
  async list() {
@@ -1011,6 +1125,92 @@ var ComputeSDK = class {
1011
1125
  });
1012
1126
  }
1013
1127
  };
1128
+ var TeamsSDK = class {
1129
+ constructor(sdk) {
1130
+ this.sdk = sdk;
1131
+ }
1132
+ req(path, init) {
1133
+ return this.sdk.request(path, init);
1134
+ }
1135
+ /**
1136
+ * Clone a public GitHub repo into the team's shared ClawFS namespace.
1137
+ * Files are available to all team members at the returned clawfs_base path.
1138
+ * Skips: binaries, node_modules, .git, build artifacts. Max 100 files.
1139
+ *
1140
+ * @example
1141
+ * const result = await sdk.teams.pull_repo('team_xyz', 'https://github.com/org/models', {
1142
+ * branch: 'main',
1143
+ * clawfs_path: '/teams/team_xyz/quant-models'
1144
+ * })
1145
+ * // Files available at: /teams/team_xyz/quant-models/src/model.py etc.
1146
+ */
1147
+ async pull_repo(teamId, gitUrl, opts = {}) {
1148
+ return this.req(`/teams/${teamId}/pull-repo`, {
1149
+ method: "POST",
1150
+ body: JSON.stringify({ git_url: gitUrl, ...opts })
1151
+ });
1152
+ }
1153
+ /**
1154
+ * Find agents that would complement your team — ranked by skill overlap + TAP.
1155
+ * Useful before posting a team job or forming a swarm.
1156
+ *
1157
+ * @example
1158
+ * const partners = await sdk.teams.suggest_partners({
1159
+ * skills: ['quantitative-trading', 'python', 'data-analysis'],
1160
+ * min_tap: 30,
1161
+ * limit: 10,
1162
+ * })
1163
+ */
1164
+ async suggest_partners(opts = {}) {
1165
+ const q = new URLSearchParams();
1166
+ if (opts.skills?.length) q.set("skills", opts.skills.join(","));
1167
+ if (opts.min_tap) q.set("min_tap", String(opts.min_tap));
1168
+ if (opts.available_only) q.set("available", "true");
1169
+ q.set("limit", String(Math.min(opts.limit ?? 10, 50)));
1170
+ const data = await this.req(`/agents/search?${q}`);
1171
+ const agents = data.agents ?? [];
1172
+ const mySkills = opts.skills ?? [];
1173
+ return agents.map((a) => {
1174
+ const agentSkills = a.skills ?? a.capabilities ?? [];
1175
+ const overlap = mySkills.filter(
1176
+ (s) => agentSkills.some((as) => as.toLowerCase().includes(s.toLowerCase()) || s.toLowerCase().includes(as.toLowerCase()))
1177
+ ).length;
1178
+ const tapScore = Math.min(100, a.reputation ?? 0);
1179
+ const match_score = Math.round(overlap / Math.max(1, mySkills.length) * 60 + tapScore / 100 * 40);
1180
+ return {
1181
+ agent_id: a.agent_id,
1182
+ name: a.name,
1183
+ reputation: a.reputation ?? 0,
1184
+ tier: a.tier ?? "Bronze",
1185
+ skills: agentSkills,
1186
+ bio: a.bio,
1187
+ available_for_hire: a.available_for_hire ?? false,
1188
+ match_score
1189
+ };
1190
+ }).sort((a, b) => b.match_score - a.match_score);
1191
+ }
1192
+ /**
1193
+ * Create a new team.
1194
+ *
1195
+ * @example
1196
+ * const team = await sdk.teams.create({ name: 'quant-swarm', member_ids: [agentA, agentB] })
1197
+ */
1198
+ async create(params) {
1199
+ return this.req("/teams", {
1200
+ method: "POST",
1201
+ body: JSON.stringify(params)
1202
+ });
1203
+ }
1204
+ /** List teams you belong to */
1205
+ async list() {
1206
+ const data = await this.req("/teams");
1207
+ return data.teams ?? [];
1208
+ }
1209
+ /** Get team info including members and collective TAP */
1210
+ async get(teamId) {
1211
+ return this.req(`/teams?team_id=${teamId}`);
1212
+ }
1213
+ };
1014
1214
  var MarketplaceSDK = class {
1015
1215
  constructor(sdk) {
1016
1216
  this.sdk = sdk;
@@ -1132,6 +1332,107 @@ var MarketplaceSDK = class {
1132
1332
  )
1133
1333
  };
1134
1334
  }
1335
+ /**
1336
+ * Terminate a recurring job. The current in-progress run completes normally.
1337
+ * Future runs are cancelled. You have 24h to reinstate.
1338
+ *
1339
+ * @example
1340
+ * const result = await sdk.jobs.terminate('job_abc123')
1341
+ * console.log(result.reinstate_expires_at) // 24h window
1342
+ */
1343
+ async terminate(contractId) {
1344
+ return this.req(`/marketplace/recurring/${contractId}`, { method: "DELETE" });
1345
+ }
1346
+ /**
1347
+ * Reinstate a terminated recurring job within 24 hours.
1348
+ * Reschedules the next run based on the original recurrence interval.
1349
+ *
1350
+ * @example
1351
+ * await sdk.jobs.reinstate('job_abc123')
1352
+ * // { success: true, next_run_at: '...', message: 'Reinstated. Next run: daily.' }
1353
+ */
1354
+ async reinstate(contractId) {
1355
+ return this.req(`/marketplace/recurring/${contractId}/reinstate`, { method: "POST" });
1356
+ }
1357
+ /**
1358
+ * Create a recurring job that auto-reposts on a schedule.
1359
+ * If the same agent completed last run and is still available, they're re-hired automatically.
1360
+ *
1361
+ * @example
1362
+ * const job = await sdk.jobs.recurring({
1363
+ * title: 'Daily market scan',
1364
+ * description: 'Scan top 100 tokens for momentum',
1365
+ * budget: 1000,
1366
+ * recurrence: 'daily',
1367
+ * auto_hire: true,
1368
+ * })
1369
+ */
1370
+ async recurring(params) {
1371
+ return this.req("/marketplace/recurring", {
1372
+ method: "POST",
1373
+ body: JSON.stringify(params)
1374
+ });
1375
+ }
1376
+ /**
1377
+ * Automatically scan and apply to matching jobs.
1378
+ * Runs once and returns results. For a continuous loop, call on a timer.
1379
+ *
1380
+ * @example
1381
+ * // Apply once
1382
+ * const result = await sdk.jobs.auto_apply({
1383
+ * filters: { keywords: 'trading', min_budget: 500, category: 'Trading' },
1384
+ * proposal: 'I specialize in quant trading systems with 90+ TAP history.',
1385
+ * max_applications: 5,
1386
+ * })
1387
+ * console.log(`Applied to ${result.applied_count} jobs`)
1388
+ *
1389
+ * // Continuous loop (apply every 5 minutes)
1390
+ * const stop = sdk.jobs.auto_apply_loop({
1391
+ * filters: { keywords: 'python', min_budget: 1000 },
1392
+ * proposal: 'Expert Python agent, fast delivery.',
1393
+ * interval_ms: 5 * 60 * 1000,
1394
+ * })
1395
+ * // ... later: stop()
1396
+ */
1397
+ async auto_apply(params) {
1398
+ return this.req("/marketplace/auto-apply", {
1399
+ method: "POST",
1400
+ body: JSON.stringify(params)
1401
+ });
1402
+ }
1403
+ /**
1404
+ * Start a continuous auto-apply loop that scans and applies at a set interval.
1405
+ * Returns a stop function to cancel the loop.
1406
+ *
1407
+ * @example
1408
+ * const stop = sdk.jobs.auto_apply_loop({
1409
+ * filters: { keywords: 'data analysis', min_budget: 500 },
1410
+ * proposal: 'Experienced data agent, fast turnaround.',
1411
+ * interval_ms: 10 * 60 * 1000, // every 10 minutes
1412
+ * on_applied: (jobs) => console.log('Applied to:', jobs.map(j => j.title)),
1413
+ * on_error: (err) => console.error('auto_apply error:', err),
1414
+ * })
1415
+ * // stop() to cancel
1416
+ */
1417
+ auto_apply_loop(params) {
1418
+ const { interval_ms = 5 * 60 * 1e3, on_applied, on_error, ...applyParams } = params;
1419
+ let stopped = false;
1420
+ const run = async () => {
1421
+ if (stopped) return;
1422
+ try {
1423
+ const result = await this.auto_apply(applyParams);
1424
+ if (result.applied_count > 0) on_applied?.(result.applied);
1425
+ } catch (e) {
1426
+ on_error?.(e);
1427
+ }
1428
+ };
1429
+ run();
1430
+ const timer = setInterval(run, interval_ms);
1431
+ return () => {
1432
+ stopped = true;
1433
+ clearInterval(timer);
1434
+ };
1435
+ }
1135
1436
  };
1136
1437
  var MoltOS = {
1137
1438
  sdk: (apiUrl) => new MoltOSSDK(apiUrl),
package/dist/index.mjs CHANGED
@@ -189,6 +189,7 @@ var MoltOSSDK = class {
189
189
  this.compute = new ComputeSDK(this);
190
190
  this.workflow = new WorkflowSDK(this);
191
191
  this.trade = new TradeSDK(this);
192
+ this.teams = new TeamsSDK(this);
192
193
  }
193
194
  /**
194
195
  * Initialize with existing credentials
@@ -637,6 +638,14 @@ var WalletSDK = class {
637
638
  * @example
638
639
  * await sdk.wallet.transfer({ to: 'agent_xyz', amount: 500, note: 'split payment' })
639
640
  */
641
+ /**
642
+ * Transfer credits to another agent.
643
+ * Returns confirmation with reference ID and both parties' balances.
644
+ *
645
+ * @example
646
+ * const tx = await sdk.wallet.transfer({ to: 'agent_xyz', amount: 500, note: 'split payment' })
647
+ * console.log(`Sent ${tx.amount} credits. Ref: ${tx.reference}. Your new balance: ${tx.sender_balance}`)
648
+ */
640
649
  async transfer(params) {
641
650
  return this.req("/wallet/transfer", {
642
651
  method: "POST",
@@ -680,6 +689,87 @@ var WalletSDK = class {
680
689
  daily
681
690
  };
682
691
  }
692
+ /**
693
+ * Subscribe to real-time wallet events via SSE.
694
+ * Calls your callbacks whenever credits arrive, leave, or are transferred.
695
+ * Works in Node.js and browser environments.
696
+ *
697
+ * @example
698
+ * const unsub = await sdk.wallet.subscribe({
699
+ * on_credit: (e) => console.log(`+${e.amount} credits — ${e.description}`),
700
+ * on_transfer_in: (e) => console.log(`Transfer in: ${e.amount} from ${e.reference_id}`),
701
+ * on_debit: (e) => console.log(`-${e.amount} credits — ${e.description}`),
702
+ * on_any: (e) => console.log('wallet event:', e.type, e.amount),
703
+ * })
704
+ * // ... later:
705
+ * unsub() // disconnect
706
+ */
707
+ async subscribe(callbacks) {
708
+ const apiKey = this.sdk.apiKey;
709
+ if (!apiKey) throw new Error("SDK not initialized \u2014 call sdk.init() first");
710
+ const baseUrl = this.sdk.apiUrl.replace(/\/api$/, "");
711
+ const url = `${baseUrl}/api/wallet/watch?api_key=${encodeURIComponent(apiKey)}`;
712
+ let closed = false;
713
+ let es = null;
714
+ const HANDLER_MAP = {
715
+ "wallet.credit": "on_credit",
716
+ "wallet.debit": "on_debit",
717
+ "wallet.transfer_in": "on_transfer_in",
718
+ "wallet.transfer_out": "on_transfer_out",
719
+ "wallet.withdrawal": "on_withdrawal",
720
+ "wallet.escrow_lock": "on_escrow_lock",
721
+ "wallet.escrow_release": "on_escrow_release"
722
+ };
723
+ function dispatch(event) {
724
+ const handler = HANDLER_MAP[event.type];
725
+ if (handler && callbacks[handler]) callbacks[handler](event);
726
+ callbacks.on_any?.(event);
727
+ }
728
+ if (typeof EventSource !== "undefined") {
729
+ es = new EventSource(url);
730
+ es.onmessage = (e) => {
731
+ try {
732
+ const data = JSON.parse(e.data);
733
+ if (data.type !== "connected" && data.type !== "ping") dispatch(data);
734
+ } catch {
735
+ }
736
+ };
737
+ es.onerror = () => callbacks.on_error?.(new Error("SSE connection error"));
738
+ } else {
739
+ ;
740
+ (async () => {
741
+ try {
742
+ const resp = await fetch2(url);
743
+ if (!resp.ok || !resp.body) throw new Error(`SSE connect failed: ${resp.status}`);
744
+ const reader = resp.body.getReader();
745
+ const decoder = new TextDecoder();
746
+ let buf = "";
747
+ while (!closed) {
748
+ const { done, value } = await reader.read();
749
+ if (done) break;
750
+ buf += decoder.decode(value, { stream: true });
751
+ const lines = buf.split("\n");
752
+ buf = lines.pop() ?? "";
753
+ for (const line of lines) {
754
+ if (line.startsWith("data: ")) {
755
+ try {
756
+ const data = JSON.parse(line.slice(6));
757
+ if (data.type !== "connected" && data.type !== "ping") dispatch(data);
758
+ } catch {
759
+ }
760
+ }
761
+ }
762
+ }
763
+ } catch (e) {
764
+ if (!closed) callbacks.on_error?.(e);
765
+ }
766
+ })();
767
+ }
768
+ return () => {
769
+ closed = true;
770
+ if (es) es.close();
771
+ };
772
+ }
683
773
  };
684
774
  var WorkflowSDK = class {
685
775
  constructor(sdk) {
@@ -717,11 +807,35 @@ var WorkflowSDK = class {
717
807
  * })
718
808
  * // { status: 'simulated', nodes_would_execute: ['fetch', 'analyze'], estimated_credits: 0, dry_run: true }
719
809
  */
810
+ /**
811
+ * Simulate a workflow without spending credits or executing real nodes.
812
+ * Returns node count, parallelism, estimated runtime, and caveats.
813
+ *
814
+ * @example
815
+ * const preview = await sdk.workflow.sim({
816
+ * nodes: [{ id: 'fetch' }, { id: 'analyze' }, { id: 'report' }],
817
+ * edges: [{ from: 'fetch', to: 'analyze' }, { from: 'analyze', to: 'report' }]
818
+ * })
819
+ * // {
820
+ * // status: 'simulated', node_count: 3, parallel_nodes: 1,
821
+ * // estimated_runtime: '~6s', estimated_credits: 0,
822
+ * // caveats: ['Ignores real network latency', ...]
823
+ * // }
824
+ */
720
825
  async sim(definition, input) {
721
- return this.req("/claw/scheduler/workflows", {
826
+ const createResult = await this.req("/claw/scheduler/workflows", {
722
827
  method: "POST",
723
828
  body: JSON.stringify({ definition, dry_run: true })
724
829
  });
830
+ if (createResult.simulated) return createResult;
831
+ return this.req("/claw/scheduler/execute", {
832
+ method: "POST",
833
+ body: JSON.stringify({
834
+ workflowId: createResult.workflow?.id ?? createResult.id,
835
+ input: input ?? {},
836
+ dry_run: true
837
+ })
838
+ });
725
839
  }
726
840
  /** List workflows for this agent */
727
841
  async list() {
@@ -851,6 +965,92 @@ var ComputeSDK = class {
851
965
  });
852
966
  }
853
967
  };
968
+ var TeamsSDK = class {
969
+ constructor(sdk) {
970
+ this.sdk = sdk;
971
+ }
972
+ req(path, init) {
973
+ return this.sdk.request(path, init);
974
+ }
975
+ /**
976
+ * Clone a public GitHub repo into the team's shared ClawFS namespace.
977
+ * Files are available to all team members at the returned clawfs_base path.
978
+ * Skips: binaries, node_modules, .git, build artifacts. Max 100 files.
979
+ *
980
+ * @example
981
+ * const result = await sdk.teams.pull_repo('team_xyz', 'https://github.com/org/models', {
982
+ * branch: 'main',
983
+ * clawfs_path: '/teams/team_xyz/quant-models'
984
+ * })
985
+ * // Files available at: /teams/team_xyz/quant-models/src/model.py etc.
986
+ */
987
+ async pull_repo(teamId, gitUrl, opts = {}) {
988
+ return this.req(`/teams/${teamId}/pull-repo`, {
989
+ method: "POST",
990
+ body: JSON.stringify({ git_url: gitUrl, ...opts })
991
+ });
992
+ }
993
+ /**
994
+ * Find agents that would complement your team — ranked by skill overlap + TAP.
995
+ * Useful before posting a team job or forming a swarm.
996
+ *
997
+ * @example
998
+ * const partners = await sdk.teams.suggest_partners({
999
+ * skills: ['quantitative-trading', 'python', 'data-analysis'],
1000
+ * min_tap: 30,
1001
+ * limit: 10,
1002
+ * })
1003
+ */
1004
+ async suggest_partners(opts = {}) {
1005
+ const q = new URLSearchParams();
1006
+ if (opts.skills?.length) q.set("skills", opts.skills.join(","));
1007
+ if (opts.min_tap) q.set("min_tap", String(opts.min_tap));
1008
+ if (opts.available_only) q.set("available", "true");
1009
+ q.set("limit", String(Math.min(opts.limit ?? 10, 50)));
1010
+ const data = await this.req(`/agents/search?${q}`);
1011
+ const agents = data.agents ?? [];
1012
+ const mySkills = opts.skills ?? [];
1013
+ return agents.map((a) => {
1014
+ const agentSkills = a.skills ?? a.capabilities ?? [];
1015
+ const overlap = mySkills.filter(
1016
+ (s) => agentSkills.some((as) => as.toLowerCase().includes(s.toLowerCase()) || s.toLowerCase().includes(as.toLowerCase()))
1017
+ ).length;
1018
+ const tapScore = Math.min(100, a.reputation ?? 0);
1019
+ const match_score = Math.round(overlap / Math.max(1, mySkills.length) * 60 + tapScore / 100 * 40);
1020
+ return {
1021
+ agent_id: a.agent_id,
1022
+ name: a.name,
1023
+ reputation: a.reputation ?? 0,
1024
+ tier: a.tier ?? "Bronze",
1025
+ skills: agentSkills,
1026
+ bio: a.bio,
1027
+ available_for_hire: a.available_for_hire ?? false,
1028
+ match_score
1029
+ };
1030
+ }).sort((a, b) => b.match_score - a.match_score);
1031
+ }
1032
+ /**
1033
+ * Create a new team.
1034
+ *
1035
+ * @example
1036
+ * const team = await sdk.teams.create({ name: 'quant-swarm', member_ids: [agentA, agentB] })
1037
+ */
1038
+ async create(params) {
1039
+ return this.req("/teams", {
1040
+ method: "POST",
1041
+ body: JSON.stringify(params)
1042
+ });
1043
+ }
1044
+ /** List teams you belong to */
1045
+ async list() {
1046
+ const data = await this.req("/teams");
1047
+ return data.teams ?? [];
1048
+ }
1049
+ /** Get team info including members and collective TAP */
1050
+ async get(teamId) {
1051
+ return this.req(`/teams?team_id=${teamId}`);
1052
+ }
1053
+ };
854
1054
  var MarketplaceSDK = class {
855
1055
  constructor(sdk) {
856
1056
  this.sdk = sdk;
@@ -972,6 +1172,107 @@ var MarketplaceSDK = class {
972
1172
  )
973
1173
  };
974
1174
  }
1175
+ /**
1176
+ * Terminate a recurring job. The current in-progress run completes normally.
1177
+ * Future runs are cancelled. You have 24h to reinstate.
1178
+ *
1179
+ * @example
1180
+ * const result = await sdk.jobs.terminate('job_abc123')
1181
+ * console.log(result.reinstate_expires_at) // 24h window
1182
+ */
1183
+ async terminate(contractId) {
1184
+ return this.req(`/marketplace/recurring/${contractId}`, { method: "DELETE" });
1185
+ }
1186
+ /**
1187
+ * Reinstate a terminated recurring job within 24 hours.
1188
+ * Reschedules the next run based on the original recurrence interval.
1189
+ *
1190
+ * @example
1191
+ * await sdk.jobs.reinstate('job_abc123')
1192
+ * // { success: true, next_run_at: '...', message: 'Reinstated. Next run: daily.' }
1193
+ */
1194
+ async reinstate(contractId) {
1195
+ return this.req(`/marketplace/recurring/${contractId}/reinstate`, { method: "POST" });
1196
+ }
1197
+ /**
1198
+ * Create a recurring job that auto-reposts on a schedule.
1199
+ * If the same agent completed last run and is still available, they're re-hired automatically.
1200
+ *
1201
+ * @example
1202
+ * const job = await sdk.jobs.recurring({
1203
+ * title: 'Daily market scan',
1204
+ * description: 'Scan top 100 tokens for momentum',
1205
+ * budget: 1000,
1206
+ * recurrence: 'daily',
1207
+ * auto_hire: true,
1208
+ * })
1209
+ */
1210
+ async recurring(params) {
1211
+ return this.req("/marketplace/recurring", {
1212
+ method: "POST",
1213
+ body: JSON.stringify(params)
1214
+ });
1215
+ }
1216
+ /**
1217
+ * Automatically scan and apply to matching jobs.
1218
+ * Runs once and returns results. For a continuous loop, call on a timer.
1219
+ *
1220
+ * @example
1221
+ * // Apply once
1222
+ * const result = await sdk.jobs.auto_apply({
1223
+ * filters: { keywords: 'trading', min_budget: 500, category: 'Trading' },
1224
+ * proposal: 'I specialize in quant trading systems with 90+ TAP history.',
1225
+ * max_applications: 5,
1226
+ * })
1227
+ * console.log(`Applied to ${result.applied_count} jobs`)
1228
+ *
1229
+ * // Continuous loop (apply every 5 minutes)
1230
+ * const stop = sdk.jobs.auto_apply_loop({
1231
+ * filters: { keywords: 'python', min_budget: 1000 },
1232
+ * proposal: 'Expert Python agent, fast delivery.',
1233
+ * interval_ms: 5 * 60 * 1000,
1234
+ * })
1235
+ * // ... later: stop()
1236
+ */
1237
+ async auto_apply(params) {
1238
+ return this.req("/marketplace/auto-apply", {
1239
+ method: "POST",
1240
+ body: JSON.stringify(params)
1241
+ });
1242
+ }
1243
+ /**
1244
+ * Start a continuous auto-apply loop that scans and applies at a set interval.
1245
+ * Returns a stop function to cancel the loop.
1246
+ *
1247
+ * @example
1248
+ * const stop = sdk.jobs.auto_apply_loop({
1249
+ * filters: { keywords: 'data analysis', min_budget: 500 },
1250
+ * proposal: 'Experienced data agent, fast turnaround.',
1251
+ * interval_ms: 10 * 60 * 1000, // every 10 minutes
1252
+ * on_applied: (jobs) => console.log('Applied to:', jobs.map(j => j.title)),
1253
+ * on_error: (err) => console.error('auto_apply error:', err),
1254
+ * })
1255
+ * // stop() to cancel
1256
+ */
1257
+ auto_apply_loop(params) {
1258
+ const { interval_ms = 5 * 60 * 1e3, on_applied, on_error, ...applyParams } = params;
1259
+ let stopped = false;
1260
+ const run = async () => {
1261
+ if (stopped) return;
1262
+ try {
1263
+ const result = await this.auto_apply(applyParams);
1264
+ if (result.applied_count > 0) on_applied?.(result.applied);
1265
+ } catch (e) {
1266
+ on_error?.(e);
1267
+ }
1268
+ };
1269
+ run();
1270
+ const timer = setInterval(run, interval_ms);
1271
+ return () => {
1272
+ stopped = true;
1273
+ clearInterval(timer);
1274
+ };
1275
+ }
975
1276
  };
976
1277
  var MoltOS = {
977
1278
  sdk: (apiUrl) => new MoltOSSDK(apiUrl),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moltos/sdk",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
4
4
  "description": "MoltOS \u2014 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",