@pulseai/sdk 0.1.3 → 0.1.4

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
@@ -13,6 +13,9 @@ var megaethTestnet = defineChain({
13
13
  nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
14
14
  rpcUrls: {
15
15
  default: { http: ["https://carrot.megaeth.com/rpc"] }
16
+ },
17
+ blockExplorers: {
18
+ default: { name: "Blockscout", url: "https://megaeth-testnet-v2.blockscout.com" }
16
19
  }
17
20
  });
18
21
  var megaethMainnet = defineChain({
@@ -21,6 +24,9 @@ var megaethMainnet = defineChain({
21
24
  nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
22
25
  rpcUrls: {
23
26
  default: { http: ["https://mainnet.megaeth.com/rpc"] }
27
+ },
28
+ blockExplorers: {
29
+ default: { name: "Blockscout", url: "https://megaeth.blockscout.com" }
24
30
  }
25
31
  });
26
32
 
@@ -36,15 +42,15 @@ var TESTNET_ADDRESSES = {
36
42
  };
37
43
  var MAINNET_ADDRESSES = {
38
44
  pulseExtension: "0xf1616D2008c4Ff5Ed7BDBd448DAE68615b7A71f0",
39
- serviceMarketplace: "0xfC180058FCB69531818B832C12473302811dfFF6",
45
+ serviceMarketplace: "0x0573C91396184323979F3f7b322C694932F91D44",
40
46
  jobEngine: "0xb5E56262b55aE453E8B16470228F0a5Ef617FF67",
41
47
  feeDistributor: "0x51EdD8E4C4B423b952821fc9e2a7dad15a858B56",
42
48
  identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
43
49
  reputationRegistry: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
44
50
  usdm: "0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7",
45
- buyerRelay: "0x633054593db34c5aAe36F784faeAe51b9604e037"
51
+ buyerRelay: "0x843B5B4AD44C174BAB8bBe11eb001aD7fE70647A"
46
52
  };
47
- var PLATFORM_BUYER_AGENT_ID = 8154n;
53
+ var PLATFORM_BUYER_AGENT_ID = 8155n;
48
54
  var DEFAULT_INDEXER_URLS = {
49
55
  testnet: "https://pulse-indexer.up.railway.app",
50
56
  mainnet: "https://pulse-indexer.up.railway.app"
@@ -1034,6 +1040,11 @@ var serviceMarketplaceAbi = [
1034
1040
  "type": "uint32",
1035
1041
  "internalType": "uint32"
1036
1042
  },
1043
+ {
1044
+ "name": "name",
1045
+ "type": "string",
1046
+ "internalType": "string"
1047
+ },
1037
1048
  {
1038
1049
  "name": "description",
1039
1050
  "type": "string",
@@ -1104,6 +1115,11 @@ var serviceMarketplaceAbi = [
1104
1115
  "type": "uint32",
1105
1116
  "internalType": "uint32"
1106
1117
  },
1118
+ {
1119
+ "name": "name",
1120
+ "type": "string",
1121
+ "internalType": "string"
1122
+ },
1107
1123
  {
1108
1124
  "name": "description",
1109
1125
  "type": "string",
@@ -1156,6 +1172,11 @@ var serviceMarketplaceAbi = [
1156
1172
  "type": "uint32",
1157
1173
  "internalType": "uint32"
1158
1174
  },
1175
+ {
1176
+ "name": "name",
1177
+ "type": "string",
1178
+ "internalType": "string"
1179
+ },
1159
1180
  {
1160
1181
  "name": "description",
1161
1182
  "type": "string",
@@ -1165,6 +1186,24 @@ var serviceMarketplaceAbi = [
1165
1186
  "outputs": [],
1166
1187
  "stateMutability": "nonpayable"
1167
1188
  },
1189
+ {
1190
+ "type": "function",
1191
+ "name": "updateOfferingSchema",
1192
+ "inputs": [
1193
+ {
1194
+ "name": "offeringId",
1195
+ "type": "uint256",
1196
+ "internalType": "uint256"
1197
+ },
1198
+ {
1199
+ "name": "requirementsSchemaURI",
1200
+ "type": "string",
1201
+ "internalType": "string"
1202
+ }
1203
+ ],
1204
+ "outputs": [],
1205
+ "stateMutability": "nonpayable"
1206
+ },
1168
1207
  {
1169
1208
  "type": "event",
1170
1209
  "name": "OfferingActivated",
@@ -1222,6 +1261,25 @@ var serviceMarketplaceAbi = [
1222
1261
  ],
1223
1262
  "anonymous": false
1224
1263
  },
1264
+ {
1265
+ "type": "event",
1266
+ "name": "OfferingSchemaUpdated",
1267
+ "inputs": [
1268
+ {
1269
+ "name": "offeringId",
1270
+ "type": "uint256",
1271
+ "indexed": true,
1272
+ "internalType": "uint256"
1273
+ },
1274
+ {
1275
+ "name": "requirementsSchemaURI",
1276
+ "type": "string",
1277
+ "indexed": false,
1278
+ "internalType": "string"
1279
+ }
1280
+ ],
1281
+ "anonymous": false
1282
+ },
1225
1283
  {
1226
1284
  "type": "event",
1227
1285
  "name": "OfferingUpdated",
@@ -1285,6 +1343,7 @@ async function listOffering(client, params) {
1285
1343
  params.serviceType,
1286
1344
  params.priceUSDm,
1287
1345
  params.slaMinutes,
1346
+ params.name,
1288
1347
  params.description,
1289
1348
  params.requirementsSchemaURI ?? ""
1290
1349
  ]
@@ -1296,12 +1355,20 @@ async function listOffering(client, params) {
1296
1355
  const offeringId = offeringLog?.topics[1] ? BigInt(offeringLog.topics[1]) : 0n;
1297
1356
  return { offeringId, txHash };
1298
1357
  }
1299
- async function updateOffering(client, offeringId, priceUSDm, slaMinutes, description) {
1358
+ async function updateOffering(client, offeringId, priceUSDm, slaMinutes, name, description) {
1300
1359
  return write(client, {
1301
1360
  address: client.addresses.serviceMarketplace,
1302
1361
  abi: serviceMarketplaceAbi,
1303
1362
  functionName: "updateOffering",
1304
- args: [offeringId, priceUSDm, slaMinutes, description]
1363
+ args: [offeringId, priceUSDm, slaMinutes, name, description]
1364
+ });
1365
+ }
1366
+ async function updateOfferingSchema(client, offeringId, requirementsSchemaURI) {
1367
+ return write(client, {
1368
+ address: client.addresses.serviceMarketplace,
1369
+ abi: serviceMarketplaceAbi,
1370
+ functionName: "updateOfferingSchema",
1371
+ args: [offeringId, requirementsSchemaURI]
1305
1372
  });
1306
1373
  }
1307
1374
  async function deactivateOffering(client, offeringId) {
@@ -1337,6 +1404,9 @@ async function getOfferingCount(client) {
1337
1404
  });
1338
1405
  }
1339
1406
 
1407
+ // src/jobs/index.ts
1408
+ import { maxUint256 } from "viem";
1409
+
1340
1410
  // src/abis/JobEngine.ts
1341
1411
  var jobEngineAbi = [
1342
1412
  {
@@ -1812,6 +1882,19 @@ var jobEngineAbi = [
1812
1882
  ],
1813
1883
  "stateMutability": "view"
1814
1884
  },
1885
+ {
1886
+ "type": "function",
1887
+ "name": "setServiceMarketplace",
1888
+ "inputs": [
1889
+ {
1890
+ "name": "newMarketplace",
1891
+ "type": "address",
1892
+ "internalType": "address"
1893
+ }
1894
+ ],
1895
+ "outputs": [],
1896
+ "stateMutability": "nonpayable"
1897
+ },
1815
1898
  {
1816
1899
  "type": "function",
1817
1900
  "name": "settle",
@@ -2088,6 +2171,25 @@ var jobEngineAbi = [
2088
2171
  ],
2089
2172
  "anonymous": false
2090
2173
  },
2174
+ {
2175
+ "type": "event",
2176
+ "name": "ServiceMarketplaceUpdated",
2177
+ "inputs": [
2178
+ {
2179
+ "name": "oldMarketplace",
2180
+ "type": "address",
2181
+ "indexed": true,
2182
+ "internalType": "address"
2183
+ },
2184
+ {
2185
+ "name": "newMarketplace",
2186
+ "type": "address",
2187
+ "indexed": true,
2188
+ "internalType": "address"
2189
+ }
2190
+ ],
2191
+ "anonymous": false
2192
+ },
2091
2193
  {
2092
2194
  "type": "event",
2093
2195
  "name": "Upgraded",
@@ -2339,6 +2441,7 @@ async function signMemo(walletClient, params) {
2339
2441
 
2340
2442
  // src/jobs/index.ts
2341
2443
  async function createJob(client, params) {
2444
+ const { account } = requireWallet(client);
2342
2445
  const offering = await client.publicClient.readContract({
2343
2446
  address: client.addresses.serviceMarketplace,
2344
2447
  abi: serviceMarketplaceAbi,
@@ -2346,13 +2449,21 @@ async function createJob(client, params) {
2346
2449
  args: [params.offeringId]
2347
2450
  });
2348
2451
  const price = offering.priceUSDm;
2349
- const approveTx = await write(client, {
2452
+ const allowance = await client.publicClient.readContract({
2350
2453
  address: client.addresses.usdm,
2351
2454
  abi: erc20Abi,
2352
- functionName: "approve",
2353
- args: [client.addresses.jobEngine, price]
2455
+ functionName: "allowance",
2456
+ args: [account.address, client.addresses.jobEngine]
2354
2457
  });
2355
- await client.publicClient.waitForTransactionReceipt({ hash: approveTx });
2458
+ if (allowance < price) {
2459
+ const approveTx = await write(client, {
2460
+ address: client.addresses.usdm,
2461
+ abi: erc20Abi,
2462
+ functionName: "approve",
2463
+ args: [client.addresses.jobEngine, maxUint256]
2464
+ });
2465
+ await client.publicClient.waitForTransactionReceipt({ hash: approveTx });
2466
+ }
2356
2467
  const txHash = await write(client, {
2357
2468
  address: client.addresses.jobEngine,
2358
2469
  abi: jobEngineAbi,
@@ -2666,39 +2777,14 @@ async function deployJobTerms(client, agentId, params) {
2666
2777
  const { masterAddress } = await deployWarrenMaster(client, agentId, pageAddress, contentBytes.length, 0);
2667
2778
  return { masterAddress, pageAddress, hash, txHash };
2668
2779
  }
2669
- function stripCodeFence(content) {
2670
- let result = content.trim();
2671
- result = result.replace(/^```\w*\n?/, "");
2672
- result = result.replace(/\n?```\s*$/, "");
2673
- return result;
2674
- }
2675
- async function deployDeliverable(client, agentId, jobId, params, indexerUrl) {
2780
+ async function deployDeliverable(client, jobId, params, indexerUrl) {
2676
2781
  const { json, hash } = createDeliverable(params);
2677
- const warrenContent = params.type === "inline" && params.content ? stripCodeFence(params.content) : json;
2678
- const contentBytes = new TextEncoder().encode(warrenContent);
2679
- const { pageAddress, txHash } = await deployWarrenPage(client, warrenContent);
2680
- const { masterAddress } = await deployWarrenMaster(client, agentId, pageAddress, contentBytes.length, 1);
2681
- await write(client, {
2782
+ const txHash = await write(client, {
2682
2783
  address: client.addresses.jobEngine,
2683
2784
  abi: jobEngineAbi,
2684
2785
  functionName: "submitDeliverable",
2685
2786
  args: [jobId, hash]
2686
2787
  });
2687
- if (indexerUrl) {
2688
- try {
2689
- await fetch(`${indexerUrl}/warren-links`, {
2690
- method: "POST",
2691
- headers: { "Content-Type": "application/json" },
2692
- body: JSON.stringify({
2693
- jobId: Number(jobId),
2694
- linkType: "deliverable",
2695
- masterAddress,
2696
- contentHash: hash
2697
- })
2698
- });
2699
- } catch {
2700
- }
2701
- }
2702
2788
  if (indexerUrl) {
2703
2789
  try {
2704
2790
  await fetch(`${indexerUrl.replace(/\/$/, "")}/deliverables`, {
@@ -2708,24 +2794,23 @@ async function deployDeliverable(client, agentId, jobId, params, indexerUrl) {
2708
2794
  jobId: Number(jobId),
2709
2795
  content: json,
2710
2796
  contentHash: hash,
2711
- storageType: "warren"
2797
+ storageType: "deliverable"
2712
2798
  })
2713
2799
  });
2714
2800
  } catch {
2715
2801
  }
2716
2802
  }
2717
- return { masterAddress, pageAddress, hash, txHash };
2803
+ return { hash, txHash };
2718
2804
  }
2719
- async function readDeliverable(client, jobId, indexerUrl) {
2720
- const res = await fetch(`${indexerUrl}/warren-links/${Number(jobId)}`);
2721
- if (!res.ok) throw new Error(`Failed to fetch warren link for job ${jobId}`);
2805
+ async function readDeliverable(jobId, indexerUrl) {
2806
+ const res = await fetch(`${indexerUrl.replace(/\/$/, "")}/deliverables/${Number(jobId)}`);
2807
+ if (!res.ok) throw new Error(`Failed to fetch deliverable for job ${jobId}`);
2722
2808
  const { data } = await res.json();
2723
- if (!data.deliverable) throw new Error(`No deliverable WARREN link for job ${jobId}`);
2724
- const content = await readWarrenMaster(client, data.deliverable.master_address);
2725
- if (!verifyContentHash(content, data.deliverable.content_hash)) {
2809
+ if (!data?.content) throw new Error(`No deliverable content for job ${jobId}`);
2810
+ if (!verifyContentHash(data.content, data.content_hash)) {
2726
2811
  throw new Error("Deliverable content hash mismatch");
2727
2812
  }
2728
- return JSON.parse(content);
2813
+ return JSON.parse(data.content);
2729
2814
  }
2730
2815
  async function deployRequirements(client, agentId, jobId, params, indexerUrl) {
2731
2816
  const { json, hash } = createRequirements(params);
@@ -2881,7 +2966,7 @@ async function callOpenAI(params) {
2881
2966
  role: message.role,
2882
2967
  content: message.content
2883
2968
  })),
2884
- max_tokens: params.maxTokens
2969
+ max_completion_tokens: params.maxTokens
2885
2970
  }),
2886
2971
  signal: params.signal
2887
2972
  });
@@ -3037,6 +3122,16 @@ function parseAndValidateUrl(urlString) {
3037
3122
  }
3038
3123
  return url;
3039
3124
  }
3125
+ function normalizeWarrenUrl(url) {
3126
+ const host = url.hostname.toLowerCase();
3127
+ if (host !== "thewarren.app" && !host.endsWith(".thewarren.app")) return url;
3128
+ const match = url.pathname.match(/^\/v\/site=(\d+)$/);
3129
+ if (!match) return url;
3130
+ const normalized = new URL(url.origin);
3131
+ normalized.pathname = "/api/source";
3132
+ normalized.searchParams.set("site", match[1]);
3133
+ return normalized;
3134
+ }
3040
3135
  function ensureAllowedUrl(url, allowedDomains) {
3041
3136
  if (!allowedDomains || allowedDomains.length === 0) return;
3042
3137
  if (!isAllowedDomain(url.hostname, allowedDomains)) {
@@ -3297,7 +3392,7 @@ var SiteModifierHandler = class {
3297
3392
  if (!isNonEmptyString(siteUrl)) {
3298
3393
  throw new Error("requirements.siteUrl must be a non-empty string");
3299
3394
  }
3300
- const parsedUrl = parseAndValidateUrl(siteUrl);
3395
+ const parsedUrl = normalizeWarrenUrl(parseAndValidateUrl(siteUrl));
3301
3396
  ensureAllowedUrl(parsedUrl, this.config.allowedDomains);
3302
3397
  const modificationRequest = requirements.modificationRequest;
3303
3398
  if (!isNonEmptyString(modificationRequest)) {
@@ -3316,7 +3411,7 @@ var SiteModifierHandler = class {
3316
3411
  throw new Error("requirements.model must be a non-empty string");
3317
3412
  }
3318
3413
  return {
3319
- siteUrl: siteUrl.trim(),
3414
+ siteUrl: parsedUrl.toString(),
3320
3415
  modificationRequest: modificationRequest.trim(),
3321
3416
  provider,
3322
3417
  model: typeof model === "string" ? model.trim() : void 0
@@ -3402,6 +3497,151 @@ var SiteModifierHandler = class {
3402
3497
  }
3403
3498
  };
3404
3499
 
3500
+ // src/handler/prompt-handler.ts
3501
+ var DEFAULT_MAX_TOKENS2 = 8192;
3502
+ var AI_MAX_RETRIES2 = 3;
3503
+ var RETRY_DELAY_MS2 = 2e3;
3504
+ var DEFAULT_MODELS2 = {
3505
+ openai: "gpt-5.2",
3506
+ anthropic: "claude-sonnet-4-6",
3507
+ google: "gemini-3.1-pro-preview"
3508
+ };
3509
+ function isRecord2(value) {
3510
+ return typeof value === "object" && value !== null;
3511
+ }
3512
+ function isNonEmptyString2(value) {
3513
+ return typeof value === "string" && value.trim().length > 0;
3514
+ }
3515
+ var PromptHandler = class {
3516
+ offeringId;
3517
+ autoAccept = true;
3518
+ schema = {
3519
+ version: 1,
3520
+ serviceRequirements: {
3521
+ type: "object",
3522
+ properties: {
3523
+ prompt: {
3524
+ type: "string",
3525
+ description: "Prompt to send to AI"
3526
+ },
3527
+ context: {
3528
+ type: "string",
3529
+ description: "Optional additional context"
3530
+ }
3531
+ },
3532
+ required: ["prompt"]
3533
+ },
3534
+ deliverableRequirements: {
3535
+ type: "object",
3536
+ properties: {
3537
+ type: {
3538
+ type: "string",
3539
+ description: 'Delivery type, always "inline"',
3540
+ enum: ["inline"]
3541
+ },
3542
+ content: {
3543
+ type: "string",
3544
+ description: "Generated markdown content"
3545
+ },
3546
+ mimeType: {
3547
+ type: "string",
3548
+ description: 'Content type, always "text/markdown"',
3549
+ enum: ["text/markdown"]
3550
+ }
3551
+ },
3552
+ required: ["type", "content", "mimeType"]
3553
+ }
3554
+ };
3555
+ config;
3556
+ constructor(offeringId, config) {
3557
+ this.offeringId = offeringId;
3558
+ this.config = config;
3559
+ }
3560
+ async validateRequirements(context) {
3561
+ try {
3562
+ this.parseRequirements(context.requirements);
3563
+ return { valid: true };
3564
+ } catch (error) {
3565
+ return {
3566
+ valid: false,
3567
+ reason: error instanceof Error ? error.message : String(error)
3568
+ };
3569
+ }
3570
+ }
3571
+ async executeJob(context) {
3572
+ const requirements = this.parseRequirements(context.requirements);
3573
+ const provider = this.config.aiProvider;
3574
+ const model = this.config.aiModel?.trim() || DEFAULT_MODELS2[provider];
3575
+ const maxTokens = this.config.maxTokens && this.config.maxTokens > 0 ? this.config.maxTokens : DEFAULT_MAX_TOKENS2;
3576
+ const apiKey = await this.config.getApiKey(provider);
3577
+ if (!isNonEmptyString2(apiKey)) {
3578
+ throw new Error(`Missing API key for provider "${provider}"`);
3579
+ }
3580
+ const userPrompt = requirements.context ? [requirements.prompt, requirements.context].join("\n\n") : requirements.prompt;
3581
+ const aiMessages = [
3582
+ { role: "system", content: this.config.systemPrompt },
3583
+ { role: "user", content: userPrompt }
3584
+ ];
3585
+ let aiResponse = null;
3586
+ let lastError = null;
3587
+ for (let attempt = 1; attempt <= AI_MAX_RETRIES2; attempt++) {
3588
+ try {
3589
+ aiResponse = await callAI({
3590
+ provider,
3591
+ model,
3592
+ maxTokens,
3593
+ apiKey,
3594
+ signal: context.abortSignal,
3595
+ messages: aiMessages
3596
+ });
3597
+ if (aiResponse.truncated) {
3598
+ throw new Error("AI output was truncated (hit token limit).");
3599
+ }
3600
+ break;
3601
+ } catch (err) {
3602
+ lastError = err instanceof Error ? err : new Error(String(err));
3603
+ console.error(
3604
+ `[prompt-handler] ${model} failed (attempt ${attempt}/${AI_MAX_RETRIES2}): ${lastError.message}`
3605
+ );
3606
+ }
3607
+ if (attempt < AI_MAX_RETRIES2) {
3608
+ const delay = RETRY_DELAY_MS2 * attempt;
3609
+ console.log(`[prompt-handler] retrying in ${delay}ms...`);
3610
+ await new Promise((r) => setTimeout(r, delay));
3611
+ }
3612
+ }
3613
+ if (!aiResponse) {
3614
+ throw new Error(
3615
+ `AI generation failed after ${AI_MAX_RETRIES2} attempts. Please try again later. Last error: ${lastError?.message ?? "unknown"}`
3616
+ );
3617
+ }
3618
+ return {
3619
+ type: "inline",
3620
+ content: aiResponse.content,
3621
+ mimeType: "text/markdown",
3622
+ usage: aiResponse.usage ? { provider, inputTokens: aiResponse.usage.inputTokens, outputTokens: aiResponse.usage.outputTokens } : void 0
3623
+ };
3624
+ }
3625
+ parseRequirements(requirements) {
3626
+ if (!isRecord2(requirements)) {
3627
+ throw new Error("Missing requirements object");
3628
+ }
3629
+ const prompt = requirements.prompt;
3630
+ if (!isNonEmptyString2(prompt)) {
3631
+ throw new Error("requirements.prompt must be a non-empty string");
3632
+ }
3633
+ const context = requirements.context;
3634
+ if (context !== void 0 && typeof context !== "string") {
3635
+ throw new Error("requirements.context must be a string when provided");
3636
+ }
3637
+ const normalizedContext = typeof context === "string" ? context.trim() : void 0;
3638
+ return {
3639
+ prompt: prompt.trim(),
3640
+ context: normalizedContext && normalizedContext.length > 0 ? normalizedContext : void 0
3641
+ };
3642
+ }
3643
+ };
3644
+
3405
3645
  // src/types.ts
3406
3646
  var JobStatus = /* @__PURE__ */ ((JobStatus2) => {
3407
3647
  JobStatus2[JobStatus2["Created"] = 0] = "Created";
@@ -3634,7 +3874,7 @@ var IndexerClientError = class extends Error {
3634
3874
  this.body = options.body;
3635
3875
  }
3636
3876
  };
3637
- function isRecord2(value) {
3877
+ function isRecord3(value) {
3638
3878
  return typeof value === "object" && value !== null;
3639
3879
  }
3640
3880
  function toIndexerAgent(raw) {
@@ -3823,7 +4063,7 @@ var IndexerClient = class {
3823
4063
  });
3824
4064
  }
3825
4065
  if (!response.ok) {
3826
- const apiError = isRecord2(payload) ? payload : void 0;
4066
+ const apiError = isRecord3(payload) ? payload : void 0;
3827
4067
  const message = response.status === 404 && notFoundMessage ? notFoundMessage : apiError?.error ?? apiError?.message ?? `Indexer request failed (${response.status})`;
3828
4068
  throw new IndexerClientError(message, {
3829
4069
  url,
@@ -3914,7 +4154,6 @@ var ProviderRuntime = class {
3914
4154
  this.processedJobs.add(deliverKey);
3915
4155
  await deployDeliverable(
3916
4156
  this.client,
3917
- this.agentId,
3918
4157
  BigInt(job.jobId),
3919
4158
  { ...params, jobId: BigInt(job.jobId) },
3920
4159
  this.indexer["baseUrl"]
@@ -4049,7 +4288,6 @@ var BuyerRuntime = class {
4049
4288
  this.processedJobs.add(deliveredKey);
4050
4289
  try {
4051
4290
  const deliverable = await readDeliverable(
4052
- this.client,
4053
4291
  BigInt(job.jobId),
4054
4292
  this.indexer["baseUrl"]
4055
4293
  );
@@ -4271,7 +4509,6 @@ var HandlerProviderRuntime = class {
4271
4509
  };
4272
4510
  await deployDeliverable(
4273
4511
  this.client,
4274
- this.agentId,
4275
4512
  BigInt(job.jobId),
4276
4513
  deliverableParams,
4277
4514
  this.indexerUrl
@@ -4351,11 +4588,21 @@ var HandlerProviderRuntime = class {
4351
4588
  if (schemaUri.startsWith("data:")) {
4352
4589
  schemaPayload = this.parseDataUriJson(schemaUri);
4353
4590
  } else if (schemaUri.startsWith("http://") || schemaUri.startsWith("https://")) {
4354
- const response = await fetch(schemaUri);
4355
- if (!response.ok) {
4356
- throw new Error(`Failed to fetch requirements schema URI (${response.status} ${response.statusText})`);
4591
+ const controller = new AbortController();
4592
+ const timeoutId = setTimeout(() => controller.abort(), 3e4);
4593
+ try {
4594
+ const response = await fetch(schemaUri, { signal: controller.signal });
4595
+ if (!response.ok) {
4596
+ throw new Error(`Failed to fetch requirements schema URI (${response.status} ${response.statusText})`);
4597
+ }
4598
+ const buf = await response.arrayBuffer();
4599
+ if (buf.byteLength > 1048576) {
4600
+ throw new Error(`Schema too large (${buf.byteLength} bytes). Limit is 1MB`);
4601
+ }
4602
+ schemaPayload = JSON.parse(new TextDecoder().decode(buf));
4603
+ } finally {
4604
+ clearTimeout(timeoutId);
4357
4605
  }
4358
- schemaPayload = await response.json();
4359
4606
  } else if (schemaUri.trim().startsWith("{")) {
4360
4607
  schemaPayload = JSON.parse(schemaUri);
4361
4608
  } else {
@@ -5781,6 +6028,7 @@ export {
5781
6028
  MEMO_TYPES,
5782
6029
  PLATFORM_BUYER_AGENT_ID,
5783
6030
  PULSE_DOMAIN,
6031
+ PromptHandler,
5784
6032
  ProviderRuntime,
5785
6033
  RISK_POOL_BPS,
5786
6034
  ServiceType,
@@ -5844,6 +6092,7 @@ export {
5844
6092
  submitDeliverable,
5845
6093
  testnetERC8004,
5846
6094
  updateOffering,
6095
+ updateOfferingSchema,
5847
6096
  validateAgainstSchema,
5848
6097
  verifyContentHash
5849
6098
  };