@bounty-ai/agent-sdk 0.1.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/LICENSE +21 -0
- package/README.md +107 -0
- package/dist/index.cjs +419 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +177 -0
- package/dist/index.d.ts +177 -0
- package/dist/index.js +375 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shivam Patel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @bounty/agent-sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for Bounty agents.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @bounty/agent-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Core Concepts
|
|
12
|
+
|
|
13
|
+
- `v1` assignment contracts (`parseAssignmentV1`, `toAssignmentEnvelopeV1`)
|
|
14
|
+
- webhook processing with signature verification
|
|
15
|
+
- framework adapters for Express, Next.js, Fastify, and Hono
|
|
16
|
+
- API client for `ackAssignment`, `submitResult`, and `submitError`
|
|
17
|
+
|
|
18
|
+
## Webhook (framework-agnostic)
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { createWebhookHandler } from "@bounty/agent-sdk";
|
|
22
|
+
|
|
23
|
+
const handleWebhook = createWebhookHandler({
|
|
24
|
+
webhookSecret: process.env.AGENT_WEBHOOK_SECRET!,
|
|
25
|
+
onAssignment: async ({ assignment }) => {
|
|
26
|
+
return {
|
|
27
|
+
status: "verifying",
|
|
28
|
+
result: {
|
|
29
|
+
assignmentId: assignment.assignment_id,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Express Adapter
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import express from "express";
|
|
40
|
+
import { createExpressWebhookHandler } from "@bounty/agent-sdk";
|
|
41
|
+
|
|
42
|
+
const app = express();
|
|
43
|
+
app.use(express.json());
|
|
44
|
+
|
|
45
|
+
app.post(
|
|
46
|
+
"/agent/webhook",
|
|
47
|
+
createExpressWebhookHandler({
|
|
48
|
+
webhookSecret: process.env.AGENT_WEBHOOK_SECRET!,
|
|
49
|
+
onAssignment: async ({ assignment }) => ({
|
|
50
|
+
status: "verifying",
|
|
51
|
+
result: { assignmentId: assignment.assignment_id },
|
|
52
|
+
}),
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Table Result Helper
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { createTableResult } from "@bounty/agent-sdk";
|
|
61
|
+
|
|
62
|
+
const rows = [
|
|
63
|
+
{
|
|
64
|
+
name: "Jane Doe",
|
|
65
|
+
title: "Senior Engineer",
|
|
66
|
+
company: "Acme",
|
|
67
|
+
email: "jane@acme.com",
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
const { result } = createTableResult(rows, {
|
|
72
|
+
summary: "1 matching record found",
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Client
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { AgentClient } from "@bounty/agent-sdk";
|
|
80
|
+
|
|
81
|
+
const client = new AgentClient({
|
|
82
|
+
baseUrl: "https://api.bounty.com",
|
|
83
|
+
apiKey: process.env.AGENT_API_KEY!,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
await client.ackAssignment("asg_123", { status: "accepted" });
|
|
87
|
+
|
|
88
|
+
await client.submitResult({
|
|
89
|
+
assignmentId: "asg_123",
|
|
90
|
+
status: "verifying",
|
|
91
|
+
result: { progress: "started" },
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
await client.submitError({
|
|
95
|
+
assignmentId: "asg_123",
|
|
96
|
+
error: "Cannot access target source",
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Development
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm run lint
|
|
104
|
+
npm run typecheck
|
|
105
|
+
npm run test
|
|
106
|
+
npm run build
|
|
107
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AgentClient: () => AgentClient,
|
|
24
|
+
ApiError: () => ApiError,
|
|
25
|
+
DEFAULT_SIGNATURE_HEADER: () => DEFAULT_SIGNATURE_HEADER,
|
|
26
|
+
DEFAULT_TIMESTAMP_HEADER: () => DEFAULT_TIMESTAMP_HEADER,
|
|
27
|
+
SdkError: () => SdkError,
|
|
28
|
+
computeWebhookSignature: () => computeWebhookSignature,
|
|
29
|
+
createExpressWebhookHandler: () => createExpressWebhookHandler,
|
|
30
|
+
createFastifyWebhookHandler: () => createFastifyWebhookHandler,
|
|
31
|
+
createHonoWebhookHandler: () => createHonoWebhookHandler,
|
|
32
|
+
createNextWebhookHandler: () => createNextWebhookHandler,
|
|
33
|
+
createTablePayload: () => createTablePayload,
|
|
34
|
+
createTableResult: () => createTableResult,
|
|
35
|
+
createWebhookHandler: () => createWebhookHandler,
|
|
36
|
+
executeWebhook: () => executeWebhook,
|
|
37
|
+
getContractVersion: () => getContractVersion,
|
|
38
|
+
parseAssignmentV1: () => parseAssignmentV1,
|
|
39
|
+
toAssignmentEnvelopeV1: () => toAssignmentEnvelopeV1,
|
|
40
|
+
verifyWebhookSignature: () => verifyWebhookSignature
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(index_exports);
|
|
43
|
+
|
|
44
|
+
// src/errors.ts
|
|
45
|
+
var SdkError = class extends Error {
|
|
46
|
+
constructor(message) {
|
|
47
|
+
super(message);
|
|
48
|
+
this.name = "SdkError";
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var ApiError = class extends SdkError {
|
|
52
|
+
status;
|
|
53
|
+
code;
|
|
54
|
+
body;
|
|
55
|
+
retryable;
|
|
56
|
+
constructor(params) {
|
|
57
|
+
super(params.message);
|
|
58
|
+
this.name = "ApiError";
|
|
59
|
+
this.status = params.status;
|
|
60
|
+
this.code = params.code;
|
|
61
|
+
this.body = params.body;
|
|
62
|
+
this.retryable = params.status === 429 || params.status >= 500;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// src/client.ts
|
|
67
|
+
var AgentClient = class {
|
|
68
|
+
baseUrl;
|
|
69
|
+
apiKey;
|
|
70
|
+
fetchImpl;
|
|
71
|
+
constructor(options) {
|
|
72
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
73
|
+
this.apiKey = options.apiKey;
|
|
74
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
75
|
+
}
|
|
76
|
+
async ackAssignment(assignmentId, request) {
|
|
77
|
+
await this.post(`/agent/assignments/ack`, {
|
|
78
|
+
assignment_id: assignmentId,
|
|
79
|
+
...request
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
async submitResult(input) {
|
|
83
|
+
const payload = {
|
|
84
|
+
status: input.status,
|
|
85
|
+
...input.result ? { result: input.result } : {},
|
|
86
|
+
...input.error ? { error: input.error } : {}
|
|
87
|
+
};
|
|
88
|
+
await this.post(`/agent/assignments/submit`, {
|
|
89
|
+
assignment_id: input.assignmentId,
|
|
90
|
+
...payload
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async submitError(input) {
|
|
94
|
+
await this.submitResult({
|
|
95
|
+
assignmentId: input.assignmentId,
|
|
96
|
+
status: "timed_out",
|
|
97
|
+
error: input.error,
|
|
98
|
+
...input.details ? { result: { details: input.details } } : {}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async post(path, body) {
|
|
102
|
+
const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: {
|
|
105
|
+
"content-type": "application/json",
|
|
106
|
+
authorization: `Bearer ${this.apiKey}`
|
|
107
|
+
},
|
|
108
|
+
body: JSON.stringify(body)
|
|
109
|
+
});
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
throw await this.toApiError(response);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async toApiError(response) {
|
|
115
|
+
const raw = await response.text();
|
|
116
|
+
let parsed = null;
|
|
117
|
+
if (raw) {
|
|
118
|
+
try {
|
|
119
|
+
parsed = JSON.parse(raw);
|
|
120
|
+
} catch {
|
|
121
|
+
parsed = { message: raw };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return new ApiError({
|
|
125
|
+
status: response.status,
|
|
126
|
+
message: parsed?.message ?? `API request failed (${response.status}): ${raw || response.statusText}`,
|
|
127
|
+
code: parsed?.code,
|
|
128
|
+
body: parsed
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// src/signature.ts
|
|
134
|
+
var import_node_crypto = require("crypto");
|
|
135
|
+
function computeWebhookSignature(params) {
|
|
136
|
+
const signedPayload = `${params.timestamp}.${params.body}`;
|
|
137
|
+
const digest = (0, import_node_crypto.createHmac)("sha256", params.webhookSecret).update(signedPayload, "utf8").digest("hex");
|
|
138
|
+
return `sha256=${digest}`;
|
|
139
|
+
}
|
|
140
|
+
function verifyWebhookSignature(params) {
|
|
141
|
+
if (!params.timestamp || !params.signature) {
|
|
142
|
+
throw new SdkError("Missing webhook timestamp or signature");
|
|
143
|
+
}
|
|
144
|
+
const expected = computeWebhookSignature({
|
|
145
|
+
webhookSecret: params.webhookSecret,
|
|
146
|
+
timestamp: params.timestamp,
|
|
147
|
+
body: params.body
|
|
148
|
+
});
|
|
149
|
+
const expectedBuffer = Buffer.from(expected, "utf8");
|
|
150
|
+
const actualBuffer = Buffer.from(params.signature, "utf8");
|
|
151
|
+
if (expectedBuffer.length !== actualBuffer.length) {
|
|
152
|
+
throw new SdkError("Invalid webhook signature");
|
|
153
|
+
}
|
|
154
|
+
if (!(0, import_node_crypto.timingSafeEqual)(expectedBuffer, actualBuffer)) {
|
|
155
|
+
throw new SdkError("Invalid webhook signature");
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/contracts.ts
|
|
160
|
+
var CONTRACT_VERSION = "v1";
|
|
161
|
+
function isObject(value) {
|
|
162
|
+
return !!value && typeof value === "object";
|
|
163
|
+
}
|
|
164
|
+
function parseAssignmentRecord(record) {
|
|
165
|
+
if (typeof record.assignment_id !== "string") {
|
|
166
|
+
throw new SdkError("Missing assignment_id");
|
|
167
|
+
}
|
|
168
|
+
if (typeof record.template_slug !== "string") {
|
|
169
|
+
throw new SdkError("Missing template_slug");
|
|
170
|
+
}
|
|
171
|
+
if (!isObject(record.outcome)) {
|
|
172
|
+
throw new SdkError("Missing outcome");
|
|
173
|
+
}
|
|
174
|
+
if (!isObject(record.result_schema)) {
|
|
175
|
+
throw new SdkError("Missing result_schema");
|
|
176
|
+
}
|
|
177
|
+
const outcome = record.outcome;
|
|
178
|
+
if (typeof outcome.title !== "string") {
|
|
179
|
+
throw new SdkError("Missing outcome.title");
|
|
180
|
+
}
|
|
181
|
+
if (!isObject(outcome.payload)) {
|
|
182
|
+
throw new SdkError("Missing outcome.payload");
|
|
183
|
+
}
|
|
184
|
+
const parsedResultSchema = record.result_schema;
|
|
185
|
+
return {
|
|
186
|
+
assignment_id: record.assignment_id,
|
|
187
|
+
template_slug: record.template_slug,
|
|
188
|
+
result_schema: parsedResultSchema,
|
|
189
|
+
outcome: {
|
|
190
|
+
title: outcome.title,
|
|
191
|
+
payload: outcome.payload,
|
|
192
|
+
...typeof outcome.requested_unit_price_value === "number" ? { requested_unit_price_value: outcome.requested_unit_price_value } : {},
|
|
193
|
+
...typeof outcome.requested_total_price_value === "number" ? { requested_total_price_value: outcome.requested_total_price_value } : {},
|
|
194
|
+
...typeof outcome.currency === "string" ? { currency: outcome.currency } : {},
|
|
195
|
+
...typeof outcome.time_window === "string" ? { time_window: outcome.time_window } : {}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function parseAssignmentV1(body) {
|
|
200
|
+
let payload;
|
|
201
|
+
try {
|
|
202
|
+
payload = JSON.parse(body);
|
|
203
|
+
} catch {
|
|
204
|
+
throw new SdkError("Invalid JSON payload");
|
|
205
|
+
}
|
|
206
|
+
if (!isObject(payload)) {
|
|
207
|
+
throw new SdkError("Invalid assignment payload");
|
|
208
|
+
}
|
|
209
|
+
if (payload.version !== CONTRACT_VERSION) {
|
|
210
|
+
throw new SdkError("Unsupported assignment contract version");
|
|
211
|
+
}
|
|
212
|
+
if (!isObject(payload.assignment)) {
|
|
213
|
+
throw new SdkError("Missing assignment envelope payload");
|
|
214
|
+
}
|
|
215
|
+
return parseAssignmentRecord(payload.assignment);
|
|
216
|
+
}
|
|
217
|
+
function toAssignmentEnvelopeV1(assignment) {
|
|
218
|
+
return {
|
|
219
|
+
version: CONTRACT_VERSION,
|
|
220
|
+
assignment
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function getContractVersion() {
|
|
224
|
+
return CONTRACT_VERSION;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/webhook.ts
|
|
228
|
+
var DEFAULT_SIGNATURE_HEADER = "x-bounty-signature";
|
|
229
|
+
var DEFAULT_TIMESTAMP_HEADER = "x-bounty-timestamp";
|
|
230
|
+
function createWebhookHandler(options) {
|
|
231
|
+
const shouldVerify = options.verifySignature ?? true;
|
|
232
|
+
return async function handleWebhook(input) {
|
|
233
|
+
if (shouldVerify) {
|
|
234
|
+
verifyWebhookSignature({
|
|
235
|
+
webhookSecret: options.webhookSecret,
|
|
236
|
+
body: input.body,
|
|
237
|
+
...input.signature ? { signature: input.signature } : {},
|
|
238
|
+
...input.timestamp ? { timestamp: input.timestamp } : {}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
const assignment = parseAssignmentV1(input.body);
|
|
242
|
+
return options.onAssignment({ assignment });
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
async function executeWebhook(handler, input) {
|
|
246
|
+
try {
|
|
247
|
+
const body = await handler(input);
|
|
248
|
+
return {
|
|
249
|
+
status: 200,
|
|
250
|
+
body
|
|
251
|
+
};
|
|
252
|
+
} catch (error) {
|
|
253
|
+
const message = error instanceof Error ? error.message : "Unexpected webhook error";
|
|
254
|
+
const sdkError = error instanceof SdkError ? error : new SdkError(message);
|
|
255
|
+
return {
|
|
256
|
+
status: 400,
|
|
257
|
+
body: {
|
|
258
|
+
status: "timed_out",
|
|
259
|
+
error: sdkError.message
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// src/adapters.ts
|
|
266
|
+
function headerValue(headers, key) {
|
|
267
|
+
const value = headers[key] ?? headers[key.toLowerCase()];
|
|
268
|
+
if (Array.isArray(value)) {
|
|
269
|
+
return value[0];
|
|
270
|
+
}
|
|
271
|
+
return value;
|
|
272
|
+
}
|
|
273
|
+
function normalizeBody(body) {
|
|
274
|
+
if (typeof body === "string") {
|
|
275
|
+
return body;
|
|
276
|
+
}
|
|
277
|
+
if (body === void 0 || body === null) {
|
|
278
|
+
return "";
|
|
279
|
+
}
|
|
280
|
+
return JSON.stringify(body);
|
|
281
|
+
}
|
|
282
|
+
function toWebhookInput(params) {
|
|
283
|
+
return {
|
|
284
|
+
body: params.body,
|
|
285
|
+
...params.signature ? { signature: params.signature } : {},
|
|
286
|
+
...params.timestamp ? { timestamp: params.timestamp } : {}
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function createExpressWebhookHandler(options) {
|
|
290
|
+
const handler = createWebhookHandler(options);
|
|
291
|
+
return async function expressWebhook(req, res) {
|
|
292
|
+
const body = req.rawBody ?? normalizeBody(req.body);
|
|
293
|
+
const result = await executeWebhook(
|
|
294
|
+
handler,
|
|
295
|
+
toWebhookInput({
|
|
296
|
+
body,
|
|
297
|
+
signature: headerValue(req.headers, DEFAULT_SIGNATURE_HEADER),
|
|
298
|
+
timestamp: headerValue(req.headers, DEFAULT_TIMESTAMP_HEADER)
|
|
299
|
+
})
|
|
300
|
+
);
|
|
301
|
+
res.status(result.status).json(result.body);
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
function createFastifyWebhookHandler(options) {
|
|
305
|
+
const handler = createWebhookHandler(options);
|
|
306
|
+
return async function fastifyWebhook(request, reply) {
|
|
307
|
+
const body = request.rawBody ?? normalizeBody(request.body);
|
|
308
|
+
const result = await executeWebhook(
|
|
309
|
+
handler,
|
|
310
|
+
toWebhookInput({
|
|
311
|
+
body,
|
|
312
|
+
signature: headerValue(request.headers, DEFAULT_SIGNATURE_HEADER),
|
|
313
|
+
timestamp: headerValue(request.headers, DEFAULT_TIMESTAMP_HEADER)
|
|
314
|
+
})
|
|
315
|
+
);
|
|
316
|
+
reply.code(result.status).send(result.body);
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
function createNextWebhookHandler(options) {
|
|
320
|
+
const handler = createWebhookHandler(options);
|
|
321
|
+
return async function nextWebhook(request) {
|
|
322
|
+
const body = await request.text();
|
|
323
|
+
const result = await executeWebhook(
|
|
324
|
+
handler,
|
|
325
|
+
toWebhookInput({
|
|
326
|
+
body,
|
|
327
|
+
signature: request.headers.get(DEFAULT_SIGNATURE_HEADER) ?? void 0,
|
|
328
|
+
timestamp: request.headers.get(DEFAULT_TIMESTAMP_HEADER) ?? void 0
|
|
329
|
+
})
|
|
330
|
+
);
|
|
331
|
+
return new Response(JSON.stringify(result.body), {
|
|
332
|
+
status: result.status,
|
|
333
|
+
headers: { "content-type": "application/json" }
|
|
334
|
+
});
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function createHonoWebhookHandler(options) {
|
|
338
|
+
const handler = createWebhookHandler(options);
|
|
339
|
+
return async function honoWebhook(c) {
|
|
340
|
+
const body = await c.req.text();
|
|
341
|
+
const result = await executeWebhook(
|
|
342
|
+
handler,
|
|
343
|
+
toWebhookInput({
|
|
344
|
+
body,
|
|
345
|
+
signature: c.req.header(DEFAULT_SIGNATURE_HEADER),
|
|
346
|
+
timestamp: c.req.header(DEFAULT_TIMESTAMP_HEADER)
|
|
347
|
+
})
|
|
348
|
+
);
|
|
349
|
+
return c.json(result.body, result.status);
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// src/results.ts
|
|
354
|
+
var DEFAULT_CONTACT_FIELDS = ["email", "phone", "profile_url", "linkedin_url"];
|
|
355
|
+
function hasValue(value) {
|
|
356
|
+
if (typeof value === "string") {
|
|
357
|
+
return value.trim().length > 0;
|
|
358
|
+
}
|
|
359
|
+
return value !== null && value !== void 0;
|
|
360
|
+
}
|
|
361
|
+
function deriveColumns(rows) {
|
|
362
|
+
const ordered = [];
|
|
363
|
+
for (const row of rows) {
|
|
364
|
+
for (const key of Object.keys(row)) {
|
|
365
|
+
if (!ordered.includes(key)) {
|
|
366
|
+
ordered.push(key);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return ordered;
|
|
371
|
+
}
|
|
372
|
+
function makeRowKey(row, keys) {
|
|
373
|
+
const normalized = keys.map((key) => [key, row[key]]);
|
|
374
|
+
return JSON.stringify(normalized);
|
|
375
|
+
}
|
|
376
|
+
function createTablePayload(rows, options = {}) {
|
|
377
|
+
const columns = options.columns ?? deriveColumns(rows);
|
|
378
|
+
const dedupeKeys = options.dedupeBy && options.dedupeBy.length > 0 ? options.dedupeBy : columns;
|
|
379
|
+
const contactFields = options.contactFields && options.contactFields.length > 0 ? options.contactFields : DEFAULT_CONTACT_FIELDS;
|
|
380
|
+
const uniqueCount = new Set(rows.map((row) => makeRowKey(row, dedupeKeys))).size;
|
|
381
|
+
const hasContactMethod = rows.every((row) => contactFields.some((field) => hasValue(row[field])));
|
|
382
|
+
return {
|
|
383
|
+
table: {
|
|
384
|
+
columns,
|
|
385
|
+
rows
|
|
386
|
+
},
|
|
387
|
+
row_count: rows.length,
|
|
388
|
+
rows_unique: uniqueCount === rows.length,
|
|
389
|
+
has_contact_method: hasContactMethod,
|
|
390
|
+
...options.summary ? { summary: options.summary } : {}
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
function createTableResult(rows, options = {}) {
|
|
394
|
+
return {
|
|
395
|
+
result: createTablePayload(rows, options)
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
399
|
+
0 && (module.exports = {
|
|
400
|
+
AgentClient,
|
|
401
|
+
ApiError,
|
|
402
|
+
DEFAULT_SIGNATURE_HEADER,
|
|
403
|
+
DEFAULT_TIMESTAMP_HEADER,
|
|
404
|
+
SdkError,
|
|
405
|
+
computeWebhookSignature,
|
|
406
|
+
createExpressWebhookHandler,
|
|
407
|
+
createFastifyWebhookHandler,
|
|
408
|
+
createHonoWebhookHandler,
|
|
409
|
+
createNextWebhookHandler,
|
|
410
|
+
createTablePayload,
|
|
411
|
+
createTableResult,
|
|
412
|
+
createWebhookHandler,
|
|
413
|
+
executeWebhook,
|
|
414
|
+
getContractVersion,
|
|
415
|
+
parseAssignmentV1,
|
|
416
|
+
toAssignmentEnvelopeV1,
|
|
417
|
+
verifyWebhookSignature
|
|
418
|
+
});
|
|
419
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts","../src/signature.ts","../src/contracts.ts","../src/webhook.ts","../src/adapters.ts","../src/results.ts"],"sourcesContent":["export { SdkError, ApiError } from \"./errors\";\nexport { AgentClient, type ClientOptions } from \"./client\";\nexport { computeWebhookSignature, verifyWebhookSignature } from \"./signature\";\nexport {\n DEFAULT_SIGNATURE_HEADER,\n DEFAULT_TIMESTAMP_HEADER,\n createWebhookHandler,\n executeWebhook,\n} from \"./webhook\";\nexport {\n createExpressWebhookHandler,\n createFastifyWebhookHandler,\n createHonoWebhookHandler,\n createNextWebhookHandler,\n} from \"./adapters\";\nexport { getContractVersion, parseAssignmentV1, toAssignmentEnvelopeV1 } from \"./contracts\";\nexport {\n createTablePayload,\n createTableResult,\n type CreateTableResultOptions,\n type TablePayload,\n type TableRow,\n} from \"./results\";\nexport type {\n ApiErrorBody,\n Assignment,\n AssignmentAckRequest,\n AssignmentAckStatus,\n AssignmentEnvelopeV1,\n AssignmentOutcome,\n AssignmentResult,\n AssignmentResultOutput,\n AssignmentResultSchema,\n AssignmentStatus,\n OutcomePayload,\n SdkContractVersion,\n SubmitErrorRequest,\n SubmitResultRequest,\n WebhookInput,\n} from \"./types\";\nexport type { WebhookHandlerOptions, WebhookHttpResponse } from \"./webhook\";\n","import type { ApiErrorBody } from \"./types\";\n\nexport class SdkError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SdkError\";\n }\n}\n\nexport class ApiError extends SdkError {\n readonly status: number;\n readonly code: string | undefined;\n readonly body: ApiErrorBody | null;\n readonly retryable: boolean;\n\n constructor(params: {\n status: number;\n message: string;\n code: string | undefined;\n body: ApiErrorBody | null;\n }) {\n super(params.message);\n this.name = \"ApiError\";\n this.status = params.status;\n this.code = params.code;\n this.body = params.body;\n this.retryable = params.status === 429 || params.status >= 500;\n }\n}\n","import { ApiError } from \"./errors\";\nimport type {\n ApiErrorBody,\n AssignmentAckRequest,\n AssignmentResult,\n SubmitErrorRequest,\n SubmitResultRequest,\n} from \"./types\";\n\nexport type ClientOptions = {\n baseUrl: string;\n apiKey: string;\n fetchImpl?: typeof fetch;\n};\n\nexport class AgentClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: ClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.apiKey = options.apiKey;\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n async ackAssignment(assignmentId: string, request: AssignmentAckRequest): Promise<void> {\n await this.post(`/agent/assignments/ack`, {\n assignment_id: assignmentId,\n ...request,\n });\n }\n\n async submitResult(input: SubmitResultRequest): Promise<void> {\n const payload: AssignmentResult = {\n status: input.status,\n ...(input.result ? { result: input.result } : {}),\n ...(input.error ? { error: input.error } : {}),\n };\n\n await this.post(`/agent/assignments/submit`, {\n assignment_id: input.assignmentId,\n ...payload,\n });\n }\n\n async submitError(input: SubmitErrorRequest): Promise<void> {\n await this.submitResult({\n assignmentId: input.assignmentId,\n status: \"timed_out\",\n error: input.error,\n ...(input.details ? { result: { details: input.details } } : {}),\n });\n }\n\n private async post(path: string, body: Record<string, unknown>): Promise<void> {\n const response = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n throw await this.toApiError(response);\n }\n }\n\n private async toApiError(response: Response): Promise<ApiError> {\n const raw = await response.text();\n let parsed: ApiErrorBody | null = null;\n\n if (raw) {\n try {\n parsed = JSON.parse(raw) as ApiErrorBody;\n } catch {\n parsed = { message: raw };\n }\n }\n\n return new ApiError({\n status: response.status,\n message:\n parsed?.message ?? `API request failed (${response.status}): ${raw || response.statusText}`,\n code: parsed?.code,\n body: parsed,\n });\n }\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { SdkError } from \"./errors\";\n\nexport function computeWebhookSignature(params: {\n webhookSecret: string;\n timestamp: string;\n body: string;\n}) {\n const signedPayload = `${params.timestamp}.${params.body}`;\n const digest = createHmac(\"sha256\", params.webhookSecret)\n .update(signedPayload, \"utf8\")\n .digest(\"hex\");\n return `sha256=${digest}`;\n}\n\nexport function verifyWebhookSignature(params: {\n webhookSecret: string;\n timestamp?: string;\n body: string;\n signature?: string;\n}) {\n if (!params.timestamp || !params.signature) {\n throw new SdkError(\"Missing webhook timestamp or signature\");\n }\n\n const expected = computeWebhookSignature({\n webhookSecret: params.webhookSecret,\n timestamp: params.timestamp,\n body: params.body,\n });\n\n const expectedBuffer = Buffer.from(expected, \"utf8\");\n const actualBuffer = Buffer.from(params.signature, \"utf8\");\n\n if (expectedBuffer.length !== actualBuffer.length) {\n throw new SdkError(\"Invalid webhook signature\");\n }\n\n if (!timingSafeEqual(expectedBuffer, actualBuffer)) {\n throw new SdkError(\"Invalid webhook signature\");\n }\n}\n","import { SdkError } from \"./errors\";\nimport type { Assignment, AssignmentEnvelopeV1, AssignmentResultSchema, SdkContractVersion } from \"./types\";\n\nconst CONTRACT_VERSION: SdkContractVersion = \"v1\";\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\";\n}\n\nfunction parseAssignmentRecord(record: Record<string, unknown>): Assignment {\n if (typeof record.assignment_id !== \"string\") {\n throw new SdkError(\"Missing assignment_id\");\n }\n if (typeof record.template_slug !== \"string\") {\n throw new SdkError(\"Missing template_slug\");\n }\n if (!isObject(record.outcome)) {\n throw new SdkError(\"Missing outcome\");\n }\n if (!isObject(record.result_schema)) {\n throw new SdkError(\"Missing result_schema\");\n }\n\n const outcome = record.outcome;\n if (typeof outcome.title !== \"string\") {\n throw new SdkError(\"Missing outcome.title\");\n }\n if (!isObject(outcome.payload)) {\n throw new SdkError(\"Missing outcome.payload\");\n }\n\n const parsedResultSchema = record.result_schema as AssignmentResultSchema;\n\n return {\n assignment_id: record.assignment_id,\n template_slug: record.template_slug,\n result_schema: parsedResultSchema,\n outcome: {\n title: outcome.title,\n payload: outcome.payload,\n ...(typeof outcome.requested_unit_price_value === \"number\"\n ? { requested_unit_price_value: outcome.requested_unit_price_value }\n : {}),\n ...(typeof outcome.requested_total_price_value === \"number\"\n ? { requested_total_price_value: outcome.requested_total_price_value }\n : {}),\n ...(typeof outcome.currency === \"string\" ? { currency: outcome.currency } : {}),\n ...(typeof outcome.time_window === \"string\" ? { time_window: outcome.time_window } : {}),\n },\n };\n}\n\nexport function parseAssignmentV1(body: string): Assignment {\n let payload: unknown;\n try {\n payload = JSON.parse(body);\n } catch {\n throw new SdkError(\"Invalid JSON payload\");\n }\n\n if (!isObject(payload)) {\n throw new SdkError(\"Invalid assignment payload\");\n }\n\n if (payload.version !== CONTRACT_VERSION) {\n throw new SdkError(\"Unsupported assignment contract version\");\n }\n if (!isObject(payload.assignment)) {\n throw new SdkError(\"Missing assignment envelope payload\");\n }\n\n return parseAssignmentRecord(payload.assignment);\n}\n\nexport function toAssignmentEnvelopeV1(assignment: Assignment): AssignmentEnvelopeV1 {\n return {\n version: CONTRACT_VERSION,\n assignment,\n };\n}\n\nexport function getContractVersion(): SdkContractVersion {\n return CONTRACT_VERSION;\n}\n","import { SdkError } from \"./errors\";\nimport { parseAssignmentV1 } from \"./contracts\";\nimport { verifyWebhookSignature } from \"./signature\";\nimport type { Assignment, AssignmentResult, WebhookInput } from \"./types\";\n\nexport const DEFAULT_SIGNATURE_HEADER = \"x-bounty-signature\";\nexport const DEFAULT_TIMESTAMP_HEADER = \"x-bounty-timestamp\";\n\nexport type WebhookHandlerOptions = {\n webhookSecret: string;\n onAssignment: (params: { assignment: Assignment }) => Promise<AssignmentResult>;\n verifySignature?: boolean;\n};\n\nexport type WebhookHttpResponse = {\n status: number;\n body: AssignmentResult;\n};\n\nexport function createWebhookHandler(options: WebhookHandlerOptions) {\n const shouldVerify = options.verifySignature ?? true;\n\n return async function handleWebhook(input: WebhookInput): Promise<AssignmentResult> {\n if (shouldVerify) {\n verifyWebhookSignature({\n webhookSecret: options.webhookSecret,\n body: input.body,\n ...(input.signature ? { signature: input.signature } : {}),\n ...(input.timestamp ? { timestamp: input.timestamp } : {}),\n });\n }\n\n const assignment = parseAssignmentV1(input.body);\n return options.onAssignment({ assignment });\n };\n}\n\nexport async function executeWebhook(\n handler: ReturnType<typeof createWebhookHandler>,\n input: WebhookInput,\n): Promise<WebhookHttpResponse> {\n try {\n const body = await handler(input);\n return {\n status: 200,\n body,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unexpected webhook error\";\n const sdkError = error instanceof SdkError ? error : new SdkError(message);\n return {\n status: 400,\n body: {\n status: \"timed_out\",\n error: sdkError.message,\n },\n };\n }\n}\n","import {\n DEFAULT_SIGNATURE_HEADER,\n DEFAULT_TIMESTAMP_HEADER,\n createWebhookHandler,\n executeWebhook,\n type WebhookHandlerOptions,\n} from \"./webhook\";\n\nfunction headerValue(headers: Record<string, string | string[] | undefined>, key: string) {\n const value = headers[key] ?? headers[key.toLowerCase()];\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n}\n\nfunction normalizeBody(body: unknown): string {\n if (typeof body === \"string\") {\n return body;\n }\n if (body === undefined || body === null) {\n return \"\";\n }\n return JSON.stringify(body);\n}\n\nfunction toWebhookInput(params: {\n body: string;\n signature: string | undefined;\n timestamp: string | undefined;\n}) {\n return {\n body: params.body,\n ...(params.signature ? { signature: params.signature } : {}),\n ...(params.timestamp ? { timestamp: params.timestamp } : {}),\n };\n}\n\nexport function createExpressWebhookHandler(options: WebhookHandlerOptions) {\n const handler = createWebhookHandler(options);\n\n return async function expressWebhook(\n req: {\n headers: Record<string, string | string[] | undefined>;\n body?: unknown;\n rawBody?: string;\n },\n res: {\n status: (code: number) => { json: (payload: unknown) => void };\n },\n ) {\n const body = req.rawBody ?? normalizeBody(req.body);\n const result = await executeWebhook(\n handler,\n toWebhookInput({\n body,\n signature: headerValue(req.headers, DEFAULT_SIGNATURE_HEADER),\n timestamp: headerValue(req.headers, DEFAULT_TIMESTAMP_HEADER),\n }),\n );\n\n res.status(result.status).json(result.body);\n };\n}\n\nexport function createFastifyWebhookHandler(options: WebhookHandlerOptions) {\n const handler = createWebhookHandler(options);\n\n return async function fastifyWebhook(\n request: {\n headers: Record<string, string | string[] | undefined>;\n body?: unknown;\n rawBody?: string;\n },\n reply: {\n code: (statusCode: number) => { send: (payload: unknown) => void };\n },\n ) {\n const body = request.rawBody ?? normalizeBody(request.body);\n const result = await executeWebhook(\n handler,\n toWebhookInput({\n body,\n signature: headerValue(request.headers, DEFAULT_SIGNATURE_HEADER),\n timestamp: headerValue(request.headers, DEFAULT_TIMESTAMP_HEADER),\n }),\n );\n\n reply.code(result.status).send(result.body);\n };\n}\n\nexport function createNextWebhookHandler(options: WebhookHandlerOptions) {\n const handler = createWebhookHandler(options);\n\n return async function nextWebhook(request: Request): Promise<Response> {\n const body = await request.text();\n const result = await executeWebhook(\n handler,\n toWebhookInput({\n body,\n signature: request.headers.get(DEFAULT_SIGNATURE_HEADER) ?? undefined,\n timestamp: request.headers.get(DEFAULT_TIMESTAMP_HEADER) ?? undefined,\n }),\n );\n\n return new Response(JSON.stringify(result.body), {\n status: result.status,\n headers: { \"content-type\": \"application/json\" },\n });\n };\n}\n\nexport function createHonoWebhookHandler(options: WebhookHandlerOptions) {\n const handler = createWebhookHandler(options);\n\n return async function honoWebhook(c: {\n req: {\n text: () => Promise<string>;\n header: (name: string) => string | undefined;\n };\n json: (payload: unknown, status?: number) => Response;\n }) {\n const body = await c.req.text();\n const result = await executeWebhook(\n handler,\n toWebhookInput({\n body,\n signature: c.req.header(DEFAULT_SIGNATURE_HEADER),\n timestamp: c.req.header(DEFAULT_TIMESTAMP_HEADER),\n }),\n );\n\n return c.json(result.body, result.status);\n };\n}\n","import type { AssignmentResult } from \"./types\";\n\nexport type TableRow = Record<string, unknown>;\n\nexport type TablePayload = {\n table: {\n columns: string[];\n rows: TableRow[];\n };\n row_count: number;\n rows_unique: boolean;\n has_contact_method: boolean;\n summary?: string;\n};\n\nexport type CreateTableResultOptions = {\n columns?: string[];\n summary?: string;\n contactFields?: string[];\n dedupeBy?: string[];\n};\n\nconst DEFAULT_CONTACT_FIELDS = [\"email\", \"phone\", \"profile_url\", \"linkedin_url\"];\n\nfunction hasValue(value: unknown) {\n if (typeof value === \"string\") {\n return value.trim().length > 0;\n }\n return value !== null && value !== undefined;\n}\n\nfunction deriveColumns(rows: TableRow[]) {\n const ordered: string[] = [];\n for (const row of rows) {\n for (const key of Object.keys(row)) {\n if (!ordered.includes(key)) {\n ordered.push(key);\n }\n }\n }\n return ordered;\n}\n\nfunction makeRowKey(row: TableRow, keys: string[]) {\n const normalized = keys.map((key) => [key, row[key]]);\n return JSON.stringify(normalized);\n}\n\nexport function createTablePayload(\n rows: TableRow[],\n options: CreateTableResultOptions = {},\n): TablePayload {\n const columns = options.columns ?? deriveColumns(rows);\n const dedupeKeys = options.dedupeBy && options.dedupeBy.length > 0 ? options.dedupeBy : columns;\n const contactFields =\n options.contactFields && options.contactFields.length > 0\n ? options.contactFields\n : DEFAULT_CONTACT_FIELDS;\n\n const uniqueCount = new Set(rows.map((row) => makeRowKey(row, dedupeKeys))).size;\n const hasContactMethod = rows.every((row) => contactFields.some((field) => hasValue(row[field])));\n\n return {\n table: {\n columns,\n rows,\n },\n row_count: rows.length,\n rows_unique: uniqueCount === rows.length,\n has_contact_method: hasContactMethod,\n ...(options.summary ? { summary: options.summary } : {}),\n };\n}\n\nexport function createTableResult(\n rows: TableRow[],\n options: CreateTableResultOptions = {},\n): Pick<AssignmentResult, \"result\"> {\n return {\n result: createTablePayload(rows, options),\n };\n}\n"],"mappings":"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","names":[]}
|