@bounty-ai/agent-sdk 0.1.0 → 0.1.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.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  type SdkContractVersion = "v1";
2
- type AssignmentStatus = "assigned" | "verifying" | "timed_out";
2
+ type AssignmentStatus = "assigned" | "verifying" | "rejected" | "timed_out";
3
3
  type OutcomePayload = Record<string, unknown>;
4
4
  type AssignmentResultOutput = {
5
5
  type: "table" | "text" | "image" | "file" | "collection";
@@ -35,6 +35,32 @@ type AssignmentResult = {
35
35
  result?: Record<string, unknown>;
36
36
  error?: string;
37
37
  };
38
+ type EmailRecipient = {
39
+ email: string;
40
+ name?: string;
41
+ };
42
+ type EmailOutreachMode = "draft" | "send";
43
+ type EmailDeliveryInput = {
44
+ to: EmailRecipient[];
45
+ cc?: EmailRecipient[];
46
+ bcc?: EmailRecipient[];
47
+ subject: string;
48
+ textBody: string;
49
+ htmlBody?: string;
50
+ };
51
+ type IntegrationAction = {
52
+ type: string;
53
+ actionKey?: string;
54
+ operation: string;
55
+ input: Record<string, unknown>;
56
+ metadata?: Record<string, unknown>;
57
+ };
58
+ type EmailDeliveryAction = IntegrationAction & {
59
+ type: "email";
60
+ operation: EmailOutreachMode;
61
+ input: EmailDeliveryInput;
62
+ };
63
+ type AssignmentAction = IntegrationAction;
38
64
  type AssignmentAckStatus = "accepted" | "rejected";
39
65
  type AssignmentAckRequest = {
40
66
  status: AssignmentAckStatus;
@@ -50,6 +76,7 @@ type SubmitResultRequest = {
50
76
  status: AssignmentStatus;
51
77
  result?: Record<string, unknown>;
52
78
  error?: string;
79
+ actions?: AssignmentAction[];
53
80
  };
54
81
  type SubmitErrorRequest = {
55
82
  assignmentId: string;
@@ -150,10 +177,75 @@ declare function createHonoWebhookHandler(options: WebhookHandlerOptions): (c: {
150
177
  json: (payload: unknown, status?: number) => Response;
151
178
  }) => Promise<Response>;
152
179
 
180
+ type RuntimeLogger = {
181
+ info?: (...args: unknown[]) => void;
182
+ error?: (...args: unknown[]) => void;
183
+ };
184
+ type AutoSubmitAssignmentHandlerOptions = {
185
+ client: AgentClient | ClientOptions;
186
+ runAssignment: (params: {
187
+ assignment: Assignment;
188
+ }) => Promise<AssignmentExecutionOutput>;
189
+ acceptAssignment?: (params: {
190
+ assignment: Assignment;
191
+ }) => Promise<AssignmentResult> | AssignmentResult;
192
+ createSubmitRequest?: (params: {
193
+ assignment: Assignment;
194
+ result: Record<string, unknown>;
195
+ actions?: AssignmentAction[];
196
+ }) => SubmitResultRequest;
197
+ createSubmitErrorRequest?: (params: {
198
+ assignment: Assignment;
199
+ error: unknown;
200
+ }) => SubmitErrorRequest;
201
+ executionMode?: "background" | "blocking";
202
+ logger?: RuntimeLogger;
203
+ };
204
+ type AssignmentExecutionResult = {
205
+ result: Record<string, unknown>;
206
+ actions?: AssignmentAction[];
207
+ };
208
+ type AssignmentExecutionOutput = Record<string, unknown> | AssignmentExecutionResult;
209
+ type AssignmentExecutionHandler = (params: {
210
+ assignment: Assignment;
211
+ }) => Promise<AssignmentExecutionOutput>;
212
+ type AssignmentSlugRouterOptions = {
213
+ handlers: Record<string, AssignmentExecutionHandler>;
214
+ fallback?: AssignmentExecutionHandler;
215
+ normalizeSlug?: (slug: string) => string;
216
+ };
217
+ declare function createAssignmentSlugRouter(options: AssignmentSlugRouterOptions): AssignmentExecutionHandler;
218
+ declare function createAutoSubmitAssignmentHandler(options: AutoSubmitAssignmentHandlerOptions): ({ assignment }: {
219
+ assignment: Assignment;
220
+ }) => Promise<AssignmentResult>;
221
+
153
222
  declare function parseAssignmentV1(body: string): Assignment;
154
223
  declare function toAssignmentEnvelopeV1(assignment: Assignment): AssignmentEnvelopeV1;
155
224
  declare function getContractVersion(): SdkContractVersion;
156
225
 
226
+ type CreateIntegrationActionInput = {
227
+ actionKey?: string;
228
+ type: string;
229
+ operation: string;
230
+ input: Record<string, unknown>;
231
+ metadata?: Record<string, unknown>;
232
+ };
233
+ type CreateEmailDeliveryActionInput = {
234
+ actionKey?: string;
235
+ mode: "draft" | "send";
236
+ to: EmailRecipient[];
237
+ cc?: EmailRecipient[];
238
+ bcc?: EmailRecipient[];
239
+ subject: string;
240
+ textBody: string;
241
+ htmlBody?: string;
242
+ metadata?: Record<string, unknown>;
243
+ };
244
+ declare function createIntegrationAction(input: CreateIntegrationActionInput): IntegrationAction;
245
+ declare function createEmailDeliveryAction(input: CreateEmailDeliveryActionInput): EmailDeliveryAction;
246
+ declare function isIntegrationAction(action: AssignmentAction): action is IntegrationAction;
247
+ declare function isEmailDeliveryAction(action: AssignmentAction): action is EmailDeliveryAction;
248
+
157
249
  type TableRow = Record<string, unknown>;
158
250
  type TablePayload = {
159
251
  table: {
@@ -174,4 +266,4 @@ type CreateTableResultOptions = {
174
266
  declare function createTablePayload(rows: TableRow[], options?: CreateTableResultOptions): TablePayload;
175
267
  declare function createTableResult(rows: TableRow[], options?: CreateTableResultOptions): Pick<AssignmentResult, "result">;
176
268
 
177
- export { AgentClient, ApiError, type ApiErrorBody, type Assignment, type AssignmentAckRequest, type AssignmentAckStatus, type AssignmentEnvelopeV1, type AssignmentOutcome, type AssignmentResult, type AssignmentResultOutput, type AssignmentResultSchema, type AssignmentStatus, type ClientOptions, type CreateTableResultOptions, DEFAULT_SIGNATURE_HEADER, DEFAULT_TIMESTAMP_HEADER, type OutcomePayload, type SdkContractVersion, SdkError, type SubmitErrorRequest, type SubmitResultRequest, type TablePayload, type TableRow, type WebhookHandlerOptions, type WebhookHttpResponse, type WebhookInput, computeWebhookSignature, createExpressWebhookHandler, createFastifyWebhookHandler, createHonoWebhookHandler, createNextWebhookHandler, createTablePayload, createTableResult, createWebhookHandler, executeWebhook, getContractVersion, parseAssignmentV1, toAssignmentEnvelopeV1, verifyWebhookSignature };
269
+ export { AgentClient, ApiError, type ApiErrorBody, type Assignment, type AssignmentAckRequest, type AssignmentAckStatus, type AssignmentAction, type AssignmentEnvelopeV1, type AssignmentExecutionHandler, type AssignmentExecutionResult, type AssignmentOutcome, type AssignmentResult, type AssignmentResultOutput, type AssignmentResultSchema, type AssignmentSlugRouterOptions, type AssignmentStatus, type AutoSubmitAssignmentHandlerOptions, type ClientOptions, type CreateEmailDeliveryActionInput, type CreateIntegrationActionInput, type CreateTableResultOptions, DEFAULT_SIGNATURE_HEADER, DEFAULT_TIMESTAMP_HEADER, type EmailDeliveryAction, type EmailDeliveryInput, type EmailOutreachMode, type EmailRecipient, type IntegrationAction, type OutcomePayload, type SdkContractVersion, SdkError, type SubmitErrorRequest, type SubmitResultRequest, type TablePayload, type TableRow, type WebhookHandlerOptions, type WebhookHttpResponse, type WebhookInput, computeWebhookSignature, createAssignmentSlugRouter, createAutoSubmitAssignmentHandler, createEmailDeliveryAction, createExpressWebhookHandler, createFastifyWebhookHandler, createHonoWebhookHandler, createIntegrationAction, createNextWebhookHandler, createTablePayload, createTableResult, createWebhookHandler, executeWebhook, getContractVersion, isEmailDeliveryAction, isIntegrationAction, parseAssignmentV1, toAssignmentEnvelopeV1, verifyWebhookSignature };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  type SdkContractVersion = "v1";
2
- type AssignmentStatus = "assigned" | "verifying" | "timed_out";
2
+ type AssignmentStatus = "assigned" | "verifying" | "rejected" | "timed_out";
3
3
  type OutcomePayload = Record<string, unknown>;
4
4
  type AssignmentResultOutput = {
5
5
  type: "table" | "text" | "image" | "file" | "collection";
@@ -35,6 +35,32 @@ type AssignmentResult = {
35
35
  result?: Record<string, unknown>;
36
36
  error?: string;
37
37
  };
38
+ type EmailRecipient = {
39
+ email: string;
40
+ name?: string;
41
+ };
42
+ type EmailOutreachMode = "draft" | "send";
43
+ type EmailDeliveryInput = {
44
+ to: EmailRecipient[];
45
+ cc?: EmailRecipient[];
46
+ bcc?: EmailRecipient[];
47
+ subject: string;
48
+ textBody: string;
49
+ htmlBody?: string;
50
+ };
51
+ type IntegrationAction = {
52
+ type: string;
53
+ actionKey?: string;
54
+ operation: string;
55
+ input: Record<string, unknown>;
56
+ metadata?: Record<string, unknown>;
57
+ };
58
+ type EmailDeliveryAction = IntegrationAction & {
59
+ type: "email";
60
+ operation: EmailOutreachMode;
61
+ input: EmailDeliveryInput;
62
+ };
63
+ type AssignmentAction = IntegrationAction;
38
64
  type AssignmentAckStatus = "accepted" | "rejected";
39
65
  type AssignmentAckRequest = {
40
66
  status: AssignmentAckStatus;
@@ -50,6 +76,7 @@ type SubmitResultRequest = {
50
76
  status: AssignmentStatus;
51
77
  result?: Record<string, unknown>;
52
78
  error?: string;
79
+ actions?: AssignmentAction[];
53
80
  };
54
81
  type SubmitErrorRequest = {
55
82
  assignmentId: string;
@@ -150,10 +177,75 @@ declare function createHonoWebhookHandler(options: WebhookHandlerOptions): (c: {
150
177
  json: (payload: unknown, status?: number) => Response;
151
178
  }) => Promise<Response>;
152
179
 
180
+ type RuntimeLogger = {
181
+ info?: (...args: unknown[]) => void;
182
+ error?: (...args: unknown[]) => void;
183
+ };
184
+ type AutoSubmitAssignmentHandlerOptions = {
185
+ client: AgentClient | ClientOptions;
186
+ runAssignment: (params: {
187
+ assignment: Assignment;
188
+ }) => Promise<AssignmentExecutionOutput>;
189
+ acceptAssignment?: (params: {
190
+ assignment: Assignment;
191
+ }) => Promise<AssignmentResult> | AssignmentResult;
192
+ createSubmitRequest?: (params: {
193
+ assignment: Assignment;
194
+ result: Record<string, unknown>;
195
+ actions?: AssignmentAction[];
196
+ }) => SubmitResultRequest;
197
+ createSubmitErrorRequest?: (params: {
198
+ assignment: Assignment;
199
+ error: unknown;
200
+ }) => SubmitErrorRequest;
201
+ executionMode?: "background" | "blocking";
202
+ logger?: RuntimeLogger;
203
+ };
204
+ type AssignmentExecutionResult = {
205
+ result: Record<string, unknown>;
206
+ actions?: AssignmentAction[];
207
+ };
208
+ type AssignmentExecutionOutput = Record<string, unknown> | AssignmentExecutionResult;
209
+ type AssignmentExecutionHandler = (params: {
210
+ assignment: Assignment;
211
+ }) => Promise<AssignmentExecutionOutput>;
212
+ type AssignmentSlugRouterOptions = {
213
+ handlers: Record<string, AssignmentExecutionHandler>;
214
+ fallback?: AssignmentExecutionHandler;
215
+ normalizeSlug?: (slug: string) => string;
216
+ };
217
+ declare function createAssignmentSlugRouter(options: AssignmentSlugRouterOptions): AssignmentExecutionHandler;
218
+ declare function createAutoSubmitAssignmentHandler(options: AutoSubmitAssignmentHandlerOptions): ({ assignment }: {
219
+ assignment: Assignment;
220
+ }) => Promise<AssignmentResult>;
221
+
153
222
  declare function parseAssignmentV1(body: string): Assignment;
154
223
  declare function toAssignmentEnvelopeV1(assignment: Assignment): AssignmentEnvelopeV1;
155
224
  declare function getContractVersion(): SdkContractVersion;
156
225
 
226
+ type CreateIntegrationActionInput = {
227
+ actionKey?: string;
228
+ type: string;
229
+ operation: string;
230
+ input: Record<string, unknown>;
231
+ metadata?: Record<string, unknown>;
232
+ };
233
+ type CreateEmailDeliveryActionInput = {
234
+ actionKey?: string;
235
+ mode: "draft" | "send";
236
+ to: EmailRecipient[];
237
+ cc?: EmailRecipient[];
238
+ bcc?: EmailRecipient[];
239
+ subject: string;
240
+ textBody: string;
241
+ htmlBody?: string;
242
+ metadata?: Record<string, unknown>;
243
+ };
244
+ declare function createIntegrationAction(input: CreateIntegrationActionInput): IntegrationAction;
245
+ declare function createEmailDeliveryAction(input: CreateEmailDeliveryActionInput): EmailDeliveryAction;
246
+ declare function isIntegrationAction(action: AssignmentAction): action is IntegrationAction;
247
+ declare function isEmailDeliveryAction(action: AssignmentAction): action is EmailDeliveryAction;
248
+
157
249
  type TableRow = Record<string, unknown>;
158
250
  type TablePayload = {
159
251
  table: {
@@ -174,4 +266,4 @@ type CreateTableResultOptions = {
174
266
  declare function createTablePayload(rows: TableRow[], options?: CreateTableResultOptions): TablePayload;
175
267
  declare function createTableResult(rows: TableRow[], options?: CreateTableResultOptions): Pick<AssignmentResult, "result">;
176
268
 
177
- export { AgentClient, ApiError, type ApiErrorBody, type Assignment, type AssignmentAckRequest, type AssignmentAckStatus, type AssignmentEnvelopeV1, type AssignmentOutcome, type AssignmentResult, type AssignmentResultOutput, type AssignmentResultSchema, type AssignmentStatus, type ClientOptions, type CreateTableResultOptions, DEFAULT_SIGNATURE_HEADER, DEFAULT_TIMESTAMP_HEADER, type OutcomePayload, type SdkContractVersion, SdkError, type SubmitErrorRequest, type SubmitResultRequest, type TablePayload, type TableRow, type WebhookHandlerOptions, type WebhookHttpResponse, type WebhookInput, computeWebhookSignature, createExpressWebhookHandler, createFastifyWebhookHandler, createHonoWebhookHandler, createNextWebhookHandler, createTablePayload, createTableResult, createWebhookHandler, executeWebhook, getContractVersion, parseAssignmentV1, toAssignmentEnvelopeV1, verifyWebhookSignature };
269
+ export { AgentClient, ApiError, type ApiErrorBody, type Assignment, type AssignmentAckRequest, type AssignmentAckStatus, type AssignmentAction, type AssignmentEnvelopeV1, type AssignmentExecutionHandler, type AssignmentExecutionResult, type AssignmentOutcome, type AssignmentResult, type AssignmentResultOutput, type AssignmentResultSchema, type AssignmentSlugRouterOptions, type AssignmentStatus, type AutoSubmitAssignmentHandlerOptions, type ClientOptions, type CreateEmailDeliveryActionInput, type CreateIntegrationActionInput, type CreateTableResultOptions, DEFAULT_SIGNATURE_HEADER, DEFAULT_TIMESTAMP_HEADER, type EmailDeliveryAction, type EmailDeliveryInput, type EmailOutreachMode, type EmailRecipient, type IntegrationAction, type OutcomePayload, type SdkContractVersion, SdkError, type SubmitErrorRequest, type SubmitResultRequest, type TablePayload, type TableRow, type WebhookHandlerOptions, type WebhookHttpResponse, type WebhookInput, computeWebhookSignature, createAssignmentSlugRouter, createAutoSubmitAssignmentHandler, createEmailDeliveryAction, createExpressWebhookHandler, createFastifyWebhookHandler, createHonoWebhookHandler, createIntegrationAction, createNextWebhookHandler, createTablePayload, createTableResult, createWebhookHandler, executeWebhook, getContractVersion, isEmailDeliveryAction, isIntegrationAction, parseAssignmentV1, toAssignmentEnvelopeV1, verifyWebhookSignature };
package/dist/index.js CHANGED
@@ -44,7 +44,8 @@ var AgentClient = class {
44
44
  };
45
45
  await this.post(`/agent/assignments/submit`, {
46
46
  assignment_id: input.assignmentId,
47
- ...payload
47
+ ...payload,
48
+ ...input.actions ? { actions: input.actions } : {}
48
49
  });
49
50
  }
50
51
  async submitError(input) {
@@ -212,7 +213,7 @@ async function executeWebhook(handler, input) {
212
213
  return {
213
214
  status: 400,
214
215
  body: {
215
- status: "timed_out",
216
+ status: "rejected",
216
217
  error: sdkError.message
217
218
  }
218
219
  };
@@ -231,11 +232,46 @@ function normalizeBody(body) {
231
232
  if (typeof body === "string") {
232
233
  return body;
233
234
  }
235
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(body)) {
236
+ return body.toString("utf8");
237
+ }
234
238
  if (body === void 0 || body === null) {
235
239
  return "";
236
240
  }
237
241
  return JSON.stringify(body);
238
242
  }
243
+ async function readExpressBody(req) {
244
+ if (typeof req.rawBody === "string" || Buffer.isBuffer(req.rawBody)) {
245
+ return normalizeBody(req.rawBody);
246
+ }
247
+ if (req.body !== void 0) {
248
+ if (typeof req.body === "object" && req.body !== null && !Buffer.isBuffer(req.body)) {
249
+ throw new SdkError(
250
+ "Express webhook route must receive raw bytes. Mount webhook routes before express.json() or exclude them from JSON parsing."
251
+ );
252
+ }
253
+ return normalizeBody(req.body);
254
+ }
255
+ if (!req.on) {
256
+ return "";
257
+ }
258
+ return await new Promise((resolve, reject) => {
259
+ const chunks = [];
260
+ req.on?.("data", (chunk) => {
261
+ if (typeof chunk === "string") {
262
+ chunks.push(Buffer.from(chunk, "utf8"));
263
+ } else if (chunk instanceof Uint8Array) {
264
+ chunks.push(chunk);
265
+ }
266
+ });
267
+ req.on?.("end", () => {
268
+ resolve(Buffer.concat(chunks).toString("utf8"));
269
+ });
270
+ req.on?.("error", (error) => {
271
+ reject(error);
272
+ });
273
+ });
274
+ }
239
275
  function toWebhookInput(params) {
240
276
  return {
241
277
  body: params.body,
@@ -243,18 +279,33 @@ function toWebhookInput(params) {
243
279
  ...params.timestamp ? { timestamp: params.timestamp } : {}
244
280
  };
245
281
  }
282
+ function toBadRequest(error) {
283
+ const message = error instanceof Error ? error.message : "Unexpected webhook error";
284
+ return {
285
+ status: 400,
286
+ body: {
287
+ status: "rejected",
288
+ error: message
289
+ }
290
+ };
291
+ }
246
292
  function createExpressWebhookHandler(options) {
247
293
  const handler = createWebhookHandler(options);
248
294
  return async function expressWebhook(req, res) {
249
- const body = req.rawBody ?? normalizeBody(req.body);
250
- const result = await executeWebhook(
251
- handler,
252
- toWebhookInput({
253
- body,
254
- signature: headerValue(req.headers, DEFAULT_SIGNATURE_HEADER),
255
- timestamp: headerValue(req.headers, DEFAULT_TIMESTAMP_HEADER)
256
- })
257
- );
295
+ let result;
296
+ try {
297
+ const body = await readExpressBody(req);
298
+ result = await executeWebhook(
299
+ handler,
300
+ toWebhookInput({
301
+ body,
302
+ signature: headerValue(req.headers, DEFAULT_SIGNATURE_HEADER),
303
+ timestamp: headerValue(req.headers, DEFAULT_TIMESTAMP_HEADER)
304
+ })
305
+ );
306
+ } catch (error) {
307
+ result = toBadRequest(error);
308
+ }
258
309
  res.status(result.status).json(result.body);
259
310
  };
260
311
  }
@@ -307,6 +358,190 @@ function createHonoWebhookHandler(options) {
307
358
  };
308
359
  }
309
360
 
361
+ // src/runtime.ts
362
+ function toMessage(error) {
363
+ if (error instanceof Error && error.message.trim().length > 0) {
364
+ return error.message;
365
+ }
366
+ return "Unknown assignment execution error";
367
+ }
368
+ function defaultAcceptedResponse(assignment) {
369
+ return {
370
+ status: "assigned",
371
+ result: {
372
+ accepted: true,
373
+ assignment_id: assignment.assignment_id
374
+ }
375
+ };
376
+ }
377
+ function defaultSubmitRequest(params) {
378
+ return {
379
+ assignmentId: params.assignment.assignment_id,
380
+ status: "verifying",
381
+ result: params.result,
382
+ ...params.actions && params.actions.length > 0 ? { actions: params.actions } : {}
383
+ };
384
+ }
385
+ function defaultSubmitErrorRequest(params) {
386
+ return {
387
+ assignmentId: params.assignment.assignment_id,
388
+ error: toMessage(params.error)
389
+ };
390
+ }
391
+ function asClient(client) {
392
+ return client instanceof AgentClient ? client : new AgentClient(client);
393
+ }
394
+ function normalizeExecutionOutput(output) {
395
+ if (output && typeof output === "object" && !Array.isArray(output) && "result" in output && output.result && typeof output.result === "object" && !Array.isArray(output.result)) {
396
+ const actions = "actions" in output && Array.isArray(output.actions) ? output.actions : void 0;
397
+ return {
398
+ result: output.result,
399
+ ...actions && actions.length > 0 ? { actions } : {}
400
+ };
401
+ }
402
+ if (!output || typeof output !== "object" || Array.isArray(output)) {
403
+ throw new SdkError("Assignment execution must return an object result");
404
+ }
405
+ return {
406
+ result: output
407
+ };
408
+ }
409
+ function createAssignmentSlugRouter(options) {
410
+ const normalize = options.normalizeSlug ?? ((slug) => slug);
411
+ const normalizedHandlers = /* @__PURE__ */ new Map();
412
+ for (const [slug, handler] of Object.entries(options.handlers)) {
413
+ normalizedHandlers.set(normalize(slug), handler);
414
+ }
415
+ return async ({ assignment }) => {
416
+ const slug = normalize(assignment.template_slug);
417
+ const handler = normalizedHandlers.get(slug) ?? options.fallback;
418
+ if (!handler) {
419
+ throw new SdkError(`No assignment handler registered for template slug "${assignment.template_slug}"`);
420
+ }
421
+ return handler({ assignment });
422
+ };
423
+ }
424
+ function createAutoSubmitAssignmentHandler(options) {
425
+ const client = asClient(options.client);
426
+ const mode = options.executionMode ?? "background";
427
+ const logger = options.logger;
428
+ async function processAssignment(assignment) {
429
+ try {
430
+ const execution = normalizeExecutionOutput(await options.runAssignment({ assignment }));
431
+ const submitRequest = options.createSubmitRequest ? options.createSubmitRequest({
432
+ assignment,
433
+ result: execution.result,
434
+ ...execution.actions ? { actions: execution.actions } : {}
435
+ }) : defaultSubmitRequest({
436
+ assignment,
437
+ result: execution.result,
438
+ ...execution.actions ? { actions: execution.actions } : {}
439
+ });
440
+ await client.submitResult(submitRequest);
441
+ logger?.info?.("[agent-sdk] assignment_submitted", {
442
+ assignmentId: assignment.assignment_id,
443
+ status: submitRequest.status,
444
+ actionCount: submitRequest.actions?.length ?? 0
445
+ });
446
+ } catch (error) {
447
+ const submitErrorRequest = options.createSubmitErrorRequest ? options.createSubmitErrorRequest({ assignment, error }) : defaultSubmitErrorRequest({ assignment, error });
448
+ await client.submitError(submitErrorRequest);
449
+ logger?.error?.("[agent-sdk] assignment_failed", {
450
+ assignmentId: assignment.assignment_id,
451
+ error: submitErrorRequest.error
452
+ });
453
+ }
454
+ }
455
+ return async function onAssignment({ assignment }) {
456
+ const accepted = options.acceptAssignment ? await options.acceptAssignment({ assignment }) : defaultAcceptedResponse(assignment);
457
+ if (accepted.status !== "assigned") {
458
+ return accepted;
459
+ }
460
+ if (mode === "blocking") {
461
+ await processAssignment(assignment);
462
+ } else {
463
+ void processAssignment(assignment).catch((error) => {
464
+ logger?.error?.("[agent-sdk] assignment_background_failure", {
465
+ assignmentId: assignment.assignment_id,
466
+ error: toMessage(error)
467
+ });
468
+ });
469
+ }
470
+ return accepted;
471
+ };
472
+ }
473
+
474
+ // src/integrations.ts
475
+ function normalizeRecipients(recipients, label) {
476
+ if (!Array.isArray(recipients) || recipients.length === 0) {
477
+ throw new Error(`${label} must include at least one recipient`);
478
+ }
479
+ return recipients.map((recipient, index) => {
480
+ if (!recipient || typeof recipient.email !== "string" || recipient.email.trim().length === 0) {
481
+ throw new Error(`${label}[${index}] is missing email`);
482
+ }
483
+ return {
484
+ email: recipient.email.trim(),
485
+ ...typeof recipient.name === "string" && recipient.name.trim().length > 0 ? { name: recipient.name.trim() } : {}
486
+ };
487
+ });
488
+ }
489
+ function createIntegrationAction(input) {
490
+ if (typeof input.type !== "string" || input.type.trim().length === 0) {
491
+ throw new Error("type is required");
492
+ }
493
+ if (typeof input.operation !== "string" || input.operation.trim().length === 0) {
494
+ throw new Error("operation is required");
495
+ }
496
+ if (!input.input || typeof input.input !== "object" || Array.isArray(input.input)) {
497
+ throw new Error("input must be an object");
498
+ }
499
+ return {
500
+ type: input.type.trim(),
501
+ ...typeof input.actionKey === "string" && input.actionKey.trim().length > 0 ? { actionKey: input.actionKey.trim() } : {},
502
+ operation: input.operation.trim(),
503
+ input,
504
+ ...input.metadata ? { metadata: input.metadata } : {}
505
+ };
506
+ }
507
+ function createEmailDeliveryInput(input) {
508
+ if (typeof input.subject !== "string" || input.subject.trim().length === 0) {
509
+ throw new Error("Email subject is required");
510
+ }
511
+ if (typeof input.textBody !== "string" || input.textBody.trim().length === 0) {
512
+ throw new Error("Email textBody is required");
513
+ }
514
+ return {
515
+ to: normalizeRecipients(input.to, "to"),
516
+ ...input.cc && input.cc.length > 0 ? { cc: normalizeRecipients(input.cc, "cc") } : {},
517
+ ...input.bcc && input.bcc.length > 0 ? { bcc: normalizeRecipients(input.bcc, "bcc") } : {},
518
+ subject: input.subject.trim(),
519
+ textBody: input.textBody.trim(),
520
+ ...typeof input.htmlBody === "string" && input.htmlBody.trim().length > 0 ? { htmlBody: input.htmlBody } : {}
521
+ };
522
+ }
523
+ function createEmailDeliveryAction(input) {
524
+ const emailInput = createEmailDeliveryInput(input);
525
+ return {
526
+ ...createIntegrationAction({
527
+ ...input.actionKey ? { actionKey: input.actionKey } : {},
528
+ type: "email",
529
+ operation: input.mode,
530
+ input: emailInput,
531
+ ...input.metadata ? { metadata: input.metadata } : {}
532
+ }),
533
+ type: "email",
534
+ operation: input.mode,
535
+ input: emailInput
536
+ };
537
+ }
538
+ function isIntegrationAction(action) {
539
+ return typeof action.type === "string" && typeof action.operation === "string";
540
+ }
541
+ function isEmailDeliveryAction(action) {
542
+ return action.type === "email" && (action.operation === "draft" || action.operation === "send");
543
+ }
544
+
310
545
  // src/results.ts
311
546
  var DEFAULT_CONTACT_FIELDS = ["email", "phone", "profile_url", "linkedin_url"];
312
547
  function hasValue(value) {
@@ -359,15 +594,21 @@ export {
359
594
  DEFAULT_TIMESTAMP_HEADER,
360
595
  SdkError,
361
596
  computeWebhookSignature,
597
+ createAssignmentSlugRouter,
598
+ createAutoSubmitAssignmentHandler,
599
+ createEmailDeliveryAction,
362
600
  createExpressWebhookHandler,
363
601
  createFastifyWebhookHandler,
364
602
  createHonoWebhookHandler,
603
+ createIntegrationAction,
365
604
  createNextWebhookHandler,
366
605
  createTablePayload,
367
606
  createTableResult,
368
607
  createWebhookHandler,
369
608
  executeWebhook,
370
609
  getContractVersion,
610
+ isEmailDeliveryAction,
611
+ isIntegrationAction,
371
612
  parseAssignmentV1,
372
613
  toAssignmentEnvelopeV1,
373
614
  verifyWebhookSignature