@oneshot-agent/sdk 0.44.0 → 0.47.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/index.js CHANGED
@@ -37,6 +37,8 @@ var __importStar = (this && this.__importStar) || (function () {
37
37
  })();
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.OneShot = exports.executeSwap = exports.getSwapQuote = exports.ReadOnlyWalletProvider = exports.CdpWalletProvider = exports.EthersWalletProvider = void 0;
40
+ const hunts_1 = require("./hunts");
41
+ __exportStar(require("./hunts"), exports);
40
42
  const physical_mail_1 = require("./physical-mail");
41
43
  __exportStar(require("./physical-mail"), exports);
42
44
  __exportStar(require("./approvals"), exports);
@@ -57,39 +59,17 @@ Object.defineProperty(exports, "getSwapQuote", { enumerable: true, get: function
57
59
  Object.defineProperty(exports, "executeSwap", { enumerable: true, get: function () { return swap_1.executeSwap; } });
58
60
  __exportStar(require("./errors"), exports);
59
61
  const approvals_1 = require("./approvals");
60
- // Receipt verification (`canonicalizeReceipt`, `verifyReceipt`,
61
- // `receiptFromWire`, and their supporting types `SignableReceipt`,
62
- // `ReceiptSignatureFields`, `ReceiptJwk`, `ReceiptJwks`,
63
- // `ReceiptVerificationResult`, `ReceiptVerificationFailureReason`) is
64
- // intentionally NOT re-exported here, values OR types. `./receipt`
65
- // statically imports `node:crypto`, and this file is the SDK's main entry —
66
- // re-exporting its values would give every consumer (including browser/edge
67
- // bundles, which this file otherwise avoids requiring Node builtins for;
68
- // see the deliberate `btoa` fallback below) a hard Node-only dependency
69
- // with no way to opt out. Import from the `@oneshot-agent/sdk/receipt`
70
- // subpath instead (see package.json `exports` and the README's
71
- // "Verifying Receipts" section).
72
- //
73
- // Types alone erase at compile time and carry no runtime import, so a
74
- // type-only re-export here would be runtime-safe — but `SignableReceipt`
75
- // declares `providerCost` (libs/agent-sdk/src/receipt.ts), the field whose
76
- // removal from the public SDK surface `tests/unit/sdk-provider-cost-removed
77
- // .test.ts` guards. Re-exporting it from the main entry would put it back
78
- // on the surface that guard exists to keep clean, just via the type system
79
- // instead of a runtime value. `providerCost` must stay inside
80
- // `SignableReceipt` itself (it's part of what the signer actually signs —
81
- // see `canonicalizeReceipt`), so the fix is not exposing that type here,
82
- // not removing the field. Import `SignableReceipt` from the `./receipt`
83
- // subpath directly if you need it.
62
+ // `./receipt` is NOT re-exported here, values or types: it statically imports
63
+ // `node:crypto`, which would force a hard Node dependency on every consumer
64
+ // including browser bundles; and its `SignableReceipt.providerCost` field must
65
+ // stay off this public surface (see tests/unit/sdk-provider-cost-removed.test.ts).
66
+ // Import from the `@oneshot-agent/sdk/receipt` subpath instead.
84
67
  // Keep in sync with package.json `version`. Guarded by version.test.ts.
85
- const SDK_VERSION = '0.44.0';
68
+ const SDK_VERSION = '0.47.0';
86
69
  /** HTTP poll cadence while push is unconfirmed: fast first checks, settling at 2s. */
87
70
  const HTTP_POLL_BACKOFF_MS = [300, 600, 1000, 2000];
88
71
  /** HTTP poll cadence once the WebSocket has delivered for this request. */
89
72
  const HTTP_POLL_RELAXED_MS = 5000;
90
- // ============================================================================
91
- // Environment Configuration
92
- // ============================================================================
93
73
  const BASE_URL = 'https://win.oneshotagent.com';
94
74
  const RPC_URL = 'https://mainnet.base.org';
95
75
  const CHAIN_ID = 8453;
@@ -122,16 +102,7 @@ function validateSwapBufferMultiplier(m) {
122
102
  }
123
103
  return m;
124
104
  }
125
- // ============================================================================
126
- // Public types — defined in ./types.ts. Re-exported below so existing
127
- // consumer imports (`import { EmailToolOptions, ... } from '@oneshot-agent/sdk'`)
128
- // keep resolving unchanged. The OneShot class below pulls the names it needs
129
- // for internal use via the import block.
130
- // ============================================================================
131
105
  __exportStar(require("./types"), exports);
132
- // ============================================================================
133
- // OneShot SDK
134
- // ============================================================================
135
106
  /**
136
107
  * OneShot Agent SDK - Execute commercial transactions with automatic x402 payments.
137
108
  *
@@ -218,6 +189,7 @@ class OneShot {
218
189
  * For CDP wallets, use OneShot.create() instead.
219
190
  */
220
191
  constructor(config, walletProvider) {
192
+ this.hunts = new hunts_1.Hunts(this);
221
193
  this.physicalMail = new physical_mail_1.PhysicalMail(async (path, method, body, mime) => {
222
194
  const response = await fetch(`${this.baseUrl}/v1/tools/physical-mail${path}`, {
223
195
  method, headers: { ...await this.signedReadHeaders(method === 'GET' ? 'read' : 'write'), 'Content-Type': mime ?? 'application/json' },
@@ -239,6 +211,7 @@ class OneShot {
239
211
  /** ETH mode: serializes read → decide → swap → reserve per instance (also prevents concurrent swap nonce races). */
240
212
  this._usdcLock = Promise.resolve();
241
213
  this.baseUrl = config.baseUrl ?? BASE_URL;
214
+ this.huntUrl = config.huntUrl;
242
215
  this.debug = config.debug ?? false;
243
216
  this.logger = config.logger ?? console.log;
244
217
  this._currency = config.currency ?? 'USDC';
@@ -294,9 +267,6 @@ class OneShot {
294
267
  this.log(`SDK initialized — chain=${CHAIN_ID} currency=${this._currency}`);
295
268
  }
296
269
  }
297
- // ---------------------------------------------------------------------------
298
- // Public getters
299
- // ---------------------------------------------------------------------------
300
270
  get address() {
301
271
  return this.provider.address;
302
272
  }
@@ -320,9 +290,6 @@ class OneShot {
320
290
  get budgetConfig() {
321
291
  return this._budgets;
322
292
  }
323
- // ---------------------------------------------------------------------------
324
- // Public methods
325
- // ---------------------------------------------------------------------------
326
293
  async tool(toolName, options) {
327
294
  return this.executeToolRequest(`/v1/tools/${toolName}`, options);
328
295
  }
@@ -780,6 +747,8 @@ class OneShot {
780
747
  payload.source_url = options.source_url;
781
748
  if (options.sections)
782
749
  payload.sections = options.sections;
750
+ if (options.pages?.length)
751
+ payload.pages = options.pages;
783
752
  if (options.lead_capture)
784
753
  payload.lead_capture = options.lead_capture;
785
754
  if (options.brand)
@@ -790,18 +759,40 @@ class OneShot {
790
759
  payload.domain = options.domain;
791
760
  if (options.build_id)
792
761
  payload.build_id = options.build_id;
762
+ return this.submitBuild(payload, options);
763
+ }
764
+ /**
765
+ * Apply natural-language changes to one of your builds. The site's existing
766
+ * code is edited (not regenerated) and redeployed to the same URL.
767
+ *
768
+ * @example
769
+ * ```typescript
770
+ * const result = await agent.refineBuild({
771
+ * build_id: previous.request_id,
772
+ * changes: 'Make the hero darker and add an FAQ page at /faq',
773
+ * });
774
+ * ```
775
+ */
776
+ async refineBuild(options) {
777
+ this.validate(options.build_id, 'build_id');
778
+ this.validate(options.changes, 'changes');
779
+ return this.submitBuild({ build_id: options.build_id, changes: options.changes }, options);
780
+ }
781
+ async submitBuild(payload, options) {
793
782
  const { execResp: buildResp } = await this.runQuoteToPay({
794
783
  endpoint: '/v1/tools/build',
795
784
  payload,
796
785
  signal: options.signal,
797
786
  maxCost: options.maxCost,
787
+ approvalId: options.approvalId,
798
788
  // Build analysis can be slow server-side; bound the quote leg client-side.
799
789
  quoteTimeoutMs: 120000,
800
790
  expectMsg: 'Expected 402 for quote',
801
791
  totalOf: (ctx) => ctx.pricing.total,
802
792
  onQuote: (ctx) => {
803
793
  this.log(`Build quote: $${ctx.pricing.total} for "${ctx.product_name}"`);
804
- this.log(`Type: ${ctx.analysis.inferred_type}, Sections: ${ctx.analysis.estimated_sections}`);
794
+ if (!ctx.is_refine)
795
+ this.log(`Type: ${ctx.analysis.inferred_type}, Sections: ${ctx.analysis.estimated_sections}`);
805
796
  },
806
797
  on400: async (resp) => {
807
798
  const errorData = await resp.json();
@@ -964,13 +955,6 @@ class OneShot {
964
955
  throw new errors_2.ToolError('Failed to delete browser profile', response.status, await response.text());
965
956
  }
966
957
  }
967
- // ── LinkedIn — messaging through a human-connected account (issue #756) ──
968
- //
969
- // The human connects THEIR OWN LinkedIn account through a hosted login link
970
- // and grants specific actions. Connection/reads are free (signed proof);
971
- // sync, reply, profile view and react are paid fixed-price tools. Every
972
- // write is idempotency-keyed automatically — a message LinkedIn accepted
973
- // cannot be recalled.
974
958
  async linkedinFree(method, path, opts) {
975
959
  const url = new URL(`${this.baseUrl}/v1/tools/linkedin${path}`);
976
960
  for (const [k, v] of Object.entries(opts.query ?? {}))
@@ -1147,9 +1131,6 @@ class OneShot {
1147
1131
  }
1148
1132
  return response.json();
1149
1133
  }
1150
- // ---------------------------------------------------------------------------
1151
- // Inbound voice — the agent's number answers its own calls
1152
- // ---------------------------------------------------------------------------
1153
1134
  /**
1154
1135
  * Get this agent a voice number without placing a call. Returns the existing
1155
1136
  * active number for free; otherwise buys one and charges the one-time phone
@@ -1337,9 +1318,6 @@ class OneShot {
1337
1318
  ]);
1338
1319
  return ethers_1.ethers.formatUnits(balance, decimals);
1339
1320
  }
1340
- // ---------------------------------------------------------------------------
1341
- // Compute methods
1342
- // ---------------------------------------------------------------------------
1343
1321
  /**
1344
1322
  * Create a compute goal — the orchestrator will plan, execute, and iterate autonomously.
1345
1323
  *
@@ -1671,9 +1649,6 @@ class OneShot {
1671
1649
  const json = await resp.json();
1672
1650
  return json.data;
1673
1651
  }
1674
- // ---------------------------------------------------------------------------
1675
- // Analytics methods
1676
- // ---------------------------------------------------------------------------
1677
1652
  /**
1678
1653
  * Get spend breakdown by category
1679
1654
  *
@@ -1831,9 +1806,6 @@ class OneShot {
1831
1806
  }
1832
1807
  return response.json();
1833
1808
  }
1834
- // ---------------------------------------------------------------------------
1835
- // Private helpers
1836
- // ---------------------------------------------------------------------------
1837
1809
  log(msg) {
1838
1810
  if (this.debug)
1839
1811
  this.logger(`[OneShot] ${msg}`);
@@ -1898,7 +1870,7 @@ class OneShot {
1898
1870
  * locally. A fresh nonce per call prevents replay. Signing failure falls back
1899
1871
  * to plain headers, with a one-time warning.
1900
1872
  */
1901
- async signedReadHeaders(scope = 'read') {
1873
+ async signedReadHeaders(scope = 'read', domainName = 'OneShot Agent Auth') {
1902
1874
  const base = this.headers();
1903
1875
  // The bearer token already binds the request to the agent (and is
1904
1876
  // revocable); the API accepts it in place of the signed proof.
@@ -1908,7 +1880,14 @@ class OneShot {
1908
1880
  const agent = this.provider.address;
1909
1881
  const issuedAt = Math.floor(Date.now() / 1000);
1910
1882
  const nonce = ethers_1.ethers.hexlify(ethers_1.ethers.randomBytes(32));
1911
- const signature = await this.provider.signTypedData({ name: 'OneShot Agent Auth', version: '1' }, {
1883
+ const signature = await this.provider.signTypedData(
1884
+ // `domainName` lets a different origin (e.g. Soul Hunt, which keeps
1885
+ // its own nonce store — see hunts.ts) use a DIFFERENT EIP-712 domain
1886
+ // than api-service's. EIP-712 mixes the domain into the signed hash,
1887
+ // so a proof is only valid for the one origin it was signed for and
1888
+ // can't be replayed across service boundaries (security finding
1889
+ // F-t_d4805d6f-3, round 2).
1890
+ { name: domainName, version: '1' }, {
1912
1891
  AgentReadAuth: [
1913
1892
  { name: 'agent', type: 'address' },
1914
1893
  { name: 'scope', type: 'string' },
@@ -2051,9 +2030,6 @@ class OneShot {
2051
2030
  const body = await response.json();
2052
2031
  return (body.data ?? body);
2053
2032
  }
2054
- // ---------------------------------------------------------------------------
2055
- // Access tokens (wallet sessions only)
2056
- // ---------------------------------------------------------------------------
2057
2033
  assertWalletSession(action) {
2058
2034
  if (this._accessToken) {
2059
2035
  throw new errors_2.ValidationError(`Access tokens cannot ${action}; use a wallet session`, 'accessToken');
@@ -2936,9 +2912,6 @@ class OneShot {
2936
2912
  throw new errors_2.OneShotError('Operation cancelled before payment');
2937
2913
  }
2938
2914
  }
2939
- // ---------------------------------------------------------------------------
2940
- // ETH-currency mode: USDC ledger + buffered swaps
2941
- // ---------------------------------------------------------------------------
2942
2915
  /**
2943
2916
  * ETH mode only. Make sure the wallet's *effective* USDC (on-chain balance
2944
2917
  * minus payments signed but not yet settled) covers this charge, swapping
@@ -2977,7 +2950,7 @@ class OneShot {
2977
2950
  return this.reserveUsdc(charge);
2978
2951
  });
2979
2952
  }
2980
- /** ETH mode is Base-mainnet-only (that is where the Uniswap route lives); fail clearly before any RPC. */
2953
+ /** ETH mode is Base-mainnet-only; fail clearly before any RPC. */
2981
2954
  assertEthModeSupported(paymentInfo) {
2982
2955
  const chainId = chainIdFromNetwork(paymentInfo.network) ?? CHAIN_ID;
2983
2956
  if (chainId !== CHAIN_ID) {
@@ -2995,7 +2968,7 @@ class OneShot {
2995
2968
  this._usdcLock = run.then(() => undefined, () => undefined);
2996
2969
  return run;
2997
2970
  }
2998
- /** On-chain USDC balance (atomic units), deduped within one block. Overridable in tests. */
2971
+ /** On-chain USDC balance (atomic units), deduped within one block. */
2999
2972
  async readUsdcBalance(usdcAddress) {
3000
2973
  const cached = this._usdcBalanceCache;
3001
2974
  if (cached && Date.now() - cached.at < USDC_BALANCE_CACHE_MS)
@@ -3057,13 +3030,13 @@ class OneShot {
3057
3030
  }
3058
3031
  return amount;
3059
3032
  }
3060
- /** Max ETH the buffered swap could cost (quote), or undefined if unavailable. Overridable in tests. */
3033
+ /** Max ETH the buffered swap could cost (quote), or undefined if unavailable. */
3061
3034
  async quoteSwapAmountInMax(usdcAmount, chainId) {
3062
3035
  const { getSwapQuote } = await Promise.resolve().then(() => __importStar(require('./swap')));
3063
3036
  const quote = await getSwapQuote(this.rpcProvider, usdcAmount, chainId, this._slippage);
3064
3037
  return quote?.amountInMax;
3065
3038
  }
3066
- /** Perform the on-chain swap. Overridable in tests. */
3039
+ /** Perform the on-chain swap. */
3067
3040
  async executeUsdcSwap(usdcAmount, chainId) {
3068
3041
  const { executeSwap } = await Promise.resolve().then(() => __importStar(require('./swap')));
3069
3042
  return executeSwap(this.provider, this.rpcProvider, usdcAmount, chainId, this._slippage);