@agrentingai/paperclip-adapter 0.2.2 → 0.4.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../server/src/index.ts","../../server/src/client.ts","../../server/src/crypto.ts","../../server/src/webhook-handler.ts","../../server/src/polling.ts","../../server/src/balance-monitor.ts","../../server/src/comment-sync.ts","../../server/src/adapter.ts"],"sourcesContent":["export { createServerAdapter } from \"./adapter.js\";\nexport { AgrentingClient } from \"./client.js\";\nexport {\n createWebhookHandler,\n registerTaskMapping,\n unregisterTaskMapping,\n getActiveTaskMappings,\n} from \"./webhook-handler.js\";\nexport type {\n AgrentingWebhookPayload,\n PaperclipApiClient,\n WebhookHandlerOptions,\n} from \"./webhook-handler.js\";\nexport {\n formatAgentResponse,\n forwardCommentToAgrenting,\n processIncomingMessage,\n} from \"./comment-sync.js\";\nexport { pollTaskUntilDone, getWebhookGracePeriodMs, POLL_INTERVALS_MS, MAX_POLLS, getBackoffMs } from \"./polling.js\";\nexport type { PollOptions, PollResult } from \"./polling.js\";\nexport {\n checkBalance,\n canSubmitTask,\n formatLowBalanceComment,\n formatInsufficientBalanceComment,\n} from \"./balance-monitor.js\";\nexport type { BalanceInfo, BalanceCheckOptions } from \"./balance-monitor.js\";\nexport { verifyWebhookSignature } from \"./crypto.js\";\nexport {\n registerWebhook,\n deregisterWebhook,\n hireAgent,\n getAgentProfile,\n sendMessageToTask,\n getTaskMessages,\n reassignTask,\n listCapabilities,\n sendMessageToHiring,\n getHiringMessages,\n retryHiring,\n getHiring,\n listHirings,\n autoSelectAgent,\n executeWithRetry,\n} from \"./adapter.js\";\nexport type {\n AgrentingAdapterConfig,\n AgrentingExecutionResult,\n AgrentingTaskStatus,\n AgrentingTask,\n AgentInfo,\n AgentProfile,\n HireAgentResult,\n SendMessageOptions,\n SendMessageResult,\n ReassignTaskResult,\n PaymentInfo,\n TransactionInfo,\n DiscoverAgentsOptions,\n CreateTaskPaymentOptions,\n Hiring,\n TaskMessage,\n HiringMessage,\n Capability,\n AutoSelectOptions,\n RetryHiringOptions,\n} from \"./types.js\";\n","import type {\n AgrentingAdapterConfig,\n AgrentingTask,\n AgentInfo,\n AgentProfile,\n BalanceInfo,\n HireAgentResult,\n PaymentInfo,\n ReassignTaskResult,\n SendMessageOptions,\n SendMessageResult,\n TransactionInfo,\n DiscoverAgentsOptions,\n CreateTaskPaymentOptions,\n Hiring,\n TaskMessage,\n HiringMessage,\n Capability,\n RetryHiringOptions,\n} from \"./types.js\";\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst MAX_RETRIES = 3;\n\n/**\n * HTTP client for the Agrenting REST API.\n * Wraps fetch with auth headers and base URL handling.\n */\nexport class AgrentingClient {\n private baseUrl: string;\n private apiKey: string;\n\n constructor(config: AgrentingAdapterConfig) {\n this.baseUrl = config.agrentingUrl.replace(/\\/+$/, \"\");\n this.apiKey = config.apiKey;\n }\n\n private headers(): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.apiKey,\n };\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<T> {\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: this.headers(),\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await response.text();\n const shouldRetry = response.status === 429 || response.status >= 500;\n\n if (shouldRetry && attempt < MAX_RETRIES) {\n clearTimeout(timer);\n // Respect Retry-After header on 429, otherwise use exponential backoff\n const retryAfter = response.headers.get(\"Retry-After\");\n let delayMs = Math.min(1000 * 2 ** attempt, 30_000);\n if (retryAfter) {\n // Retry-After can be seconds (integer) or a date string (HTTP-date)\n const seconds = parseInt(retryAfter, 10);\n if (!Number.isNaN(seconds) && seconds > 0) {\n delayMs = seconds * 1000;\n } else {\n // Try parsing as HTTP date\n const dateMs = Date.parse(retryAfter);\n if (!Number.isNaN(dateMs)) {\n delayMs = Math.max(0, dateMs - Date.now());\n }\n }\n }\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n continue;\n }\n\n throw new Error(\n `Agrenting API ${response.status}: ${text.slice(0, 500)}`\n );\n }\n\n const envelope = (await response.json()) as Record<string, unknown>;\n if (Array.isArray(envelope.errors) && envelope.errors.length) {\n throw new Error(`API errors: ${(envelope.errors as string[]).join(\", \")}`);\n }\n return (envelope.data ?? envelope) as T;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < MAX_RETRIES) {\n clearTimeout(timer);\n const delayMs = Math.min(1000 * 2 ** attempt, 30_000);\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n continue;\n }\n throw lastError;\n } finally {\n clearTimeout(timer);\n }\n }\n\n // Should never reach here, but satisfy the compiler\n throw lastError ?? new Error(\"Unexpected retry loop exit\");\n }\n\n /** Submit a new task to Agrenting.\n * When `maxPrice` is set, the task includes pricing info.\n * Call `createTaskPayment` after this to actually lock escrow funds.\n */\n async createTask(params: {\n providerAgentId: string;\n capability: string;\n input: string;\n /** Max price in USD. If set, the task will have a price for escrow. */\n maxPrice?: string;\n /** Payment type: \"crypto\" | \"escrow\" | \"nowpayments\" */\n paymentType?: string;\n }): Promise<AgrentingTask> {\n const body: Record<string, unknown> = {\n provider_agent_id: params.providerAgentId,\n capability: params.capability,\n input: params.input,\n };\n if (params.maxPrice) {\n body.max_price = params.maxPrice;\n }\n return this.request(\"POST\", \"/api/v1/tasks\", body);\n }\n\n /** Create a payment for an existing task to lock escrow funds.\n * This is the step that actually deducts funds from the client's balance\n * and places them in escrow for the task.\n */\n async createTaskPayment(\n taskId: string,\n options: CreateTaskPaymentOptions = {}\n ): Promise<PaymentInfo> {\n const body: Record<string, unknown> = {\n task_id: taskId,\n };\n if (options.cryptoCurrency) body.crypto_currency = options.cryptoCurrency;\n if (options.paymentType) body.payment_type = options.paymentType;\n return this.request(\"POST\", `/api/v1/tasks/${taskId}/payments`, body);\n }\n\n /** Get payment info for a task */\n async getTaskPayment(taskId: string): Promise<PaymentInfo> {\n return this.request(\"GET\", `/api/v1/tasks/${taskId}/payments`);\n }\n\n /** Get the status and result of a task */\n async getTask(taskId: string): Promise<AgrentingTask> {\n return this.request<AgrentingTask>(\"GET\", `/api/v1/tasks/${taskId}`);\n }\n\n /** Get task timeline events (progress, attempts, status changes) */\n async getTaskTimeline(taskId: string): Promise<{\n events: Array<{\n event_type: string;\n timestamp: string;\n progress_percent?: number;\n progress_message?: string;\n details?: Record<string, unknown>;\n }>;\n }> {\n return this.request(\"GET\", `/api/v1/tasks/${taskId}/timeline`);\n }\n\n /** Get attempt history for a task */\n async getTaskAttempts(taskId: string): Promise<{\n attempts: Array<{\n id: string;\n status: string;\n created_at: string;\n completed_at?: string;\n error_reason?: string;\n }>;\n }> {\n return this.request(\"GET\", `/api/v1/tasks/${taskId}/attempts`);\n }\n\n /** Get current progress of a task */\n async getTaskProgress(taskId: string): Promise<{\n status: string;\n progress_percent: number;\n progress_message?: string;\n updated_at: string;\n }> {\n const task = await this.getTask(taskId);\n return {\n status: task.status,\n progress_percent: task.progress_percent ?? 0,\n progress_message: task.progress_message,\n updated_at: task.updated_at,\n };\n }\n\n /** Register a webhook to receive task lifecycle events.\n * Sends a flat request body matching the backend's expected shape.\n */\n async registerWebhook(params: {\n callbackUrl: string;\n eventTypes?: string[];\n }): Promise<{\n id: string;\n callback_url: string;\n event_types: string[];\n secret_key: string;\n status: string;\n }> {\n return this.request(\"POST\", \"/api/v1/webhooks\", {\n callback_url: params.callbackUrl,\n event_types: params.eventTypes ?? [\n \"task.created\",\n \"task.claimed\",\n \"task.in_progress\",\n \"task.completed\",\n \"task.failed\",\n \"task.cancelled\",\n ],\n });\n }\n\n /** List registered webhooks */\n async listWebhooks(): Promise<\n Array<{\n id: string;\n callback_url: string;\n event_types: string[];\n status: string;\n last_delivery_at?: string;\n failure_count: number;\n }>\n > {\n return this.request(\"GET\", \"/api/v1/webhooks\");\n }\n\n /** Delete a registered webhook */\n async deleteWebhook(webhookId: string): Promise<void> {\n return this.request(\"DELETE\", `/api/v1/webhooks/${webhookId}`);\n }\n\n /** Cancel a task by ID */\n async cancelTask(taskId: string): Promise<AgrentingTask> {\n return this.request(\"POST\", `/api/v1/tasks/${taskId}/cancel`);\n }\n\n /** Discover marketplace agents available for hire.\n * Filters by capability, price range, reputation, and availability.\n */\n async discoverAgents(\n options: DiscoverAgentsOptions = {}\n ): Promise<AgentInfo[]> {\n const params = new URLSearchParams();\n if (options.capability) params.set(\"capability\", options.capability);\n if (options.minPrice) params.set(\"min_price\", options.minPrice.toFixed(2));\n if (options.maxPrice) params.set(\"max_price\", options.maxPrice.toFixed(2));\n if (options.minReputation)\n params.set(\"min_reputation\", String(options.minReputation));\n if (options.sortBy) params.set(\"sort_by\", options.sortBy);\n if (options.limit) params.set(\"limit\", String(options.limit));\n\n return this.request<AgentInfo[]>(\n \"GET\",\n `/api/v1/agents/discover?${params}`\n );\n }\n\n /** Fetch the current platform balance including available, escrowed, and total. */\n async getBalance(): Promise<BalanceInfo> {\n return this.request(\"GET\", \"/api/v1/ledger/balance\");\n }\n\n /** List recent transactions for the authenticated agent. */\n async getTransactions(\n options: { limit?: number; offset?: number; type?: string } = {}\n ): Promise<TransactionInfo[]> {\n const params = new URLSearchParams();\n if (options.limit) params.set(\"limit\", String(options.limit));\n if (options.offset) params.set(\"offset\", String(options.offset));\n if (options.type) params.set(\"type\", options.type);\n\n return this.request<TransactionInfo[]>(\n \"GET\",\n `/api/v1/ledger/transactions?${params}`\n );\n }\n\n /** Deposit funds into the Agrenting ledger. */\n async deposit(params: {\n amount: string;\n currency?: string;\n paymentMethod?: string;\n }): Promise<{\n transaction_id: string;\n status: string;\n deposit_address?: string;\n payment_url?: string;\n }> {\n return this.request(\"POST\", \"/api/v1/ledger/deposit\", {\n amount: params.amount,\n currency: params.currency ?? \"USD\",\n payment_method: params.paymentMethod ?? \"crypto\",\n });\n }\n\n /** Withdraw funds from the Agrenting ledger to an external wallet. */\n async withdraw(params: {\n amount: string;\n currency?: string;\n withdrawalAddressId?: string;\n }): Promise<{\n transaction_id: string;\n status: string;\n }> {\n return this.request(\"POST\", \"/api/v1/ledger/withdraw\", {\n amount: params.amount,\n currency: params.currency ?? \"USD\",\n withdrawal_address_id: params.withdrawalAddressId,\n });\n }\n\n /** Create a payment intent for off-platform payment processing. */\n async createPaymentIntent(params: {\n amount: string;\n currency?: string;\n paymentType?: string;\n }): Promise<{\n id: string;\n status: string;\n payment_url?: string;\n address?: string;\n }> {\n return this.request(\"POST\", \"/api/v1/payments/create-intent\", {\n amount: params.amount,\n currency: params.currency ?? \"USD\",\n payment_type: params.paymentType ?? \"crypto\",\n });\n }\n\n /** Validate connectivity and API key by fetching the account balance */\n async testConnection(): Promise<{ ok: boolean; message: string }> {\n try {\n const data = await this.request<{\n available?: string;\n escrow?: string;\n total?: string;\n currency?: string;\n }>(\"GET\", \"/api/v1/ledger/balance\");\n return {\n ok: true,\n message: `Connected. Balance: ${data.total ?? data.available ?? \"N/A\"} ${data.currency ?? \"USD\"} (Available: ${data.available ?? \"N/A\"})`,\n };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : \"Unknown connection error\",\n };\n }\n }\n\n /** Upload a document (e.g. instructions) to Agrenting.\n * Uses the dedicated uploads endpoint which accepts base64-encoded content,\n * separate from the deal-scoped `/api/v1/documents` endpoint.\n */\n async uploadDocument(params: {\n name: string;\n content: string;\n contentType?: string;\n documentType?: string;\n taskId?: string;\n }): Promise<{\n id: string;\n name: string;\n file_url: string;\n content_type: string;\n file_hash: string;\n document_type: string;\n }> {\n const contentBase64 = Buffer.from(params.content).toString(\"base64\");\n return this.request(\"POST\", \"/api/v1/uploads\", {\n name: params.name,\n content: contentBase64,\n content_type: params.contentType ?? \"text/plain\",\n document_type: params.documentType ?? \"instructions\",\n task_id: params.taskId,\n });\n }\n\n /** Get the full profile of an agent by DID.\n * Returns capabilities, pricing tiers, reviews, and availability.\n */\n async getAgentProfile(agentDid: string): Promise<AgentProfile> {\n return this.request(\"GET\", `/api/v1/agents/${encodeURIComponent(agentDid)}`);\n }\n\n /** Hire/bind an agent to your account.\n * Returns adapter config so Paperclip can auto-provision the agent.\n */\n async hireAgent(\n agentDid: string,\n options: { pricingModel?: string } = {}\n ): Promise<HireAgentResult> {\n const body: Record<string, unknown> = {};\n if (options.pricingModel) body.pricing_model = options.pricingModel;\n return this.request(\n \"POST\",\n `/api/v1/agents/${encodeURIComponent(agentDid)}/hire`,\n body\n );\n }\n\n /** Send a message to a running task (mid-task instructions, feedback, or questions).\n * Enables bidirectional communication between the Paperclip user and the remote agent.\n */\n async sendMessageToTask(\n taskId: string,\n options: SendMessageOptions\n ): Promise<SendMessageResult> {\n return this.request(\"POST\", `/api/v1/tasks/${taskId}/messages`, {\n message: options.message,\n message_type: options.messageType ?? \"instruction\",\n });\n }\n\n /** Get messages for a task.\n * GET /api/v1/tasks/:id/messages\n */\n async getTaskMessages(taskId: string): Promise<TaskMessage[]> {\n return this.request<TaskMessage[]>(\n \"GET\",\n `/api/v1/tasks/${taskId}/messages`\n );\n }\n\n /** Reassign a failed or cancelled task to a different agent.\n * If `newAgentDid` is omitted, the platform picks the best available agent.\n */\n async reassignTask(\n taskId: string,\n newAgentDid?: string\n ): Promise<ReassignTaskResult> {\n const body: Record<string, unknown> = {};\n if (newAgentDid) {\n body.new_provider_agent_did = newAgentDid;\n }\n return this.request<ReassignTaskResult>(\n \"POST\",\n `/api/v1/tasks/${taskId}/reassign`,\n body\n );\n }\n\n /** List all available capabilities with descriptions and usage stats.\n * GET /api/v1/capabilities\n */\n async listCapabilities(): Promise<Capability[]> {\n return this.request<Capability[]>(\"GET\", \"/api/v1/capabilities\");\n }\n\n /** Send a message to a hiring for communication with the hired agent.\n * POST /api/v1/hirings/:id/messages\n */\n async sendMessageToHiring(\n hiringId: string,\n content: string\n ): Promise<HiringMessage> {\n if (content.length > 5000) {\n throw new Error(\"Message content exceeds 5000 character limit\");\n }\n return this.request<HiringMessage>(\n \"POST\",\n `/api/v1/hirings/${hiringId}/messages`,\n { content }\n );\n }\n\n /** Get messages for a hiring.\n * GET /api/v1/hirings/:id/messages\n */\n async getHiringMessages(hiringId: string): Promise<HiringMessage[]> {\n return this.request<HiringMessage[]>(\n \"GET\",\n `/api/v1/hirings/${hiringId}/messages`\n );\n }\n\n /** Retry a failed hiring.\n * POST /api/v1/hirings/:id/retry\n */\n async retryHiring(\n hiringId: string,\n options: RetryHiringOptions = {}\n ): Promise<Hiring> {\n const body: Record<string, unknown> = {};\n if (options.reason) {\n body.reason = options.reason;\n }\n return this.request<Hiring>(\n \"POST\",\n `/api/v1/hirings/${hiringId}/retry`,\n body\n );\n }\n\n /** Get a hiring by ID.\n * GET /api/v1/hirings/:id\n */\n async getHiring(hiringId: string): Promise<Hiring> {\n return this.request<Hiring>(\"GET\", `/api/v1/hirings/${hiringId}`);\n }\n\n /** List hirings for the authenticated agent.\n * GET /api/v1/hirings\n */\n async listHirings(options: {\n status?: string;\n limit?: number;\n offset?: number;\n } = {}): Promise<Hiring[]> {\n const params = new URLSearchParams();\n if (options.status) params.set(\"status\", options.status);\n if (options.limit) params.set(\"limit\", String(options.limit));\n if (options.offset) params.set(\"offset\", String(options.offset));\n const query = params.toString() ? `?${params}` : \"\";\n return this.request<Hiring[]>(\"GET\", `/api/v1/hirings${query}`);\n }\n\n /** List agents filtered by capability for auto-select.\n * GET /api/v1/agents?capability=X\n */\n async listAgentsByCapability(capability: string): Promise<AgentProfile[]> {\n return this.request<AgentProfile[]>(\n \"GET\",\n `/api/v1/agents?capability=${encodeURIComponent(capability)}`\n );\n }\n}\n","/**\n * Shared cryptographic utilities for the Agrenting adapter.\n */\n\n/**\n * Verify an HMAC-SHA256 signature against a raw request body.\n * Uses constant-time comparison to prevent timing attacks.\n */\nexport async function verifyWebhookSignature(\n rawBody: string,\n signature: string,\n secret: string\n): Promise<boolean> {\n const crypto = await import(\"crypto\");\n const expected = crypto\n .createHmac(\"sha256\", secret)\n .update(rawBody)\n .digest(\"base64\");\n const sigBuf = Buffer.from(signature);\n const expectedBuf = Buffer.from(expected);\n if (sigBuf.byteLength !== expectedBuf.byteLength) {\n return false;\n }\n return crypto.timingSafeEqual(sigBuf, expectedBuf);\n}\n","/**\n * Paperclip-side webhook handler for Agrenting task events.\n *\n * This module provides:\n * - An HTTP request handler that processes incoming webhook payloads from Agrenting\n * - Task ID to Paperclip issue ID mapping registry\n * - Automatic issue status updates and comment posting on task events\n *\n * Usage: Paperclip mounts this handler at `POST /api/webhooks/agrenting/:companyId`.\n * The handler receives raw body, headers, and a Paperclip API client to update issues.\n */\n\nimport type { IncomingHttpHeaders } from \"http\";\nimport type { AgrentingAdapterConfig } from \"./types.js\";\nimport { verifyWebhookSignature } from \"./crypto.js\";\n\n// ---------------------------------------------------------------------------\n// Task → Issue mapping registry\n// ---------------------------------------------------------------------------\n\ninterface TaskMapping {\n issueId: string;\n companyId: string;\n config: AgrentingAdapterConfig;\n startedAt: number;\n status: string;\n}\n\nconst taskRegistry = new Map<string, TaskMapping>();\n\nconst TASK_REGISTRY_TTL_MS = 2 * 60 * 60 * 1000; // 2h — max age before cleanup\nconst TASK_REGISTRY_CLEANUP_INTERVAL_MS = 60_000; // 60s sweep interval\nlet registryCleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n/**\n * Sweep taskRegistry for entries older than the TTL.\n * Called periodically to bound memory growth if terminal events are lost.\n */\nfunction sweepStaleRegistryEntries(): void {\n const now = Date.now();\n for (const [id, entry] of taskRegistry) {\n if (now - entry.startedAt > TASK_REGISTRY_TTL_MS) {\n taskRegistry.delete(id);\n }\n }\n}\n\n/**\n * Start the periodic registry cleanup timer.\n * Safe to call multiple times — only one timer runs at a time.\n */\nexport function startRegistryCleanup(): void {\n if (registryCleanupTimer) return;\n registryCleanupTimer = setInterval(sweepStaleRegistryEntries, TASK_REGISTRY_CLEANUP_INTERVAL_MS);\n registryCleanupTimer.unref();\n}\n\n/**\n * Stop the periodic registry cleanup timer.\n */\nexport function stopRegistryCleanup(): void {\n if (registryCleanupTimer) {\n clearInterval(registryCleanupTimer);\n registryCleanupTimer = null;\n }\n}\n\n/**\n * Register a mapping between an Agrenting task ID and a Paperclip issue.\n * Call this before executing a task so the webhook handler knows which issue to update.\n */\nexport function registerTaskMapping(\n taskId: string,\n issueId: string,\n companyId: string,\n config: AgrentingAdapterConfig\n): void {\n taskRegistry.set(taskId, {\n issueId,\n companyId,\n config,\n startedAt: Date.now(),\n status: \"pending\",\n });\n}\n\n/**\n * Remove a task mapping from the registry.\n */\nexport function unregisterTaskMapping(taskId: string): void {\n taskRegistry.delete(taskId);\n}\n\n/**\n * Get all active task mappings.\n */\nexport function getActiveTaskMappings(): ReadonlyMap<string, TaskMapping> {\n return taskRegistry;\n}\n\n// ---------------------------------------------------------------------------\n// Webhook payload types\n// ---------------------------------------------------------------------------\n\nexport interface AgrentingWebhookPayload {\n task_id: string;\n status: string;\n output?: string;\n error_reason?: string;\n progress_percent?: number;\n progress_message?: string;\n completed_at?: string;\n created_at?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Paperclip API client interface\n// ---------------------------------------------------------------------------\n\nexport interface PaperclipApiClient {\n /** Update an issue's status and optionally post a comment */\n updateIssue(issueId: string, body: {\n status?: string;\n comment?: string;\n }): Promise<void>;\n\n /** Post a comment on an issue without changing status */\n postComment(issueId: string, body: string): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// Event handlers\n// ---------------------------------------------------------------------------\n\ninterface EventHandlerContext {\n api: PaperclipApiClient;\n mapping: TaskMapping;\n payload: AgrentingWebhookPayload;\n}\n\nconst eventHandlers: Record<\n string,\n (ctx: EventHandlerContext) => Promise<void>\n> = {\n \"task.created\": async (ctx) => {\n ctx.mapping.status = \"pending\";\n await ctx.api.postComment(\n ctx.mapping.issueId,\n `**Agrenting task created** — Task \\`${ctx.payload.task_id}\\` submitted and awaiting claim.`\n );\n },\n\n \"task.claimed\": async (ctx) => {\n ctx.mapping.status = \"claimed\";\n await ctx.api.postComment(\n ctx.mapping.issueId,\n `**Agrenting task claimed** — An agent has picked up the task and is preparing to work.`\n );\n },\n\n \"task.in_progress\": async (ctx) => {\n ctx.mapping.status = \"in_progress\";\n const progress = ctx.payload.progress_percent\n ? ` (${ctx.payload.progress_percent}%)`\n : \"\";\n const message = ctx.payload.progress_message\n ? ` — ${ctx.payload.progress_message}`\n : \"\";\n await ctx.api.postComment(\n ctx.mapping.issueId,\n `**Task in progress**${progress}${message}`\n );\n },\n\n \"task.completed\": async (ctx) => {\n ctx.mapping.status = \"completed\";\n const duration = ((Date.now() - ctx.mapping.startedAt) / 1000).toFixed(1);\n await ctx.api.updateIssue(ctx.mapping.issueId, {\n status: \"done\",\n comment: `**Agrenting task completed** — Task \\`${ctx.payload.task_id}\\` finished in ${duration}s.${\n ctx.payload.output ? `\\n\\n### Output\\n\\n${ctx.payload.output}` : \"\"\n }`,\n });\n unregisterTaskMapping(ctx.payload.task_id);\n },\n\n \"task.failed\": async (ctx) => {\n ctx.mapping.status = \"failed\";\n await ctx.api.updateIssue(ctx.mapping.issueId, {\n status: \"blocked\",\n comment: `**Agrenting task failed** — Task \\`${ctx.payload.task_id}\\` encountered an error.\\n\\n**Error:** ${ctx.payload.error_reason ?? \"No error reason provided.\"}`,\n });\n unregisterTaskMapping(ctx.payload.task_id);\n },\n\n \"task.cancelled\": async (ctx) => {\n ctx.mapping.status = \"cancelled\";\n await ctx.api.updateIssue(ctx.mapping.issueId, {\n status: \"cancelled\",\n comment: `**Agrenting task cancelled** — Task \\`${ctx.payload.task_id}\\` was cancelled.`,\n });\n unregisterTaskMapping(ctx.payload.task_id);\n },\n};\n\n// ---------------------------------------------------------------------------\n// Webhook handler factory\n// ---------------------------------------------------------------------------\n\nexport interface WebhookHandlerOptions {\n /** Secret used to verify HMAC signatures */\n webhookSecret: string;\n /** Paperclip API client for updating issues */\n api: PaperclipApiClient;\n /** Optional: handle unknown event types */\n onUnknownEvent?: (event: string, payload: AgrentingWebhookPayload) => void;\n}\n\n/**\n * Create a webhook handler function suitable for mounting in an HTTP server.\n *\n * The returned handler expects `(rawBody, headers)` and returns a Promise\n * resolving to `{ status, body, headers }` for the HTTP response.\n *\n * This design is framework-agnostic: Paperclip can wrap it in Express,\n * Fastify, or a raw Node.js http server.\n */\nexport function createWebhookHandler(options: WebhookHandlerOptions) {\n startRegistryCleanup();\n return async function handleWebhookRequest(\n rawBody: string,\n headers: IncomingHttpHeaders\n ): Promise<{ status: number; body: string; headers?: Record<string, string> }> {\n const signature =\n (headers[\"x-webhook-signature\"] as string) ??\n (headers[\"X-Webhook-Signature\"] as string) ??\n \"\";\n const eventType =\n (headers[\"x-webhook-event\"] as string) ??\n (headers[\"X-Webhook-Event\"] as string) ??\n \"\";\n\n // Parse payload\n let payload: AgrentingWebhookPayload;\n try {\n payload = JSON.parse(rawBody);\n } catch {\n return { status: 400, body: \"Invalid JSON\" };\n }\n\n // Verify signature\n const valid = await verifyWebhookSignature(\n rawBody,\n signature,\n options.webhookSecret\n );\n if (!valid) {\n return { status: 401, body: \"Invalid signature\" };\n }\n\n // Look up task mapping\n const taskId = payload.task_id;\n if (!taskId) {\n return { status: 400, body: \"Missing task_id in payload\" };\n }\n\n const mapping = taskRegistry.get(taskId);\n if (!mapping) {\n // Webhook received but no active mapping — task may have been handled\n // by the in-process listener already, or the mapping was cleaned up.\n return { status: 200, body: \"OK (no active mapping)\" };\n }\n\n // Dispatch to event handler\n const handler = eventHandlers[eventType];\n if (handler) {\n try {\n await handler({ api: options.api, mapping, payload });\n } catch (err) {\n console.error(\"[adapter-agrenting] Webhook handler error:\", err);\n return {\n status: 500,\n body: \"Internal error\",\n };\n }\n } else {\n options.onUnknownEvent?.(eventType, payload);\n }\n\n return { status: 200, body: \"OK\" };\n };\n}\n","/**\n * Fallback polling logic for Agrenting task status.\n *\n * Used when webhooks are delayed or fail to deliver.\n * Polls with exponential backoff: 10s → 30s → 60s → 120s (max 10 polls).\n */\n\nimport { AgrentingClient } from \"./client.js\";\nimport type {\n AgrentingAdapterConfig,\n AgrentingExecutionResult,\n AgrentingTask,\n} from \"./types.js\";\n\n/** Poll intervals in milliseconds (exponential backoff) — shared across polling modes */\nexport const POLL_INTERVALS_MS = [10_000, 30_000, 60_000, 120_000];\nexport const MAX_POLLS = 10;\n\n/** Compute the backoff duration for a given poll attempt (0-indexed). */\nexport function getBackoffMs(attempt: number): number {\n const index = Math.min(attempt, POLL_INTERVALS_MS.length - 1);\n return POLL_INTERVALS_MS[index];\n}\n\nexport interface PollOptions {\n config: AgrentingAdapterConfig;\n taskId: string;\n /** Deadline in ms (Date.now() + timeoutMs) */\n deadline: number;\n /** Optional callback fired on each poll cycle with the current task state */\n onStatusUpdate?: (task: AgrentingTask, pollAttempt: number) => void;\n /** Starting poll attempt (useful for resuming after a webhook delay) */\n startAttempt?: number;\n /** AbortSignal to cancel polling early (e.g., when a webhook resolves first) */\n signal?: AbortSignal;\n}\n\nexport interface PollResult {\n /** Final execution result */\n result: AgrentingExecutionResult;\n /** Number of polls performed */\n pollCount: number;\n /** Whether the result came from polling (true) or was already resolved */\n viaPolling: boolean;\n}\n\n/**\n * Poll the Agrenting task API with exponential backoff until the task\n * reaches a terminal state or the deadline is reached.\n */\nexport async function pollTaskUntilDone(\n options: PollOptions\n): Promise<PollResult> {\n const client = new AgrentingClient(options.config);\n let pollAttempt = options.startAttempt ?? 0;\n const startTime = Date.now();\n\n while (pollAttempt < MAX_POLLS) {\n // Check if polling was aborted (e.g., webhook resolved first)\n if (options.signal?.aborted) {\n return {\n result: {\n success: false,\n error: \"Polling aborted\",\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n }\n\n const now = Date.now();\n if (now >= options.deadline) {\n return {\n result: {\n success: false,\n error: `Task timed out after ${options.config.timeoutSec ?? 600}s`,\n taskId: options.taskId,\n durationMs: now - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n }\n\n // Wait for the next poll interval (respects abort signal).\n // Skip the wait on the first iteration so the first poll is immediate.\n if (pollAttempt > 0) {\n const waitMs = getBackoffMs(pollAttempt);\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, waitMs);\n if (options.signal) {\n options.signal.addEventListener(\"abort\", () => {\n clearTimeout(timer);\n resolve();\n }, { once: true });\n }\n });\n }\n\n const task = await client.getTask(options.taskId);\n pollAttempt++;\n\n options.onStatusUpdate?.(task, pollAttempt);\n\n if (task.status === \"completed\") {\n return {\n result: {\n success: true,\n output: task.output,\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n }\n\n if (task.status === \"failed\") {\n return {\n result: {\n success: false,\n error: task.error_reason ?? \"Task failed with no reason provided\",\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n }\n\n if (task.status === \"cancelled\") {\n return {\n result: {\n success: false,\n error: \"Task was cancelled\",\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n }\n }\n\n // Max polls reached without terminal state — do one final check\n const finalTask = await client.getTask(options.taskId);\n if (finalTask.status === \"completed\") {\n return {\n result: {\n success: true,\n output: finalTask.output,\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt + 1,\n viaPolling: true,\n };\n }\n\n return {\n result: {\n success: false,\n error: `Task did not complete after ${pollAttempt} polls (max ${MAX_POLLS})`,\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n}\n\n/**\n * Calculate when to activate fallback polling.\n * Returns the number of ms to wait before switching from webhook\n * wait mode to polling mode.\n */\nexport function getWebhookGracePeriodMs(config: AgrentingAdapterConfig): number {\n // Default: 60 seconds. If the timeout is very short, use a fraction of it.\n const timeoutMs = (config.timeoutSec ?? 600) * 1000;\n return Math.min(60_000, timeoutMs * 0.1);\n}\n","/**\n * Balance monitoring for the Agrenting adapter.\n *\n * Monitors the platform balance via `GET /api/v1/ledger/balance`\n * and provides low-balance warnings and pre-submission checks.\n */\n\nimport { AgrentingClient } from \"./client.js\";\nimport type { AgrentingAdapterConfig } from \"./types.js\";\n\nexport interface BalanceInfo {\n available: number;\n escrow: number;\n total: number;\n currency: string;\n isLow: boolean;\n isInsufficient: boolean;\n}\n\nexport interface BalanceCheckOptions {\n config: AgrentingAdapterConfig;\n /** Low balance threshold in USD (default: $10) */\n lowBalanceThresholdUsd?: number;\n /** Minimum balance required to submit a task in USD (default: $1) */\n minSubmissionBalanceUsd?: number;\n}\n\n/**\n * Fetch the current platform balance and evaluate thresholds.\n * The server returns { available, escrow, total } — we use `available`\n * for threshold checks since escrowed funds are already committed.\n */\nexport async function checkBalance(\n options: BalanceCheckOptions\n): Promise<BalanceInfo> {\n const client = new AgrentingClient(options.config);\n const lowThreshold = options.lowBalanceThresholdUsd ?? 10;\n const minSubmission = options.minSubmissionBalanceUsd ?? 1;\n\n try {\n const raw = await client.getBalance();\n const available = parseFloat(raw.available);\n const escrow = parseFloat(raw.escrow);\n const total = parseFloat(raw.total);\n\n const anyNaN = Number.isNaN(available) || Number.isNaN(escrow) || Number.isNaN(total);\n if (anyNaN) {\n return {\n available: 0,\n escrow: 0,\n total: 0,\n currency: raw.currency ?? \"USD\",\n isLow: true,\n isInsufficient: true,\n };\n }\n\n return {\n available,\n escrow,\n total,\n currency: raw.currency ?? \"USD\",\n isLow: available < lowThreshold,\n isInsufficient: available < minSubmission,\n };\n } catch {\n // If we can't fetch balance, assume insufficient to avoid failed submissions\n return {\n available: 0,\n escrow: 0,\n total: 0,\n currency: \"USD\",\n isLow: true,\n isInsufficient: true,\n };\n }\n}\n\n/**\n * Pre-submission balance check.\n * Returns { ok: true } if sufficient, or { ok: false, reason } if not.\n */\nexport async function canSubmitTask(\n options: BalanceCheckOptions\n): Promise<{ ok: true } | { ok: false; reason: string }> {\n const balanceInfo = await checkBalance(options);\n\n if (balanceInfo.isInsufficient) {\n return {\n ok: false,\n reason: `Insufficient balance: ${formatUsd(balanceInfo.available)}. Minimum required: ${formatUsd(options.minSubmissionBalanceUsd ?? 1)}.`,\n };\n }\n\n return { ok: true };\n}\n\n/**\n * Format a USD amount as a human-readable dollar string.\n */\nfunction formatUsd(amount: number): string {\n return `$${amount.toFixed(2)}`;\n}\n\n/**\n * Generate a warning comment for low balance.\n * Returns the markdown comment to post on the Paperclip issue.\n */\nexport function formatLowBalanceComment(balanceInfo: BalanceInfo): string {\n return `**Agrenting balance warning** — Available: ${formatUsd(balanceInfo.available)} ${balanceInfo.currency} (Escrowed: ${formatUsd(balanceInfo.escrow)}). Funds are running low. Add credits to avoid task submission failures.`;\n}\n\n/**\n * Generate a blocking comment for insufficient balance.\n */\nexport function formatInsufficientBalanceComment(balanceInfo: BalanceInfo): string {\n return `**Agrenting task blocked** — Insufficient balance: ${formatUsd(balanceInfo.available)} ${balanceInfo.currency}. Please add credits to your Agrenting account before retrying.`;\n}\n","/**\n * Comment formatting utilities for bidirectional sync between\n * Paperclip issues and Agrenting task message threads.\n */\n\nimport type { AgrentingAdapterConfig, TaskMessage, SendMessageResult } from \"./types.js\";\nimport { AgrentingClient } from \"./client.js\";\n\n/**\n * Process an Agrenting agent response and return the comment body\n * that should be posted on the Paperclip issue.\n *\n * This is called by the webhook handler when it receives task output\n * or progress messages that should appear as comments.\n */\nexport function formatAgentResponse(\n agentName: string,\n message: string\n): string {\n return `**${agentName} says:**\\n\\n${message}`;\n}\n\n/**\n * Forward a comment from Paperclip to the Agrenting task.\n * Used for bidirectional comment sync when the user adds a comment\n * to a Paperclip issue that has an active Agrenting task.\n *\n * @param config - Agrenting adapter configuration\n * @param taskId - The Agrenting task ID\n * @param comment - The comment content to forward\n * @param authorName - Optional author name for attribution\n * @returns The created TaskMessage or null if forwarding failed\n */\nexport async function forwardCommentToAgrenting(\n config: AgrentingAdapterConfig,\n taskId: string,\n comment: string,\n authorName?: string\n): Promise<SendMessageResult | null> {\n const client = new AgrentingClient(config);\n\n // Format the comment for Agrenting\n const formattedComment = authorName\n ? `[${authorName}]: ${comment}`\n : comment;\n\n try {\n return await client.sendMessageToTask(taskId, { message: formattedComment });\n } catch (err) {\n // Log but don't throw — comment sync is non-critical\n console.error(\n `[adapter-agrenting] Failed to forward comment to task ${taskId}:`,\n err instanceof Error ? err.message : String(err)\n );\n return null;\n }\n}\n\n/**\n * Process incoming Agrenting messages and format them for Paperclip.\n * Called by the webhook handler when it receives task messages.\n *\n * @param message - The incoming TaskMessage from Agrenting\n * @returns Formatted comment body for Paperclip\n */\nexport function processIncomingMessage(\n message: TaskMessage\n): string {\n const senderName = message.sender_name ?? \"Agent\";\n return formatAgentResponse(senderName, message.content);\n}\n","import { AgrentingClient } from \"./client.js\";\nimport type {\n AgrentingAdapterConfig,\n AgrentingExecutionResult,\n AgrentingTaskStatus,\n AgentInfo,\n AgentProfile,\n BalanceInfo as BalanceInfoRaw,\n HireAgentResult,\n PaymentInfo,\n ReassignTaskResult,\n SendMessageResult,\n TransactionInfo,\n DiscoverAgentsOptions,\n CreateTaskPaymentOptions,\n Hiring,\n TaskMessage,\n HiringMessage,\n Capability,\n AutoSelectOptions,\n} from \"./types.js\";\nimport { registerTaskMapping } from \"./webhook-handler.js\";\nimport { pollTaskUntilDone } from \"./polling.js\";\nimport { canSubmitTask } from \"./balance-monitor.js\";\nimport { verifyWebhookSignature } from \"./crypto.js\";\nimport { formatAgentResponse } from \"./comment-sync.js\";\n\nconst DEFAULT_WEBHOOK_PORT = 8765;\nconst MAX_WEBHOOK_BODY_SIZE = 1024 * 1024; // 1MB — prevent OOM from oversized bodies\nconst STALE_TASK_CLEANUP_INTERVAL_MS = 60_000; // 60s\nconst STALE_TASK_TTL_MS = 2 * 60 * 60 * 1000; // 2h — max age before cleanup sweeps it\n\n/** In-memory store for webhook listeners keyed by task ID */\nconst pendingTasks = new Map<\n string,\n {\n resolve: (result: AgrentingExecutionResult) => void;\n status: AgrentingTaskStatus;\n progressPercent: number;\n progressMessage?: string;\n startedAt: number;\n createdAt: number;\n settled: boolean;\n }\n>();\n\nlet webhookServer: ReturnType<typeof import(\"http\").createServer> | null = null;\nlet staleCleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n/**\n * Sweep pendingTasks for entries that are settled or older than the TTL,\n * removing them from the map to bound memory usage.\n */\nfunction sweepStaleTasks(): void {\n const now = Date.now();\n for (const [id, entry] of pendingTasks) {\n if (entry.settled || now - entry.createdAt > STALE_TASK_TTL_MS) {\n pendingTasks.delete(id);\n }\n }\n}\n\n/**\n * JSON Schema for Agrenting adapter configuration fields.\n * Used by Paperclip server to validate adapter config at creation time.\n */\nexport function getConfigSchema(): Record<string, unknown> {\n return {\n type: \"object\",\n required: [\"agrentingUrl\", \"apiKey\", \"agentDid\"],\n properties: {\n agrentingUrl: {\n type: \"string\",\n format: \"uri\",\n description: \"Agrenting platform URL (e.g. https://www.agrenting.com)\",\n default: \"https://www.agrenting.com\",\n },\n apiKey: {\n type: \"string\",\n description: \"Agrenting API key for authentication\",\n sensitive: true,\n },\n agentDid: {\n type: \"string\",\n description:\n \"Decentralized identifier of the target agent (did:agrenting:...)\",\n },\n webhookSecret: {\n type: \"string\",\n description: \"Webhook signing secret for task completion callbacks\",\n sensitive: true,\n },\n webhookCallbackUrl: {\n type: \"string\",\n format: \"uri\",\n description:\n \"URL where Agrenting should POST task events (e.g. https://your-host:8765/webhook)\",\n },\n pricingModel: {\n type: \"string\",\n enum: [\"fixed\", \"per-token\", \"subscription\"],\n description: \"Pricing model for this agent\",\n default: \"fixed\",\n },\n timeoutSec: {\n type: \"integer\",\n minimum: 10,\n maximum: 3600,\n description: \"Task timeout in seconds\",\n default: 600,\n },\n instructionsBundleMode: {\n type: \"string\",\n enum: [\"managed\", \"inline\"],\n description: \"How agent instructions are delivered\",\n default: \"inline\",\n },\n },\n };\n}\n\n/**\n * Validate the adapter configuration and test connectivity.\n */\nexport async function testEnvironment(\n config: AgrentingAdapterConfig\n): Promise<{ ok: boolean; message: string }> {\n const client = new AgrentingClient(config);\n return client.testConnection();\n}\n\n/**\n * Start an HTTP listener that receives webhook callbacks from Agrenting.\n * Returns the base URL of the listener (for registering with Agrenting).\n *\n * The listener resolves pending `execute()` calls when task events arrive.\n * Only call this once per process — subsequent calls return the existing server.\n */\nexport async function startWebhookListener(\n config: AgrentingAdapterConfig\n): Promise<string> {\n if (webhookServer) {\n const addr = webhookServer.address();\n const port =\n typeof addr === \"object\" && addr ? addr.port : DEFAULT_WEBHOOK_PORT;\n return `http://localhost:${port}/webhook`;\n }\n\n const http = await import(\"http\");\n const port = process.env.PAPERCLIP_WEBHOOK_PORT\n ? parseInt(process.env.PAPERCLIP_WEBHOOK_PORT, 10)\n : DEFAULT_WEBHOOK_PORT;\n\n return new Promise((resolve, reject) => {\n const server = http.createServer(async (req, res) => {\n if (req.method !== \"POST\" || req.url !== \"/webhook\") {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n let bodyChunks: Buffer[] = [];\n let bodyLength = 0;\n let bodyTooLarge = false;\n req.on(\"data\", (chunk: Buffer) => {\n bodyLength += chunk.length;\n if (bodyLength > MAX_WEBHOOK_BODY_SIZE) {\n bodyTooLarge = true;\n res.writeHead(413);\n res.end(\"Request body too large\");\n req.destroy();\n return;\n }\n bodyChunks.push(chunk);\n });\n\n req.on(\"end\", async () => {\n if (bodyTooLarge) return;\n const rawBody = Buffer.concat(bodyChunks).toString(\"utf8\");\n bodyChunks = []; // free reference for GC\n const taskId = req.headers[\"x-webhook-task-id\"] as string | undefined;\n const signature =\n (req.headers[\"x-webhook-signature\"] as string) || \"\";\n\n let payload: Record<string, unknown>;\n try {\n payload = JSON.parse(rawBody);\n } catch {\n res.writeHead(400);\n res.end(\"Invalid JSON\");\n return;\n }\n\n // Verify signature if secret is configured\n if (config.webhookSecret) {\n if (!signature) {\n res.writeHead(401);\n res.end(\"Missing signature\");\n return;\n }\n const valid = await verifyWebhookSignature(\n rawBody,\n signature,\n config.webhookSecret\n );\n if (!valid) {\n res.writeHead(401);\n res.end(\"Invalid signature\");\n return;\n }\n }\n\n // Extract task ID from payload if not in header\n const resolvedTaskId =\n taskId ??\n (payload.task_id as string) ??\n (payload.taskId as string);\n\n if (resolvedTaskId) {\n const pending = pendingTasks.get(resolvedTaskId);\n if (pending && !pending.settled) {\n const status = (payload.status as AgrentingTaskStatus) ?? pending.status;\n pending.status = status;\n pending.progressPercent =\n (payload.progress_percent as number) ?? pending.progressPercent;\n pending.progressMessage =\n (payload.progress_message as string) ?? pending.progressMessage;\n\n if (status === \"completed\") {\n pending.settled = true;\n pending.resolve({\n success: true,\n output: (payload.output as string) ?? JSON.stringify(payload.output ?? {}),\n taskId: resolvedTaskId,\n durationMs: Date.now() - pending.startedAt,\n });\n } else if (status === \"failed\") {\n pending.settled = true;\n pending.resolve({\n success: false,\n error:\n (payload.error_reason as string) ??\n \"Task failed with no reason provided\",\n taskId: resolvedTaskId,\n durationMs: Date.now() - pending.startedAt,\n });\n } else if (status === \"cancelled\") {\n pending.settled = true;\n pending.resolve({\n success: false,\n error: \"Task was cancelled\",\n taskId: resolvedTaskId,\n durationMs: Date.now() - pending.startedAt,\n });\n }\n }\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/plain\" });\n res.end(\"OK\");\n });\n });\n\n server.listen(port, () => {\n webhookServer = server;\n // Start periodic cleanup of stale entries\n if (!staleCleanupTimer) {\n staleCleanupTimer = setInterval(sweepStaleTasks, STALE_TASK_CLEANUP_INTERVAL_MS);\n staleCleanupTimer.unref();\n }\n resolve(`http://localhost:${port}/webhook`);\n });\n\n server.on(\"error\", reject);\n });\n}\n\nconst WEBHOOK_STOP_TIMEOUT_MS = 5_000;\n\n/**\n * Stop the webhook listener if it was started.\n * Closes all active connections and waits up to 5s for a clean shutdown.\n */\nexport async function stopWebhookListener(): Promise<void> {\n if (!webhookServer) {\n return;\n }\n\n if (staleCleanupTimer) {\n clearInterval(staleCleanupTimer);\n staleCleanupTimer = null;\n }\n\n const server = webhookServer;\n webhookServer = null;\n\n // Force-close all active connections (Node 18.2+) so server.close() doesn't hang\n if (\"closeAllConnections\" in server && typeof server.closeAllConnections === \"function\") {\n (server as import(\"http\").Server<typeof import(\"http\").IncomingMessage, typeof import(\"http\").ServerResponse>).closeAllConnections();\n }\n\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n resolve();\n }, WEBHOOK_STOP_TIMEOUT_MS);\n timeout.unref();\n\n server.close(() => {\n clearTimeout(timeout);\n resolve();\n });\n });\n}\n\n/**\n * Register a webhook with Agrenting to receive task lifecycle events.\n * Returns the webhook ID and secret key.\n */\nexport async function registerWebhook(\n config: AgrentingAdapterConfig,\n callbackUrl?: string\n): Promise<{\n id: string;\n secretKey: string;\n callbackUrl: string;\n}> {\n const client = new AgrentingClient(config);\n const url = callbackUrl ?? (await startWebhookListener(config));\n\n const result = await client.registerWebhook({\n callbackUrl: url,\n eventTypes: [\n \"task.created\",\n \"task.claimed\",\n \"task.in_progress\",\n \"task.completed\",\n \"task.failed\",\n \"task.cancelled\",\n ],\n });\n\n return {\n id: result.id,\n secretKey: result.secret_key,\n callbackUrl: result.callback_url,\n };\n}\n\n/**\n * Deregister a webhook from Agrenting to stop receiving task lifecycle events.\n * Use this to clean up orphaned webhooks when they are no longer needed.\n */\nexport async function deregisterWebhook(\n config: AgrentingAdapterConfig,\n webhookId: string\n): Promise<void> {\n const client = new AgrentingClient(config);\n await client.deleteWebhook(webhookId);\n}\n\n/**\n * Execute a task by submitting it to the Agrenting platform.\n *\n * Uses webhook callbacks when `webhookCallbackUrl` is configured in the adapter config\n * (or when `startWebhookListener()` has been called). Falls back to polling\n * when webhooks are not available.\n *\n * When `maxPrice` is provided, the task is created with a budget and escrow funds\n * are locked via `createTaskPayment()` after submission.\n */\nexport async function execute(\n config: AgrentingAdapterConfig,\n params: {\n input: string;\n capability: string;\n instructions?: string;\n /** Maximum price in USD to budget for this task. Triggers escrow payment. */\n maxPrice?: string;\n /** Payment type: \"crypto\" | \"escrow\" | \"nowpayments\". Defaults to \"crypto\". */\n paymentType?: string;\n }\n): Promise<AgrentingExecutionResult> {\n const client = new AgrentingClient(config);\n const startTime = Date.now();\n\n // Upload instructions if managed mode is configured\n if (\n config.instructionsBundleMode === \"managed\" &&\n params.instructions\n ) {\n await client.uploadDocument({\n name: \"instructions\",\n content: params.instructions,\n documentType: \"instructions\",\n });\n }\n\n // Pre-submission balance check (non-blocking — logs warning but doesn't prevent)\n const balanceCheck = await canSubmitTask({ config });\n if (!balanceCheck.ok) {\n // Log but don't block — let the task fail naturally\n console.warn(`[adapter-agrenting] ${balanceCheck.reason}`);\n }\n\n // Submit the task to Agrenting\n const task = await client.createTask({\n providerAgentId: config.agentDid,\n capability: params.capability,\n input: params.input,\n maxPrice: params.maxPrice,\n paymentType: params.paymentType,\n });\n\n const taskId = task.id;\n\n // Lock escrow funds if a max price was specified.\n // If payment fails, cancel the orphaned task to avoid leaving it stuck on the server.\n let payment: PaymentInfo | undefined;\n if (params.maxPrice) {\n try {\n const paymentOptions: CreateTaskPaymentOptions = {};\n if (params.paymentType) paymentOptions.paymentType = params.paymentType;\n payment = await client.createTaskPayment(taskId, paymentOptions);\n console.log(`[adapter-agrenting] Escrow locked for task ${taskId}: ${payment.amount} ${payment.currency} (${payment.status})`);\n } catch (err) {\n console.error(`[adapter-agrenting] Failed to lock escrow for task ${taskId}, cancelling orphaned task:`, err);\n try {\n await client.cancelTask(taskId);\n } catch {\n // Best-effort cleanup — log but don't throw, the payment error is the real problem\n }\n return {\n success: false,\n error: `Escrow payment failed: ${err instanceof Error ? err.message : String(err)}`,\n taskId,\n durationMs: Date.now() - startTime,\n };\n }\n }\n\n // Register for webhook callbacks only when webhook mode is actually configured.\n // The taskRegistry in webhook-handler.ts is for the Paperclip-side webhook handler\n // (issue status updates), while pendingTasks below is for the in-process listener\n // (resolving execute() promises). They serve different purposes.\n if (config.webhookCallbackUrl || config.webhookSecret) {\n registerTaskMapping(taskId, taskId, config.agrentingUrl, config);\n return executeWithWebhook(client, config, taskId, startTime);\n }\n\n // Fall back to polling — delegate to pollTaskUntilDone\n return executeWithPolling(config, taskId, startTime);\n}\n\n/**\n * Execute with webhook: register a listener, submit task, wait for callback.\n * Falls back to polling if no webhook received within the grace period.\n */\nasync function executeWithWebhook(\n _client: AgrentingClient,\n config: AgrentingAdapterConfig,\n taskId: string,\n startTime: number\n): Promise<AgrentingExecutionResult> {\n // Ensure the listener is running\n await startWebhookListener(config);\n\n const deadline = startTime + (config.timeoutSec ?? 600) * 1000;\n\n // AbortController for clean cancellation when webhook resolves first\n const abortController = new AbortController();\n\n // Register the pending task so the webhook handler can resolve it\n const pending = new Promise<AgrentingExecutionResult>((resolve) => {\n pendingTasks.set(taskId, {\n resolve,\n status: \"pending\",\n progressPercent: 0,\n startedAt: startTime,\n createdAt: Date.now(),\n settled: false,\n });\n }).then((result) => {\n // Webhook resolved — abort any in-flight polling\n abortController.abort();\n return result;\n });\n\n // Race between webhook callback and timeout\n const timeout = new Promise<AgrentingExecutionResult>((resolve) => {\n const ms = deadline - Date.now();\n setTimeout(() => {\n const entry = pendingTasks.get(taskId);\n if (entry && !entry.settled) {\n entry.settled = true;\n }\n resolve({\n success: false,\n error: `Task timed out after ${config.timeoutSec ?? 600}s`,\n taskId,\n durationMs: Date.now() - startTime,\n });\n }, Math.max(ms, 0));\n });\n\n // If webhook doesn't resolve within grace period, fall back to polling.\n // Polling is deferred so it only starts when the timeout actually fires,\n // avoiding wasted HTTP calls when the webhook wins.\n return Promise.race([pending, timeout.then(async (result) => {\n if (!result.success && result.error?.includes(\"timed out\")) {\n const pollingFallback = await pollTaskUntilDone({\n config,\n taskId,\n deadline,\n signal: abortController.signal,\n });\n return pollingFallback.result;\n }\n return result;\n })]);\n}\n\n/**\n * Execute with polling by delegating to pollTaskUntilDone.\n * Avoids reimplementing the backoff loop that polling.ts already provides.\n */\nasync function executeWithPolling(\n config: AgrentingAdapterConfig,\n taskId: string,\n startTime: number\n): Promise<AgrentingExecutionResult> {\n const deadline = startTime + (config.timeoutSec ?? 600) * 1000;\n const { result } = await pollTaskUntilDone({ config, taskId, deadline });\n return result;\n}\n\n/**\n * Get the current progress of a task including percentage and message.\n * Useful for progress monitoring in UI dashboards.\n */\nexport async function getTaskProgress(\n config: AgrentingAdapterConfig,\n taskId: string\n): Promise<{\n status: AgrentingTaskStatus;\n progressPercent: number;\n progressMessage?: string;\n timeline: Array<{\n event_type: string;\n timestamp: string;\n progress_percent?: number;\n progress_message?: string;\n }>;\n}> {\n const client = new AgrentingClient(config);\n const [progress, timeline] = await Promise.all([\n client.getTaskProgress(taskId),\n client.getTaskTimeline(taskId),\n ]);\n\n return {\n status: progress.status as AgrentingTaskStatus,\n progressPercent: progress.progress_percent,\n progressMessage: progress.progress_message,\n timeline: timeline.events,\n };\n}\n\n/**\n * Discover marketplace agents available for hire.\n * Filters by capability, price range, reputation, and availability.\n */\nexport async function discoverAgents(\n config: AgrentingAdapterConfig,\n options: DiscoverAgentsOptions = {}\n): Promise<AgentInfo[]> {\n const client = new AgrentingClient(config);\n return client.discoverAgents(options);\n}\n\n/**\n * Get the current platform balance including available, escrowed, and total amounts.\n */\nexport async function getBalance(\n config: AgrentingAdapterConfig\n): Promise<BalanceInfoRaw> {\n const client = new AgrentingClient(config);\n return client.getBalance();\n}\n\n/**\n * List recent ledger transactions.\n */\nexport async function getTransactions(\n config: AgrentingAdapterConfig,\n options: { limit?: number; offset?: number; type?: string } = {}\n): Promise<TransactionInfo[]> {\n const client = new AgrentingClient(config);\n return client.getTransactions(options);\n}\n\n/**\n * Deposit funds into the Agrenting ledger.\n */\nexport async function deposit(\n config: AgrentingAdapterConfig,\n params: { amount: string; currency?: string; paymentMethod?: string }\n): Promise<{ transaction_id: string; status: string; deposit_address?: string; payment_url?: string }> {\n const client = new AgrentingClient(config);\n return client.deposit(params);\n}\n\n/**\n * Withdraw funds from the Agrenting ledger to an external wallet.\n */\nexport async function withdraw(\n config: AgrentingAdapterConfig,\n params: { amount: string; currency?: string; withdrawalAddressId?: string }\n): Promise<{ transaction_id: string; status: string }> {\n const client = new AgrentingClient(config);\n return client.withdraw(params);\n}\n\n/**\n * Get the payment status and escrow details for a task.\n */\nexport async function getTaskPayment(\n config: AgrentingAdapterConfig,\n taskId: string\n): Promise<PaymentInfo | undefined> {\n const client = new AgrentingClient(config);\n try {\n return await client.getTaskPayment(taskId);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Cancel a running task.\n */\nexport async function cancelTask(\n config: AgrentingAdapterConfig,\n taskId: string\n): Promise<{ success: boolean; error?: string }> {\n const client = new AgrentingClient(config);\n try {\n await client.cancelTask(taskId);\n pendingTasks.delete(taskId);\n return { success: true };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : \"Failed to cancel task\",\n };\n }\n}\n\n// -------------------------------------------------------------------------\n// New adapter functions for hire, messaging, auto-select, and retry\n// -------------------------------------------------------------------------\n\n/** Task retry configuration */\nconst TASK_MAX_RETRIES = 2;\nconst TASK_RETRY_BASE_DELAY_MS = 1000; // 1s initial delay\nconst TASK_RETRY_MAX_DELAY_MS = 30_000; // 30s max delay\n\n/**\n * Hire an agent by DID. Returns hiring record and adapter config for auto-provisioning.\n * This is the primary entry point for the \"browse marketplace, click Hire\" flow.\n */\nexport async function hireAgent(\n config: AgrentingAdapterConfig,\n agentDid: string\n): Promise<HireAgentResult> {\n const client = new AgrentingClient(config);\n return client.hireAgent(agentDid);\n}\n\n/**\n * Get full agent profile by DID.\n * Returns description, capabilities, pricing, reputation, and availability.\n */\nexport async function getAgentProfile(\n config: AgrentingAdapterConfig,\n agentDid: string\n): Promise<AgentProfile> {\n const client = new AgrentingClient(config);\n return client.getAgentProfile(agentDid);\n}\n\n/**\n * Send a message to an active task for bidirectional communication.\n * Used for sending follow-up instructions to the remote agent mid-task.\n */\nexport async function sendMessageToTask(\n config: AgrentingAdapterConfig,\n taskId: string,\n message: string\n): Promise<SendMessageResult> {\n const client = new AgrentingClient(config);\n return client.sendMessageToTask(taskId, { message });\n}\n\n/**\n * Get messages for a task (bidirectional comment history).\n */\nexport async function getTaskMessages(\n config: AgrentingAdapterConfig,\n taskId: string\n): Promise<TaskMessage[]> {\n const client = new AgrentingClient(config);\n return client.getTaskMessages(taskId);\n}\n\n/**\n * Reassign a failed/cancelled task to a different agent.\n * If newAgentDid is not provided, the system will auto-select a replacement.\n */\nexport async function reassignTask(\n config: AgrentingAdapterConfig,\n taskId: string,\n newAgentDid?: string\n): Promise<ReassignTaskResult> {\n const client = new AgrentingClient(config);\n return client.reassignTask(taskId, newAgentDid);\n}\n\n/**\n * List all available capabilities with descriptions and usage stats.\n * Helps with agent discovery and validation.\n */\nexport async function listCapabilities(\n config: AgrentingAdapterConfig\n): Promise<Capability[]> {\n const client = new AgrentingClient(config);\n return client.listCapabilities();\n}\n\n/**\n * Send a message to a hiring for communication with the hired agent.\n */\nexport async function sendMessageToHiring(\n config: AgrentingAdapterConfig,\n hiringId: string,\n message: string\n): Promise<HiringMessage> {\n const client = new AgrentingClient(config);\n return client.sendMessageToHiring(hiringId, message);\n}\n\n/**\n * Get messages for a hiring.\n */\nexport async function getHiringMessages(\n config: AgrentingAdapterConfig,\n hiringId: string\n): Promise<HiringMessage[]> {\n const client = new AgrentingClient(config);\n return client.getHiringMessages(hiringId);\n}\n\n/**\n * Retry a failed hiring.\n */\nexport async function retryHiring(\n config: AgrentingAdapterConfig,\n hiringId: string,\n options?: { reason?: string }\n): Promise<Hiring> {\n const client = new AgrentingClient(config);\n return client.retryHiring(hiringId, options);\n}\n\n/**\n * Get a hiring by ID.\n */\nexport async function getHiring(\n config: AgrentingAdapterConfig,\n hiringId: string\n): Promise<Hiring> {\n const client = new AgrentingClient(config);\n return client.getHiring(hiringId);\n}\n\n/**\n * List hirings for the authenticated agent.\n */\nexport async function listHirings(\n config: AgrentingAdapterConfig,\n options?: { status?: string; limit?: number; offset?: number }\n): Promise<Hiring[]> {\n const client = new AgrentingClient(config);\n return client.listHirings(options);\n}\n\n/**\n * Auto-select mode: given a capability requirement, discover the best agent,\n * hire them, and return the adapter config for immediate use.\n *\n * Selection algorithm:\n * 1. Call listCapabilities() to validate capability exists\n * 2. Call GET /api/v1/agents filtered by capability\n * 3. Sort by: availability first, then reputation_score desc, then base_price asc\n * 4. Call hireAgent() to auto-provision\n * 5. Return adapter config\n */\nexport async function autoSelectAgent(\n config: AgrentingAdapterConfig,\n options: AutoSelectOptions\n): Promise<HireAgentResult & { selectedAgent: AgentProfile }> {\n const client = new AgrentingClient(config);\n\n // 1. Validate capability exists\n const capabilities = await client.listCapabilities();\n const capabilityExists = capabilities.some(\n (c) => c.name === options.capability || c.name.toLowerCase() === options.capability.toLowerCase()\n );\n if (!capabilityExists) {\n throw new Error(`Capability \"${options.capability}\" not found. Available: ${capabilities.map(c => c.name).join(\", \")}`);\n }\n\n // 2. Get agents filtered by capability\n const agents = await client.listAgentsByCapability(options.capability);\n if (agents.length === 0) {\n throw new Error(`No agents available for capability \"${options.capability}\"`);\n }\n\n // 3. Filter by options and sort\n let filtered = agents;\n\n // Filter by max price\n if (options.maxPrice) {\n const maxPriceNum = parseFloat(options.maxPrice);\n filtered = filtered.filter((a) => {\n if (!a.base_price) return true; // No price info = assume fits budget\n return parseFloat(a.base_price) <= maxPriceNum;\n });\n }\n\n // Filter by min reputation\n if (options.minReputation) {\n const minRep = options.minReputation;\n filtered = filtered.filter((a) => {\n if (!a.reputation_score) return false; // No reputation = excluded\n return a.reputation_score >= minRep;\n });\n }\n\n if (filtered.length === 0) {\n throw new Error(\n `No agents match criteria for capability \"${options.capability}\" (maxPrice=${options.maxPrice ?? \"any\"}, minReputation=${options.minReputation ?? \"any\"})`\n );\n }\n\n // Sort: availability first, then by specified sort criteria\n const sortBy = options.sortBy ?? \"reputation_score\";\n\n // Prefer available agents if requested\n if (options.preferAvailable ?? true) {\n filtered.sort((a, b) => {\n const aAvail = a.availability_status === \"available\" ? 0 : 1;\n const bAvail = b.availability_status === \"available\" ? 0 : 1;\n if (aAvail !== bAvail) return aAvail - bAvail;\n return 0;\n });\n }\n\n // Secondary sort\n filtered.sort((a, b) => {\n if (sortBy === \"reputation_score\") {\n return (b.reputation_score ?? 0) - (a.reputation_score ?? 0);\n }\n if (sortBy === \"base_price\") {\n const aPrice = parseFloat(a.base_price ?? \"999999\");\n const bPrice = parseFloat(b.base_price ?? \"999999\");\n return aPrice - bPrice;\n }\n if (sortBy === \"availability\") {\n const aAvail = a.availability_status === \"available\" ? 0 : 1;\n const bAvail = b.availability_status === \"available\" ? 0 : 1;\n return aAvail - bAvail;\n }\n return 0;\n });\n\n // 4. Hire the best agent\n const selectedAgent = filtered[0];\n const hireResult = await client.hireAgent(selectedAgent.did);\n\n // 5. Return combined result\n return {\n ...hireResult,\n selectedAgent,\n };\n}\n\n/**\n * Execute a task with retry logic.\n * If the task fails, it will be retried up to TASK_MAX_RETRIES times\n * with exponential backoff.\n */\nexport async function executeWithRetry(\n config: AgrentingAdapterConfig,\n params: {\n input: string;\n capability: string;\n instructions?: string;\n maxPrice?: string;\n paymentType?: string;\n maxRetries?: number;\n }\n): Promise<AgrentingExecutionResult> {\n const maxRetries = params.maxRetries ?? TASK_MAX_RETRIES;\n let lastResult: AgrentingExecutionResult | undefined;\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n lastResult = await execute(config, params);\n\n if (lastResult.success) {\n return lastResult;\n }\n\n // If task failed but we have retries remaining, wait and retry\n if (attempt < maxRetries && lastResult.error) {\n const delayMs = Math.min(\n TASK_RETRY_BASE_DELAY_MS * Math.pow(2, attempt),\n TASK_RETRY_MAX_DELAY_MS\n );\n console.warn(\n `[adapter-agrenting] Task failed on attempt ${attempt + 1}, retrying in ${delayMs}ms: ${lastResult.error}`\n );\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n continue;\n }\n\n return lastResult;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n\n if (attempt < maxRetries) {\n const delayMs = Math.min(\n TASK_RETRY_BASE_DELAY_MS * Math.pow(2, attempt),\n TASK_RETRY_MAX_DELAY_MS\n );\n console.warn(\n `[adapter-agrenting] Execution error on attempt ${attempt + 1}, retrying in ${delayMs}ms: ${lastError.message}`\n );\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n continue;\n }\n }\n }\n\n // All retries exhausted\n return {\n success: false,\n error: lastError?.message ?? lastResult?.error ?? \"Task failed after all retries\",\n taskId: lastResult?.taskId,\n durationMs: lastResult?.durationMs ?? 0,\n };\n}\n\n/**\n * Forward a comment from Paperclip to the Agrenting task.\n * Used for bidirectional comment sync when the user adds a comment\n * to a Paperclip issue that has an active Agrenting task.\n */\nexport async function forwardCommentToAgrenting(\n config: AgrentingAdapterConfig,\n taskId: string,\n comment: string,\n authorName?: string\n): Promise<SendMessageResult | null> {\n const client = new AgrentingClient(config);\n\n // Format the comment for Agrenting\n const formattedComment = authorName\n ? `[${authorName}]: ${comment}`\n : comment;\n\n try {\n return await client.sendMessageToTask(taskId, { message: formattedComment });\n } catch (err) {\n // Log but don't throw — comment sync is non-critical\n console.error(\n `[adapter-agrenting] Failed to forward comment to task ${taskId}:`,\n err instanceof Error ? err.message : String(err)\n );\n return null;\n }\n}\n\n/**\n * Process incoming Agrenting messages and format them for Paperclip.\n * Called by the webhook handler when it receives task messages.\n */\nexport function processIncomingMessage(\n message: TaskMessage\n): string {\n const senderName = message.sender_name ?? \"Agent\";\n return formatAgentResponse(senderName, message.content);\n}\n\n/**\n * Create the server-side adapter module.\n * This is the entry point for Paperclip's server adapter registry.\n */\nexport function createServerAdapter() {\n return {\n name: \"agrenting\" as const,\n execute,\n testEnvironment,\n getConfigSchema,\n startWebhookListener,\n stopWebhookListener,\n registerWebhook,\n deregisterWebhook,\n getTaskProgress,\n getTaskPayment,\n cancelTask,\n discoverAgents,\n getAgentProfile,\n hireAgent,\n sendMessageToTask,\n getTaskMessages,\n reassignTask,\n listCapabilities,\n sendMessageToHiring,\n getHiringMessages,\n retryHiring,\n getHiring,\n listHirings,\n autoSelectAgent,\n executeWithRetry,\n forwardCommentToAgrenting,\n processIncomingMessage,\n getBalance,\n getTransactions,\n deposit,\n withdraw,\n };\n}\n"],"mappings":"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","names":["port","forwardCommentToAgrenting","processIncomingMessage"]}
1
+ {"version":3,"sources":["../../server/src/index.ts","../../server/src/client.ts","../../server/src/paperclip.ts","../../server/src/crypto.ts","../../server/src/webhook-handler.ts","../../server/src/polling.ts","../../server/src/balance-monitor.ts","../../server/src/comment-sync.ts","../../server/src/adapter.ts","../../server/src/apps-v2.ts"],"sourcesContent":["export { createServerAdapter } from \"./adapter.js\";\nexport { AgrentingClient } from \"./client.js\";\nexport {\n createWebhookHandler,\n registerTaskMapping,\n unregisterTaskMapping,\n getActiveTaskMappings,\n} from \"./webhook-handler.js\";\nexport type {\n AgrentingWebhookPayload,\n PaperclipApiClient,\n WebhookHandlerOptions,\n} from \"./webhook-handler.js\";\nexport {\n formatAgentResponse,\n forwardCommentToAgrenting,\n processIncomingMessage,\n} from \"./comment-sync.js\";\nexport { pollTaskUntilDone, getWebhookGracePeriodMs, POLL_INTERVALS_MS, MAX_POLLS, getBackoffMs } from \"./polling.js\";\nexport type { PollOptions, PollResult } from \"./polling.js\";\nexport {\n checkBalance,\n canSubmitTask,\n formatLowBalanceComment,\n formatInsufficientBalanceComment,\n} from \"./balance-monitor.js\";\nexport type { BalanceInfo, BalanceCheckOptions } from \"./balance-monitor.js\";\nexport { verifyWebhookSignature } from \"./crypto.js\";\nexport {\n registerWebhook,\n deregisterWebhook,\n hireAgent,\n getAgentProfile,\n sendMessageToTask,\n getTaskMessages,\n reassignTask,\n listCapabilities,\n sendMessageToHiring,\n getHiringMessages,\n retryHiring,\n cancelHiring,\n getHiring,\n listHirings,\n autoSelectAgent,\n executeWithRetry,\n // Legacy pre-0.4 task-oriented compatibility exports. The package-root\n // createServerAdapter() exposes Paperclip's current ServerAdapterModule.\n execute,\n testEnvironment,\n getConfigSchema,\n cancelTask,\n getTaskProgress,\n invoke,\n status,\n cancel,\n detectModel,\n listSkills,\n syncSkills,\n sessionCodec,\n} from \"./adapter.js\";\nexport {\n type,\n label,\n agentConfigurationDoc,\n executePaperclip,\n testPaperclipEnvironment,\n getPaperclipConfigSchema,\n paperclipSessionCodec,\n} from \"./paperclip.js\";\nexport { agrentingAppGalleryEntry } from \"./apps-v2.js\";\nexport type { PaperclipSkill } from \"./adapter.js\";\nexport type {\n AgrentingAdapterConfig,\n AgrentingExecutionResult,\n AgrentingTaskStatus,\n AgrentingTask,\n AgentInfo,\n AgentProfile,\n HireAgentResult,\n HireAgentOptions,\n HiringStatus,\n HiringListResult,\n SendMessageOptions,\n SendMessageResult,\n ReassignTaskResult,\n PaymentInfo,\n TransactionInfo,\n DiscoverAgentsOptions,\n CreateTaskPaymentOptions,\n Hiring,\n TaskMessage,\n HiringMessage,\n Capability,\n AutoSelectOptions,\n RetryHiringOptions,\n} from \"./types.js\";\n","import type {\n AgrentingAdapterConfig,\n AgrentingTask,\n AgentInfo,\n AgentProfile,\n BalanceInfo,\n HireAgentOptions,\n HireAgentResult,\n PaymentInfo,\n ReassignTaskResult,\n SendMessageOptions,\n SendMessageResult,\n TransactionInfo,\n DiscoverAgentsOptions,\n CreateTaskPaymentOptions,\n Hiring,\n HiringListResult,\n TaskMessage,\n HiringMessage,\n Capability,\n RetryHiringOptions,\n} from \"./types.js\";\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst MAX_RETRIES = 3;\n\nclass NonRetryableAgrentingError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"NonRetryableAgrentingError\";\n }\n}\n\n/**\n * HTTP client for the Agrenting REST API.\n * Wraps fetch with auth headers and base URL handling.\n */\nexport class AgrentingClient {\n private baseUrl: string;\n private apiKey: string;\n\n constructor(config: AgrentingAdapterConfig) {\n this.baseUrl = config.agrentingUrl.replace(/\\/+$/, \"\");\n this.apiKey = config.apiKey;\n }\n\n private headers(): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.apiKey,\n };\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<T> {\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: this.headers(),\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await response.text();\n const shouldRetry = response.status === 429 || response.status >= 500;\n\n if (shouldRetry && attempt < MAX_RETRIES) {\n clearTimeout(timer);\n // Respect Retry-After header on 429, otherwise use exponential backoff\n const retryAfter = response.headers.get(\"Retry-After\");\n let delayMs = Math.min(1000 * 2 ** attempt, 30_000);\n if (retryAfter) {\n // Retry-After can be seconds (integer) or a date string (HTTP-date)\n const seconds = parseInt(retryAfter, 10);\n if (!Number.isNaN(seconds) && seconds > 0) {\n delayMs = seconds * 1000;\n } else {\n // Try parsing as HTTP date\n const dateMs = Date.parse(retryAfter);\n if (!Number.isNaN(dateMs)) {\n delayMs = Math.max(0, dateMs - Date.now());\n }\n }\n }\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n continue;\n }\n\n throw new NonRetryableAgrentingError(\n `Agrenting API ${response.status}: ${text.slice(0, 500)}`\n );\n }\n\n const envelope = (await response.json()) as Record<string, unknown>;\n if (Array.isArray(envelope.errors) && envelope.errors.length) {\n throw new NonRetryableAgrentingError(\n `API errors: ${(envelope.errors as string[]).join(\", \")}`\n );\n }\n return (envelope.data ?? envelope) as T;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (lastError instanceof NonRetryableAgrentingError) {\n throw lastError;\n }\n if (attempt < MAX_RETRIES) {\n clearTimeout(timer);\n const delayMs = Math.min(1000 * 2 ** attempt, 30_000);\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n continue;\n }\n throw lastError;\n } finally {\n clearTimeout(timer);\n }\n }\n\n // Should never reach here, but satisfy the compiler\n throw lastError ?? new Error(\"Unexpected retry loop exit\");\n }\n\n /** Submit a new task to Agrenting.\n * When `maxPrice` is set, the task includes pricing info.\n * Call `createTaskPayment` after this to actually lock escrow funds.\n */\n async createTask(params: {\n providerAgentId: string;\n capability: string;\n input: string;\n /** Max price in USD. If set, the task will have a price for escrow. */\n maxPrice?: string;\n /** Payment type: \"crypto\" | \"escrow\" | \"nowpayments\" */\n paymentType?: string;\n }): Promise<AgrentingTask> {\n const body: Record<string, unknown> = {\n provider_agent_id: params.providerAgentId,\n capability: params.capability,\n input: params.input,\n };\n if (params.maxPrice) {\n body.max_price = params.maxPrice;\n }\n return this.request(\"POST\", \"/api/v1/tasks\", body);\n }\n\n /** Create a payment for an existing task to lock escrow funds.\n * This is the step that actually deducts funds from the client's balance\n * and places them in escrow for the task.\n */\n async createTaskPayment(\n taskId: string,\n options: CreateTaskPaymentOptions = {}\n ): Promise<PaymentInfo> {\n const body: Record<string, unknown> = {\n task_id: taskId,\n };\n if (options.cryptoCurrency) body.crypto_currency = options.cryptoCurrency;\n if (options.paymentType) body.payment_type = options.paymentType;\n return this.request(\"POST\", `/api/v1/tasks/${taskId}/payments`, body);\n }\n\n /** Get payment info for a task */\n async getTaskPayment(taskId: string): Promise<PaymentInfo> {\n return this.request(\"GET\", `/api/v1/tasks/${taskId}/payments`);\n }\n\n /** Get the status and result of a task */\n async getTask(taskId: string): Promise<AgrentingTask> {\n return this.request<AgrentingTask>(\"GET\", `/api/v1/tasks/${taskId}`);\n }\n\n /** Get task timeline events (progress, attempts, status changes) */\n async getTaskTimeline(taskId: string): Promise<{\n events: Array<{\n event_type: string;\n timestamp: string;\n progress_percent?: number;\n progress_message?: string;\n details?: Record<string, unknown>;\n }>;\n }> {\n return this.request(\"GET\", `/api/v1/tasks/${taskId}/timeline`);\n }\n\n /** Get attempt history for a task */\n async getTaskAttempts(taskId: string): Promise<{\n attempts: Array<{\n id: string;\n status: string;\n created_at: string;\n completed_at?: string;\n error_reason?: string;\n }>;\n }> {\n return this.request(\"GET\", `/api/v1/tasks/${taskId}/attempts`);\n }\n\n /** Get current progress of a task */\n async getTaskProgress(taskId: string): Promise<{\n status: string;\n progress_percent: number;\n progress_message?: string;\n updated_at: string;\n }> {\n const task = await this.getTask(taskId);\n return {\n status: task.status,\n progress_percent: task.progress_percent ?? 0,\n progress_message: task.progress_message,\n updated_at: task.updated_at,\n };\n }\n\n /** Register a webhook to receive task lifecycle events.\n * Sends a flat request body matching the backend's expected shape.\n */\n async registerWebhook(params: {\n callbackUrl: string;\n eventTypes?: string[];\n }): Promise<{\n id: string;\n callback_url: string;\n event_types: string[];\n secret_key: string;\n status: string;\n }> {\n return this.request(\"POST\", \"/api/v1/webhooks\", {\n callback_url: params.callbackUrl,\n event_types: params.eventTypes ?? [\n \"task.created\",\n \"task.claimed\",\n \"task.in_progress\",\n \"task.completed\",\n \"task.failed\",\n \"task.cancelled\",\n ],\n });\n }\n\n /** List registered webhooks */\n async listWebhooks(): Promise<\n Array<{\n id: string;\n callback_url: string;\n event_types: string[];\n status: string;\n last_delivery_at?: string;\n failure_count: number;\n }>\n > {\n return this.request(\"GET\", \"/api/v1/webhooks\");\n }\n\n /** Delete a registered webhook */\n async deleteWebhook(webhookId: string): Promise<void> {\n return this.request(\"DELETE\", `/api/v1/webhooks/${webhookId}`);\n }\n\n /** Cancel a task by ID */\n async cancelTask(taskId: string): Promise<AgrentingTask> {\n return this.request(\"POST\", `/api/v1/tasks/${taskId}/cancel`);\n }\n\n /** Discover marketplace agents available for hire.\n * Filters by capability, price range, reputation, and availability.\n */\n async discoverAgents(\n options: DiscoverAgentsOptions = {}\n ): Promise<AgentInfo[]> {\n const params = new URLSearchParams();\n if (options.capability) params.set(\"capability\", options.capability);\n if (options.minPrice) params.set(\"min_price\", options.minPrice.toFixed(2));\n if (options.maxPrice) params.set(\"max_price\", options.maxPrice.toFixed(2));\n if (options.minReputation)\n params.set(\"min_reputation\", String(options.minReputation));\n if (options.sortBy) params.set(\"sort_by\", options.sortBy);\n if (options.limit) params.set(\"limit\", String(options.limit));\n\n return this.request<AgentInfo[]>(\n \"GET\",\n `/api/v1/agents/discover?${params}`\n );\n }\n\n /** Fetch the current platform balance including available, escrowed, and total. */\n async getBalance(): Promise<BalanceInfo> {\n return this.request(\"GET\", \"/api/v1/ledger/balance\");\n }\n\n /** List recent transactions for the authenticated agent. */\n async getTransactions(\n options: { limit?: number; offset?: number; type?: string } = {}\n ): Promise<TransactionInfo[]> {\n const params = new URLSearchParams();\n if (options.limit) params.set(\"limit\", String(options.limit));\n if (options.offset) params.set(\"offset\", String(options.offset));\n if (options.type) params.set(\"type\", options.type);\n\n return this.request<TransactionInfo[]>(\n \"GET\",\n `/api/v1/ledger/transactions?${params}`\n );\n }\n\n /** Deposit funds into the Agrenting ledger. */\n async deposit(params: {\n amount: string;\n currency?: string;\n paymentMethod?: string;\n }): Promise<{\n transaction_id: string;\n status: string;\n deposit_address?: string;\n payment_url?: string;\n }> {\n return this.request(\"POST\", \"/api/v1/ledger/deposit\", {\n amount: params.amount,\n currency: params.currency ?? \"USD\",\n payment_method: params.paymentMethod ?? \"crypto\",\n });\n }\n\n /** Withdraw funds from the Agrenting ledger to an external wallet. */\n async withdraw(params: {\n amount: string;\n currency?: string;\n withdrawalAddressId?: string;\n }): Promise<{\n transaction_id: string;\n status: string;\n }> {\n return this.request(\"POST\", \"/api/v1/ledger/withdraw\", {\n amount: params.amount,\n currency: params.currency ?? \"USD\",\n withdrawal_address_id: params.withdrawalAddressId,\n });\n }\n\n /** Create a payment intent for off-platform payment processing. */\n async createPaymentIntent(params: {\n amount: string;\n currency?: string;\n paymentType?: string;\n }): Promise<{\n id: string;\n status: string;\n payment_url?: string;\n address?: string;\n }> {\n return this.request(\"POST\", \"/api/v1/payments/create-intent\", {\n amount: params.amount,\n currency: params.currency ?? \"USD\",\n payment_type: params.paymentType ?? \"crypto\",\n });\n }\n\n /** Validate connectivity and API key by fetching the account balance */\n async testConnection(): Promise<{ ok: boolean; message: string }> {\n try {\n const data = await this.request<{\n available?: string;\n escrow?: string;\n total?: string;\n currency?: string;\n }>(\"GET\", \"/api/v1/ledger/balance\");\n return {\n ok: true,\n message: `Connected. Balance: ${data.total ?? data.available ?? \"N/A\"} ${data.currency ?? \"USD\"} (Available: ${data.available ?? \"N/A\"})`,\n };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : \"Unknown connection error\",\n };\n }\n }\n\n /** Upload a document (e.g. instructions) to Agrenting.\n * Uses the dedicated uploads endpoint which accepts base64-encoded content,\n * separate from the deal-scoped `/api/v1/documents` endpoint.\n */\n async uploadDocument(params: {\n name: string;\n content: string;\n contentType?: string;\n documentType?: string;\n taskId?: string;\n }): Promise<{\n id: string;\n name: string;\n file_url: string;\n content_type: string;\n file_hash: string;\n document_type: string;\n }> {\n const contentBase64 = Buffer.from(params.content).toString(\"base64\");\n return this.request(\"POST\", \"/api/v1/uploads\", {\n name: params.name,\n content: contentBase64,\n content_type: params.contentType ?? \"text/plain\",\n document_type: params.documentType ?? \"instructions\",\n task_id: params.taskId,\n });\n }\n\n /** Get the full profile of an agent by DID.\n * Returns capabilities, pricing tiers, reviews, and availability.\n */\n async getAgentProfile(agentDid: string): Promise<AgentProfile> {\n return this.request(\"GET\", `/api/v1/agents/${encodeURIComponent(agentDid)}`);\n }\n\n /** Create a paid hiring for an agent.\n * Agrenting requires a concrete task, capability, and offered price.\n */\n async hireAgent(\n agentDid: string,\n options: HireAgentOptions\n ): Promise<HireAgentResult> {\n const body: Record<string, unknown> = {\n task_description: options.taskDescription,\n capability_requested: options.capabilityRequested,\n price: String(options.price),\n delivery_mode: options.deliveryMode ?? \"output\",\n };\n if (options.repoUrl) body.repo_url = options.repoUrl;\n if (options.repoAccessToken) body.repo_access_token = options.repoAccessToken;\n if (options.clientIdempotencyKey) {\n body.client_idempotency_key = options.clientIdempotencyKey;\n }\n if (options.taskInput) body.task_input = options.taskInput;\n if (options.clientMessage) body.client_message = options.clientMessage;\n return this.request(\n \"POST\",\n `/api/v1/agents/${encodeURIComponent(agentDid)}/hire`,\n body\n );\n }\n\n /** Send a message to a running task (mid-task instructions, feedback, or questions).\n * Enables bidirectional communication between the Paperclip user and the remote agent.\n */\n async sendMessageToTask(\n taskId: string,\n options: SendMessageOptions\n ): Promise<SendMessageResult> {\n return this.request(\"POST\", `/api/v1/tasks/${taskId}/messages`, {\n message: options.message,\n message_type: options.messageType ?? \"instruction\",\n });\n }\n\n /** Get messages for a task.\n * GET /api/v1/tasks/:id/messages\n */\n async getTaskMessages(taskId: string): Promise<TaskMessage[]> {\n return this.request<TaskMessage[]>(\n \"GET\",\n `/api/v1/tasks/${taskId}/messages`\n );\n }\n\n /** Reassign a failed or cancelled task to a different agent.\n * If `newAgentDid` is omitted, the platform picks the best available agent.\n */\n async reassignTask(\n taskId: string,\n newAgentDid?: string\n ): Promise<ReassignTaskResult> {\n const body: Record<string, unknown> = {};\n if (newAgentDid) {\n body.new_provider_agent_did = newAgentDid;\n }\n return this.request<ReassignTaskResult>(\n \"POST\",\n `/api/v1/tasks/${taskId}/reassign`,\n body\n );\n }\n\n /** List all available capabilities with descriptions and usage stats.\n * GET /api/v1/capabilities\n */\n async listCapabilities(): Promise<Capability[]> {\n return this.request<Capability[]>(\"GET\", \"/api/v1/capabilities\");\n }\n\n /** Send a message to a hiring for communication with the hired agent.\n * POST /api/v1/hirings/:id/messages\n */\n async sendMessageToHiring(\n hiringId: string,\n content: string\n ): Promise<HiringMessage> {\n if (content.length > 5000) {\n throw new Error(\"Message content exceeds 5000 character limit\");\n }\n return this.request<HiringMessage>(\n \"POST\",\n `/api/v1/hirings/${hiringId}/messages`,\n { content }\n );\n }\n\n /** Get messages for a hiring.\n * The canonical API includes recent messages in GET /api/v1/hirings/:id.\n */\n async getHiringMessages(hiringId: string): Promise<HiringMessage[]> {\n const hiring = await this.getHiring(hiringId);\n return hiring.messages ?? [];\n }\n\n /** Retry a failed hiring.\n * POST /api/v1/hirings/:id/retry\n */\n async retryHiring(\n hiringId: string,\n options: RetryHiringOptions = {}\n ): Promise<Hiring> {\n const body: Record<string, unknown> = {};\n if (options.reason) {\n body.reason = options.reason;\n }\n return this.request<Hiring>(\n \"POST\",\n `/api/v1/hirings/${hiringId}/retry`,\n body\n );\n }\n\n /** Get a hiring by ID.\n * GET /api/v1/hirings/:id\n */\n async getHiring(hiringId: string): Promise<Hiring> {\n return this.request<Hiring>(\"GET\", `/api/v1/hirings/${hiringId}`);\n }\n\n /** Cancel an active hiring.\n * POST /api/v1/hirings/:id/cancel\n */\n async cancelHiring(hiringId: string): Promise<Hiring> {\n return this.request<Hiring>(\n \"POST\",\n `/api/v1/hirings/${hiringId}/cancel`\n );\n }\n\n /** List hirings for the authenticated agent.\n * GET /api/v1/hirings\n */\n async listHirings(options: {\n status?: string;\n limit?: number;\n offset?: number;\n } = {}): Promise<Hiring[]> {\n const params = new URLSearchParams();\n if (options.status) params.set(\"status\", options.status);\n if (options.limit) params.set(\"limit\", String(options.limit));\n if (options.offset) {\n const perPage = options.limit ?? 20;\n params.set(\"page\", String(Math.floor(options.offset / perPage) + 1));\n }\n const query = params.toString() ? `?${params}` : \"\";\n const result = await this.request<HiringListResult>(\n \"GET\",\n `/api/v1/hirings${query}`\n );\n return result.hirings;\n }\n\n /** List agents filtered by capability for auto-select.\n * GET /api/v1/agents?capability=X\n */\n async listAgentsByCapability(capability: string): Promise<AgentProfile[]> {\n return this.request<AgentProfile[]>(\n \"GET\",\n `/api/v1/agents?capability=${encodeURIComponent(capability)}`\n );\n }\n}\n","import type {\n AdapterConfigSchema,\n AdapterEnvironmentCheck,\n AdapterEnvironmentTestContext,\n AdapterEnvironmentTestResult,\n AdapterExecutionContext,\n AdapterExecutionResult,\n AdapterSessionCodec,\n ServerAdapterModule,\n} from \"@paperclipai/adapter-utils\";\nimport { AgrentingClient } from \"./client.js\";\nimport type {\n AgentProfile,\n AgrentingAdapterConfig,\n Hiring,\n} from \"./types.js\";\n\nexport const type = \"agrenting\";\nexport const label = \"Agrenting\";\n\nexport const agentConfigurationDoc = `# agrenting agent configuration\n\nAdapter: agrenting\n\nUse when:\n- A Paperclip agent should delegate each heartbeat to a remote agent hired from Agrenting.\n- The operator has an Agrenting user API token and sufficient ledger balance.\n\nCore fields:\n- agrentingUrl (required): Agrenting base URL, normally https://agrenting.com\n- apiKey (required, secret): Agrenting user API token (ap_...)\n- agentDid (required): DID of the marketplace agent to hire\n- capabilityRequested (optional): defaults to the first capability on the agent profile\n- price (optional): defaults to the agent's current base price\n- timeoutSec (optional): maximum time to poll a hiring, default 600\n- pollIntervalMs (optional): hiring status poll interval, default 2000\n- deliveryMode (optional): output by default; push requires repository access\n- repoUrl (optional): repository URL used only when deliveryMode is push\n\nRecommended API-key scopes:\n- agents:discover, agents:read, hire:create, hirings:read, hirings:cancel\n- add balance:read and artifacts:read when sharing the key with Apps/Claude\n- deposits:create and account:read/account:write are optional elevated scopes\n- set max_price_per_hire on the key to cap paid actions\n\nExecution:\n- Each Paperclip run creates one canonical Agrenting hiring.\n- The Paperclip run id is sent as client_idempotency_key so safe retries deduplicate.\n- Paperclip polls the hiring until it completes, fails, is cancelled, or times out.\n- Push delivery can use a repository URL from Paperclip and an Agrenting-stored\n GitHub token. The adapter never stores a repository token in agent config.\n`;\n\nconst TERMINAL_STATUSES = new Set([\n \"completed\",\n \"failed\",\n \"cancelled\",\n \"disputed\",\n \"refunded\",\n]);\nconst DEFAULT_TIMEOUT_SEC = 600;\nconst DEFAULT_POLL_INTERVAL_MS = 2_000;\nconst MAX_TASK_DESCRIPTION_LENGTH = 5_000;\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n return value as Record<string, unknown>;\n}\n\nfunction nonEmpty(value: unknown): string | null {\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : null;\n}\n\nfunction positiveNumber(value: unknown, fallback: number): number {\n const parsed = typeof value === \"number\" ? value : Number(value);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;\n}\n\nfunction configFrom(raw: Record<string, unknown>): AgrentingAdapterConfig {\n return {\n agrentingUrl: nonEmpty(raw.agrentingUrl) ?? \"https://agrenting.com\",\n apiKey: nonEmpty(raw.apiKey) ?? \"\",\n agentDid: nonEmpty(raw.agentDid) ?? \"\",\n capabilityRequested: nonEmpty(raw.capabilityRequested) ?? undefined,\n price: nonEmpty(raw.price) ?? undefined,\n timeoutSec: positiveNumber(raw.timeoutSec, DEFAULT_TIMEOUT_SEC),\n pollIntervalMs: positiveNumber(\n raw.pollIntervalMs,\n DEFAULT_POLL_INTERVAL_MS\n ),\n deliveryMode: raw.deliveryMode === \"push\" ? \"push\" : \"output\",\n repoUrl: nonEmpty(raw.repoUrl) ?? undefined,\n };\n}\n\nfunction taskDescriptionFrom(ctx: AdapterExecutionContext): string {\n const context = ctx.context;\n const title =\n nonEmpty(context.taskTitle) ??\n nonEmpty(context.issueTitle) ??\n nonEmpty(context.title);\n const body =\n nonEmpty(context.paperclipTaskMarkdown) ??\n nonEmpty(context.taskBody) ??\n nonEmpty(context.taskDescription) ??\n nonEmpty(context.issueDescription) ??\n nonEmpty(context.prompt) ??\n nonEmpty(context.input);\n\n let description = [title, body].filter(Boolean).join(\"\\n\\n\").trim();\n if (!description) {\n description = `Continue the assigned Paperclip work for ${ctx.agent.name}.`;\n }\n if (description.length <= MAX_TASK_DESCRIPTION_LENGTH) return description;\n return `${description.slice(0, MAX_TASK_DESCRIPTION_LENGTH - 32)}\\n\\n[truncated by Paperclip adapter]`;\n}\n\nfunction capabilityFrom(\n config: AgrentingAdapterConfig,\n context: Record<string, unknown>,\n profile: AgentProfile\n): string | null {\n return (\n nonEmpty(config.capabilityRequested) ??\n nonEmpty(context.capabilityRequested) ??\n nonEmpty(context.capability) ??\n profile.capabilities.find((capability) => capability.trim().length > 0) ??\n null\n );\n}\n\nfunction priceFrom(\n config: AgrentingAdapterConfig,\n context: Record<string, unknown>,\n profile: AgentProfile\n): string | null {\n return (\n nonEmpty(config.price) ??\n nonEmpty(context.price) ??\n nonEmpty(context.maxPrice) ??\n nonEmpty(profile.base_price)\n );\n}\n\nfunction repoUrlFrom(ctx: AdapterExecutionContext): string | undefined {\n const workspace = asRecord(ctx.context.paperclipWorkspace);\n return (\n nonEmpty(configFrom(ctx.config).repoUrl) ??\n nonEmpty(workspace?.repoUrl) ??\n undefined\n );\n}\n\nfunction taskInputFrom(ctx: AdapterExecutionContext): Record<string, unknown> {\n const input: Record<string, unknown> = {\n paperclip_run_id: ctx.runId,\n paperclip_agent_id: ctx.agent.id,\n paperclip_company_id: ctx.agent.companyId,\n };\n const mappings: Array<[string, unknown]> = [\n [\"paperclip_issue_id\", ctx.context.issueId ?? ctx.context.taskId],\n [\"paperclip_project_id\", ctx.context.projectId],\n [\"paperclip_wake_reason\", ctx.context.wakeReason],\n ];\n for (const [key, value] of mappings) {\n const normalized = nonEmpty(value);\n if (normalized) input[key] = normalized;\n }\n const wake = asRecord(ctx.context.paperclipWake);\n if (wake) input.paperclip_wake = wake;\n return input;\n}\n\nfunction outputText(hiring: Hiring): string {\n const output = hiring.task_output;\n if (typeof output === \"string\" && output.trim()) return output;\n const record = asRecord(output);\n if (record) {\n for (const key of [\"result\", \"output\", \"text\", \"summary\"]) {\n const direct = nonEmpty(record[key]);\n if (direct) return direct;\n }\n return JSON.stringify(record, null, 2);\n }\n return `Agrenting hiring ${hiring.id} completed.`;\n}\n\nfunction firstLine(value: string): string {\n return value\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .find(Boolean) ?? \"Agrenting hiring completed\";\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction resultForFailure(\n hiring: Hiring,\n message: string\n): AdapterExecutionResult {\n return {\n exitCode: 1,\n signal: null,\n timedOut: false,\n errorMessage: message,\n errorCode: `agrenting_hiring_${hiring.status}`,\n provider: \"agrenting\",\n biller: \"agrenting\",\n sessionParams: { hiringId: hiring.id },\n sessionDisplayId: hiring.id,\n resultJson: {\n hiringId: hiring.id,\n status: hiring.status,\n failedReason: hiring.failed_reason ?? null,\n },\n };\n}\n\n/** Canonical Paperclip ServerAdapterModule execution entry point. */\nexport async function executePaperclip(\n ctx: AdapterExecutionContext\n): Promise<AdapterExecutionResult> {\n const config = configFrom(ctx.config);\n if (!config.apiKey || !config.agentDid) {\n return {\n exitCode: 1,\n signal: null,\n timedOut: false,\n errorCode: \"agrenting_config_invalid\",\n errorMessage: \"Agrenting requires apiKey and agentDid.\",\n };\n }\n\n const client = new AgrentingClient(config);\n try {\n const profile = await client.getAgentProfile(config.agentDid);\n const capability = capabilityFrom(config, ctx.context, profile);\n const price = priceFrom(config, ctx.context, profile);\n if (!capability) {\n throw new Error(\n \"No capabilityRequested was configured and the Agrenting agent profile has no capabilities.\"\n );\n }\n if (!price) {\n throw new Error(\n \"No price was configured and the Agrenting agent profile has no base_price.\"\n );\n }\n\n const taskDescription = taskDescriptionFrom(ctx);\n await ctx.onLog(\n \"stdout\",\n `[agrenting] Hiring ${config.agentDid} for ${capability} at ${price}\\n`\n );\n const created = await client.hireAgent(config.agentDid, {\n taskDescription,\n capabilityRequested: capability,\n price,\n deliveryMode: config.deliveryMode,\n clientIdempotencyKey: ctx.runId,\n taskInput: taskInputFrom(ctx),\n repoUrl: repoUrlFrom(ctx),\n });\n const hiringId = created.hiring.id;\n await ctx.onMeta?.({\n adapterType: type,\n command: \"POST /api/v1/agents/:did/hire\",\n context: { hiringId, agentDid: config.agentDid, capability, price },\n });\n await ctx.onLog(\n \"stdout\",\n `[agrenting] Hiring ${hiringId} created with status ${created.hiring.status}\\n`\n );\n\n const timeoutMs = (config.timeoutSec ?? DEFAULT_TIMEOUT_SEC) * 1_000;\n const pollIntervalMs = config.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const deadline = Date.now() + timeoutMs;\n let hiring = created.hiring;\n let lastStatus = hiring.status;\n\n while (!TERMINAL_STATUSES.has(hiring.status) && Date.now() < deadline) {\n await sleep(Math.min(pollIntervalMs, Math.max(1, deadline - Date.now())));\n hiring = await client.getHiring(hiringId);\n if (hiring.status !== lastStatus) {\n lastStatus = hiring.status;\n await ctx.onLog(\n \"stdout\",\n `[agrenting] Hiring ${hiringId} is ${hiring.status}\\n`\n );\n }\n }\n\n if (!TERMINAL_STATUSES.has(hiring.status)) {\n try {\n await client.cancelHiring(hiringId);\n await ctx.onLog(\n \"stderr\",\n `[agrenting] Hiring ${hiringId} timed out and was cancelled\\n`\n );\n } catch (cancelError) {\n await ctx.onLog(\n \"stderr\",\n `[agrenting] Hiring ${hiringId} timed out; cancellation failed: ${cancelError instanceof Error ? cancelError.message : String(cancelError)}\\n`\n );\n }\n return {\n exitCode: null,\n signal: null,\n timedOut: true,\n errorCode: \"agrenting_hiring_timeout\",\n errorMessage: `Agrenting hiring ${hiringId} timed out after ${config.timeoutSec ?? DEFAULT_TIMEOUT_SEC}s.`,\n provider: \"agrenting\",\n biller: \"agrenting\",\n sessionParams: { hiringId },\n sessionDisplayId: hiringId,\n };\n }\n\n if (hiring.status !== \"completed\") {\n return resultForFailure(\n hiring,\n hiring.failed_reason ?? `Agrenting hiring ended with status ${hiring.status}.`\n );\n }\n\n const output = outputText(hiring);\n await ctx.onLog(\"stdout\", `${output}\\n`);\n const numericPrice = Number(hiring.price ?? price);\n return {\n exitCode: 0,\n signal: null,\n timedOut: false,\n provider: \"agrenting\",\n biller: \"agrenting\",\n billingType: \"fixed\",\n costUsd: Number.isFinite(numericPrice) ? numericPrice : null,\n sessionParams: { hiringId },\n sessionDisplayId: hiringId,\n summary: firstLine(output),\n resultJson: {\n hiringId,\n status: hiring.status,\n taskOutput: hiring.task_output ?? null,\n },\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const transient = /\\b(429|5\\d\\d)\\b|rate.?limit|temporar|timeout/i.test(message);\n await ctx.onLog(\"stderr\", `[agrenting] ${message}\\n`);\n return {\n exitCode: 1,\n signal: null,\n timedOut: false,\n errorCode: \"agrenting_hiring_failed\",\n errorFamily: transient ? \"transient_upstream\" : null,\n errorMessage: message,\n provider: \"agrenting\",\n biller: \"agrenting\",\n };\n }\n}\n\nfunction summarizeChecks(\n checks: AdapterEnvironmentCheck[]\n): AdapterEnvironmentTestResult[\"status\"] {\n if (checks.some((check) => check.level === \"error\")) return \"fail\";\n if (checks.some((check) => check.level === \"warn\")) return \"warn\";\n return \"pass\";\n}\n\n/** Canonical structured environment test used by Paperclip. */\nexport async function testPaperclipEnvironment(\n ctx: AdapterEnvironmentTestContext\n): Promise<AdapterEnvironmentTestResult> {\n const config = configFrom(ctx.config);\n const checks: AdapterEnvironmentCheck[] = [];\n\n let parsedUrl: URL | null = null;\n try {\n parsedUrl = new URL(config.agrentingUrl);\n if (parsedUrl.protocol !== \"http:\" && parsedUrl.protocol !== \"https:\") {\n parsedUrl = null;\n }\n } catch {\n parsedUrl = null;\n }\n if (!parsedUrl) {\n checks.push({\n code: \"agrenting_url_invalid\",\n level: \"error\",\n message: \"agrentingUrl must be an http:// or https:// URL.\",\n });\n }\n if (!config.apiKey) {\n checks.push({\n code: \"agrenting_api_key_missing\",\n level: \"error\",\n message: \"Agrenting requires a user API token.\",\n hint: \"Create an ap_... token in Agrenting and store it as a Paperclip secret.\",\n });\n }\n if (!config.agentDid) {\n checks.push({\n code: \"agrenting_agent_did_missing\",\n level: \"error\",\n message: \"Agrenting requires agentDid.\",\n });\n }\n\n if (!checks.some((check) => check.level === \"error\")) {\n const client = new AgrentingClient(config);\n let connectionOk = false;\n try {\n await client.listHirings({ limit: 1 });\n connectionOk = true;\n checks.push({\n code: \"agrenting_connection_ok\",\n level: \"info\",\n message: \"Connected to the authenticated Agrenting hiring API.\",\n });\n } catch (error) {\n checks.push({\n code: \"agrenting_connection_failed\",\n level: \"error\",\n message: \"Could not access the authenticated Agrenting hiring API.\",\n detail: error instanceof Error ? error.message : String(error),\n });\n }\n if (connectionOk) {\n try {\n const profile = await client.getAgentProfile(config.agentDid);\n checks.push({\n code: \"agrenting_agent_profile_ok\",\n level: \"info\",\n message: `Found Agrenting agent ${profile.name} (${profile.did}).`,\n detail: `${profile.capabilities.length} capabilities; base price ${profile.base_price ?? \"not reported\"}.`,\n });\n } catch (error) {\n checks.push({\n code: \"agrenting_agent_profile_failed\",\n level: \"error\",\n message: `Could not load Agrenting agent ${config.agentDid}.`,\n detail: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n\n return {\n adapterType: ctx.adapterType,\n status: summarizeChecks(checks),\n checks,\n testedAt: new Date().toISOString(),\n };\n}\n\nexport function getPaperclipConfigSchema(): AdapterConfigSchema {\n return {\n fields: [\n {\n key: \"agrentingUrl\",\n label: \"Agrenting URL\",\n type: \"text\",\n required: true,\n default: \"https://agrenting.com\",\n hint: \"Base URL of the Agrenting platform.\",\n },\n {\n key: \"apiKey\",\n label: \"API token\",\n type: \"text\",\n required: true,\n hint: \"Agrenting user API token (ap_...). Stored as a Paperclip secret.\",\n meta: { secret: true },\n },\n {\n key: \"agentDid\",\n label: \"Agent DID\",\n type: \"text\",\n required: true,\n hint: \"Marketplace agent DID, for example did:agrenting:code-reviewer.\",\n },\n {\n key: \"capabilityRequested\",\n label: \"Capability\",\n type: \"text\",\n hint: \"Optional default. Falls back to the first capability on the agent profile.\",\n },\n {\n key: \"price\",\n label: \"Price per hiring (USD)\",\n type: \"text\",\n hint: \"Optional. Falls back to the agent's current base price.\",\n },\n {\n key: \"timeoutSec\",\n label: \"Timeout seconds\",\n type: \"number\",\n default: DEFAULT_TIMEOUT_SEC,\n },\n {\n key: \"pollIntervalMs\",\n label: \"Poll interval milliseconds\",\n type: \"number\",\n default: DEFAULT_POLL_INTERVAL_MS,\n },\n {\n key: \"repoUrl\",\n label: \"Repository URL\",\n type: \"text\",\n hint: \"Optional push target. Push delivery uses a GitHub token already stored in Agrenting.\",\n },\n {\n key: \"deliveryMode\",\n label: \"Delivery mode\",\n type: \"select\",\n default: \"output\",\n options: [\n { value: \"output\", label: \"Return output\" },\n { value: \"push\", label: \"Push to repository\" },\n ],\n hint: \"Use output unless the hiring also has repository credentials.\",\n },\n ],\n };\n}\n\ntype CompatibilitySessionCodec = AdapterSessionCodec & {\n encode(state: unknown): string;\n decode(blob: string | null | undefined): unknown;\n};\n\nexport const paperclipSessionCodec: CompatibilitySessionCodec = {\n deserialize(raw: unknown): Record<string, unknown> | null {\n if (typeof raw === \"string\") {\n try {\n return asRecord(JSON.parse(raw));\n } catch {\n return null;\n }\n }\n return asRecord(raw);\n },\n serialize(params: Record<string, unknown> | null): Record<string, unknown> | null {\n return params;\n },\n getDisplayId(params: Record<string, unknown> | null): string | null {\n return nonEmpty(params?.hiringId);\n },\n encode(state: unknown): string {\n return JSON.stringify(state ?? null);\n },\n decode(blob: string | null | undefined): unknown {\n if (!blob) return null;\n try {\n return JSON.parse(blob);\n } catch {\n return null;\n }\n },\n};\n\nexport function createCanonicalServerAdapter() {\n return {\n type,\n execute: executePaperclip,\n testEnvironment: testPaperclipEnvironment,\n sessionCodec: paperclipSessionCodec,\n getConfigSchema: getPaperclipConfigSchema,\n agentConfigurationDoc,\n } satisfies ServerAdapterModule;\n}\n","/**\n * Shared cryptographic utilities for the Agrenting adapter.\n */\n\n/**\n * Verify an HMAC-SHA256 signature against a raw request body.\n * Uses constant-time comparison to prevent timing attacks.\n */\nexport async function verifyWebhookSignature(\n rawBody: string,\n signature: string,\n secret: string\n): Promise<boolean> {\n const crypto = await import(\"crypto\");\n const expected = crypto\n .createHmac(\"sha256\", secret)\n .update(rawBody)\n .digest(\"base64\");\n const sigBuf = Buffer.from(signature);\n const expectedBuf = Buffer.from(expected);\n if (sigBuf.byteLength !== expectedBuf.byteLength) {\n return false;\n }\n return crypto.timingSafeEqual(sigBuf, expectedBuf);\n}\n","/**\n * Paperclip-side webhook handler for Agrenting task events.\n *\n * This module provides:\n * - An HTTP request handler that processes incoming webhook payloads from Agrenting\n * - Task ID to Paperclip issue ID mapping registry\n * - Automatic issue status updates and comment posting on task events\n *\n * Usage: Paperclip mounts this handler at `POST /api/webhooks/agrenting/:companyId`.\n * The handler receives raw body, headers, and a Paperclip API client to update issues.\n */\n\nimport type { IncomingHttpHeaders } from \"http\";\nimport type { AgrentingAdapterConfig } from \"./types.js\";\nimport { verifyWebhookSignature } from \"./crypto.js\";\n\n// ---------------------------------------------------------------------------\n// Task → Issue mapping registry\n// ---------------------------------------------------------------------------\n\ninterface TaskMapping {\n issueId: string;\n companyId: string;\n config: AgrentingAdapterConfig;\n startedAt: number;\n status: string;\n}\n\nconst taskRegistry = new Map<string, TaskMapping>();\n\nconst TASK_REGISTRY_TTL_MS = 2 * 60 * 60 * 1000; // 2h — max age before cleanup\nconst TASK_REGISTRY_CLEANUP_INTERVAL_MS = 60_000; // 60s sweep interval\nlet registryCleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n/**\n * Sweep taskRegistry for entries older than the TTL.\n * Called periodically to bound memory growth if terminal events are lost.\n */\nfunction sweepStaleRegistryEntries(): void {\n const now = Date.now();\n for (const [id, entry] of taskRegistry) {\n if (now - entry.startedAt > TASK_REGISTRY_TTL_MS) {\n taskRegistry.delete(id);\n }\n }\n}\n\n/**\n * Start the periodic registry cleanup timer.\n * Safe to call multiple times — only one timer runs at a time.\n */\nexport function startRegistryCleanup(): void {\n if (registryCleanupTimer) return;\n registryCleanupTimer = setInterval(sweepStaleRegistryEntries, TASK_REGISTRY_CLEANUP_INTERVAL_MS);\n registryCleanupTimer.unref();\n}\n\n/**\n * Stop the periodic registry cleanup timer.\n */\nexport function stopRegistryCleanup(): void {\n if (registryCleanupTimer) {\n clearInterval(registryCleanupTimer);\n registryCleanupTimer = null;\n }\n}\n\n/**\n * Register a mapping between an Agrenting task ID and a Paperclip issue.\n * Call this before executing a task so the webhook handler knows which issue to update.\n */\nexport function registerTaskMapping(\n taskId: string,\n issueId: string,\n companyId: string,\n config: AgrentingAdapterConfig\n): void {\n taskRegistry.set(taskId, {\n issueId,\n companyId,\n config,\n startedAt: Date.now(),\n status: \"pending\",\n });\n}\n\n/**\n * Remove a task mapping from the registry.\n */\nexport function unregisterTaskMapping(taskId: string): void {\n taskRegistry.delete(taskId);\n}\n\n/**\n * Get all active task mappings.\n */\nexport function getActiveTaskMappings(): ReadonlyMap<string, TaskMapping> {\n return taskRegistry;\n}\n\n// ---------------------------------------------------------------------------\n// Webhook payload types\n// ---------------------------------------------------------------------------\n\nexport interface AgrentingWebhookPayload {\n task_id: string;\n status: string;\n output?: string;\n error_reason?: string;\n progress_percent?: number;\n progress_message?: string;\n completed_at?: string;\n created_at?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Paperclip API client interface\n// ---------------------------------------------------------------------------\n\nexport interface PaperclipApiClient {\n /** Update an issue's status and optionally post a comment */\n updateIssue(issueId: string, body: {\n status?: string;\n comment?: string;\n }): Promise<void>;\n\n /** Post a comment on an issue without changing status */\n postComment(issueId: string, body: string): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// Event handlers\n// ---------------------------------------------------------------------------\n\ninterface EventHandlerContext {\n api: PaperclipApiClient;\n mapping: TaskMapping;\n payload: AgrentingWebhookPayload;\n}\n\nconst eventHandlers: Record<\n string,\n (ctx: EventHandlerContext) => Promise<void>\n> = {\n \"task.created\": async (ctx) => {\n ctx.mapping.status = \"pending\";\n await ctx.api.postComment(\n ctx.mapping.issueId,\n `**Agrenting task created** — Task \\`${ctx.payload.task_id}\\` submitted and awaiting claim.`\n );\n },\n\n \"task.claimed\": async (ctx) => {\n ctx.mapping.status = \"claimed\";\n await ctx.api.postComment(\n ctx.mapping.issueId,\n `**Agrenting task claimed** — An agent has picked up the task and is preparing to work.`\n );\n },\n\n \"task.in_progress\": async (ctx) => {\n ctx.mapping.status = \"in_progress\";\n const progress = ctx.payload.progress_percent\n ? ` (${ctx.payload.progress_percent}%)`\n : \"\";\n const message = ctx.payload.progress_message\n ? ` — ${ctx.payload.progress_message}`\n : \"\";\n await ctx.api.postComment(\n ctx.mapping.issueId,\n `**Task in progress**${progress}${message}`\n );\n },\n\n \"task.completed\": async (ctx) => {\n ctx.mapping.status = \"completed\";\n const duration = ((Date.now() - ctx.mapping.startedAt) / 1000).toFixed(1);\n await ctx.api.updateIssue(ctx.mapping.issueId, {\n status: \"done\",\n comment: `**Agrenting task completed** — Task \\`${ctx.payload.task_id}\\` finished in ${duration}s.${\n ctx.payload.output ? `\\n\\n### Output\\n\\n${ctx.payload.output}` : \"\"\n }`,\n });\n unregisterTaskMapping(ctx.payload.task_id);\n },\n\n \"task.failed\": async (ctx) => {\n ctx.mapping.status = \"failed\";\n await ctx.api.updateIssue(ctx.mapping.issueId, {\n status: \"blocked\",\n comment: `**Agrenting task failed** — Task \\`${ctx.payload.task_id}\\` encountered an error.\\n\\n**Error:** ${ctx.payload.error_reason ?? \"No error reason provided.\"}`,\n });\n unregisterTaskMapping(ctx.payload.task_id);\n },\n\n \"task.cancelled\": async (ctx) => {\n ctx.mapping.status = \"cancelled\";\n await ctx.api.updateIssue(ctx.mapping.issueId, {\n status: \"cancelled\",\n comment: `**Agrenting task cancelled** — Task \\`${ctx.payload.task_id}\\` was cancelled.`,\n });\n unregisterTaskMapping(ctx.payload.task_id);\n },\n};\n\n// ---------------------------------------------------------------------------\n// Webhook handler factory\n// ---------------------------------------------------------------------------\n\nexport interface WebhookHandlerOptions {\n /** Secret used to verify HMAC signatures */\n webhookSecret: string;\n /** Paperclip API client for updating issues */\n api: PaperclipApiClient;\n /** Optional: handle unknown event types */\n onUnknownEvent?: (event: string, payload: AgrentingWebhookPayload) => void;\n}\n\n/**\n * Create a webhook handler function suitable for mounting in an HTTP server.\n *\n * The returned handler expects `(rawBody, headers)` and returns a Promise\n * resolving to `{ status, body, headers }` for the HTTP response.\n *\n * This design is framework-agnostic: Paperclip can wrap it in Express,\n * Fastify, or a raw Node.js http server.\n */\nexport function createWebhookHandler(options: WebhookHandlerOptions) {\n startRegistryCleanup();\n return async function handleWebhookRequest(\n rawBody: string,\n headers: IncomingHttpHeaders\n ): Promise<{ status: number; body: string; headers?: Record<string, string> }> {\n const signature =\n (headers[\"x-webhook-signature\"] as string) ??\n (headers[\"X-Webhook-Signature\"] as string) ??\n \"\";\n const eventType =\n (headers[\"x-webhook-event\"] as string) ??\n (headers[\"X-Webhook-Event\"] as string) ??\n \"\";\n\n // Parse payload\n let payload: AgrentingWebhookPayload;\n try {\n payload = JSON.parse(rawBody);\n } catch {\n return { status: 400, body: \"Invalid JSON\" };\n }\n\n // Verify signature\n const valid = await verifyWebhookSignature(\n rawBody,\n signature,\n options.webhookSecret\n );\n if (!valid) {\n return { status: 401, body: \"Invalid signature\" };\n }\n\n // Look up task mapping\n const taskId = payload.task_id;\n if (!taskId) {\n return { status: 400, body: \"Missing task_id in payload\" };\n }\n\n const mapping = taskRegistry.get(taskId);\n if (!mapping) {\n // Webhook received but no active mapping — task may have been handled\n // by the in-process listener already, or the mapping was cleaned up.\n return { status: 200, body: \"OK (no active mapping)\" };\n }\n\n // Dispatch to event handler\n const handler = eventHandlers[eventType];\n if (handler) {\n try {\n await handler({ api: options.api, mapping, payload });\n } catch (err) {\n console.error(\"[adapter-agrenting] Webhook handler error:\", err);\n return {\n status: 500,\n body: \"Internal error\",\n };\n }\n } else {\n options.onUnknownEvent?.(eventType, payload);\n }\n\n return { status: 200, body: \"OK\" };\n };\n}\n","/**\n * Fallback polling logic for Agrenting task status.\n *\n * Used when webhooks are delayed or fail to deliver.\n * Polls with exponential backoff: 10s → 30s → 60s → 120s (max 10 polls).\n */\n\nimport { AgrentingClient } from \"./client.js\";\nimport type {\n AgrentingAdapterConfig,\n AgrentingExecutionResult,\n AgrentingTask,\n} from \"./types.js\";\n\n/** Poll intervals in milliseconds (exponential backoff) — shared across polling modes */\nexport const POLL_INTERVALS_MS = [10_000, 30_000, 60_000, 120_000];\nexport const MAX_POLLS = 10;\n\n/** Compute the backoff duration for a given poll attempt (0-indexed). */\nexport function getBackoffMs(attempt: number): number {\n const index = Math.min(attempt, POLL_INTERVALS_MS.length - 1);\n return POLL_INTERVALS_MS[index];\n}\n\nexport interface PollOptions {\n config: AgrentingAdapterConfig;\n taskId: string;\n /** Deadline in ms (Date.now() + timeoutMs) */\n deadline: number;\n /** Optional callback fired on each poll cycle with the current task state */\n onStatusUpdate?: (task: AgrentingTask, pollAttempt: number) => void;\n /** Starting poll attempt (useful for resuming after a webhook delay) */\n startAttempt?: number;\n /** AbortSignal to cancel polling early (e.g., when a webhook resolves first) */\n signal?: AbortSignal;\n}\n\nexport interface PollResult {\n /** Final execution result */\n result: AgrentingExecutionResult;\n /** Number of polls performed */\n pollCount: number;\n /** Whether the result came from polling (true) or was already resolved */\n viaPolling: boolean;\n}\n\n/**\n * Poll the Agrenting task API with exponential backoff until the task\n * reaches a terminal state or the deadline is reached.\n */\nexport async function pollTaskUntilDone(\n options: PollOptions\n): Promise<PollResult> {\n const client = new AgrentingClient(options.config);\n let pollAttempt = options.startAttempt ?? 0;\n const startTime = Date.now();\n\n while (pollAttempt < MAX_POLLS) {\n // Check if polling was aborted (e.g., webhook resolved first)\n if (options.signal?.aborted) {\n return {\n result: {\n success: false,\n error: \"Polling aborted\",\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n }\n\n const now = Date.now();\n if (now >= options.deadline) {\n return {\n result: {\n success: false,\n error: `Task timed out after ${options.config.timeoutSec ?? 600}s`,\n taskId: options.taskId,\n durationMs: now - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n }\n\n // Wait for the next poll interval (respects abort signal).\n // Skip the wait on the first iteration so the first poll is immediate.\n if (pollAttempt > 0) {\n const waitMs = getBackoffMs(pollAttempt);\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, waitMs);\n if (options.signal) {\n options.signal.addEventListener(\"abort\", () => {\n clearTimeout(timer);\n resolve();\n }, { once: true });\n }\n });\n }\n\n const task = await client.getTask(options.taskId);\n pollAttempt++;\n\n options.onStatusUpdate?.(task, pollAttempt);\n\n if (task.status === \"completed\") {\n return {\n result: {\n success: true,\n output: task.output,\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n }\n\n if (task.status === \"failed\") {\n return {\n result: {\n success: false,\n error: task.error_reason ?? \"Task failed with no reason provided\",\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n }\n\n if (task.status === \"cancelled\") {\n return {\n result: {\n success: false,\n error: \"Task was cancelled\",\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n }\n }\n\n // Max polls reached without terminal state — do one final check\n const finalTask = await client.getTask(options.taskId);\n if (finalTask.status === \"completed\") {\n return {\n result: {\n success: true,\n output: finalTask.output,\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt + 1,\n viaPolling: true,\n };\n }\n\n return {\n result: {\n success: false,\n error: `Task did not complete after ${pollAttempt} polls (max ${MAX_POLLS})`,\n taskId: options.taskId,\n durationMs: Date.now() - startTime,\n },\n pollCount: pollAttempt,\n viaPolling: true,\n };\n}\n\n/**\n * Calculate when to activate fallback polling.\n * Returns the number of ms to wait before switching from webhook\n * wait mode to polling mode.\n */\nexport function getWebhookGracePeriodMs(config: AgrentingAdapterConfig): number {\n // Default: 60 seconds. If the timeout is very short, use a fraction of it.\n const timeoutMs = (config.timeoutSec ?? 600) * 1000;\n return Math.min(60_000, timeoutMs * 0.1);\n}\n","/**\n * Balance monitoring for the Agrenting adapter.\n *\n * Monitors the platform balance via `GET /api/v1/ledger/balance`\n * and provides low-balance warnings and pre-submission checks.\n */\n\nimport { AgrentingClient } from \"./client.js\";\nimport type { AgrentingAdapterConfig } from \"./types.js\";\n\nexport interface BalanceInfo {\n available: number;\n escrow: number;\n total: number;\n currency: string;\n isLow: boolean;\n isInsufficient: boolean;\n}\n\nexport interface BalanceCheckOptions {\n config: AgrentingAdapterConfig;\n /** Low balance threshold in USD (default: $10) */\n lowBalanceThresholdUsd?: number;\n /** Minimum balance required to submit a task in USD (default: $1) */\n minSubmissionBalanceUsd?: number;\n}\n\n/**\n * Fetch the current platform balance and evaluate thresholds.\n * The server returns { available, escrow, total } — we use `available`\n * for threshold checks since escrowed funds are already committed.\n */\nexport async function checkBalance(\n options: BalanceCheckOptions\n): Promise<BalanceInfo> {\n const client = new AgrentingClient(options.config);\n const lowThreshold = options.lowBalanceThresholdUsd ?? 10;\n const minSubmission = options.minSubmissionBalanceUsd ?? 1;\n\n try {\n const raw = await client.getBalance();\n const available = parseFloat(raw.available);\n const escrow = parseFloat(raw.escrow);\n const total = parseFloat(raw.total);\n\n const anyNaN = Number.isNaN(available) || Number.isNaN(escrow) || Number.isNaN(total);\n if (anyNaN) {\n return {\n available: 0,\n escrow: 0,\n total: 0,\n currency: raw.currency ?? \"USD\",\n isLow: true,\n isInsufficient: true,\n };\n }\n\n return {\n available,\n escrow,\n total,\n currency: raw.currency ?? \"USD\",\n isLow: available < lowThreshold,\n isInsufficient: available < minSubmission,\n };\n } catch {\n // If we can't fetch balance, assume insufficient to avoid failed submissions\n return {\n available: 0,\n escrow: 0,\n total: 0,\n currency: \"USD\",\n isLow: true,\n isInsufficient: true,\n };\n }\n}\n\n/**\n * Pre-submission balance check.\n * Returns { ok: true } if sufficient, or { ok: false, reason } if not.\n */\nexport async function canSubmitTask(\n options: BalanceCheckOptions\n): Promise<{ ok: true } | { ok: false; reason: string }> {\n const balanceInfo = await checkBalance(options);\n\n if (balanceInfo.isInsufficient) {\n return {\n ok: false,\n reason: `Insufficient balance: ${formatUsd(balanceInfo.available)}. Minimum required: ${formatUsd(options.minSubmissionBalanceUsd ?? 1)}.`,\n };\n }\n\n return { ok: true };\n}\n\n/**\n * Format a USD amount as a human-readable dollar string.\n */\nfunction formatUsd(amount: number): string {\n return `$${amount.toFixed(2)}`;\n}\n\n/**\n * Generate a warning comment for low balance.\n * Returns the markdown comment to post on the Paperclip issue.\n */\nexport function formatLowBalanceComment(balanceInfo: BalanceInfo): string {\n return `**Agrenting balance warning** — Available: ${formatUsd(balanceInfo.available)} ${balanceInfo.currency} (Escrowed: ${formatUsd(balanceInfo.escrow)}). Funds are running low. Add credits to avoid task submission failures.`;\n}\n\n/**\n * Generate a blocking comment for insufficient balance.\n */\nexport function formatInsufficientBalanceComment(balanceInfo: BalanceInfo): string {\n return `**Agrenting task blocked** — Insufficient balance: ${formatUsd(balanceInfo.available)} ${balanceInfo.currency}. Please add credits to your Agrenting account before retrying.`;\n}\n","/**\n * Comment formatting utilities for bidirectional sync between\n * Paperclip issues and Agrenting task message threads.\n */\n\nimport type { AgrentingAdapterConfig, TaskMessage, SendMessageResult } from \"./types.js\";\nimport { AgrentingClient } from \"./client.js\";\n\n/**\n * Process an Agrenting agent response and return the comment body\n * that should be posted on the Paperclip issue.\n *\n * This is called by the webhook handler when it receives task output\n * or progress messages that should appear as comments.\n */\nexport function formatAgentResponse(\n agentName: string,\n message: string\n): string {\n return `**${agentName} says:**\\n\\n${message}`;\n}\n\n/**\n * Forward a comment from Paperclip to the Agrenting task.\n * Used for bidirectional comment sync when the user adds a comment\n * to a Paperclip issue that has an active Agrenting task.\n *\n * @param config - Agrenting adapter configuration\n * @param taskId - The Agrenting task ID\n * @param comment - The comment content to forward\n * @param authorName - Optional author name for attribution\n * @returns The created TaskMessage or null if forwarding failed\n */\nexport async function forwardCommentToAgrenting(\n config: AgrentingAdapterConfig,\n taskId: string,\n comment: string,\n authorName?: string\n): Promise<SendMessageResult | null> {\n const client = new AgrentingClient(config);\n\n // Format the comment for Agrenting\n const formattedComment = authorName\n ? `[${authorName}]: ${comment}`\n : comment;\n\n try {\n return await client.sendMessageToTask(taskId, { message: formattedComment });\n } catch (err) {\n // Log but don't throw — comment sync is non-critical\n console.error(\n `[adapter-agrenting] Failed to forward comment to task ${taskId}:`,\n err instanceof Error ? err.message : String(err)\n );\n return null;\n }\n}\n\n/**\n * Process incoming Agrenting messages and format them for Paperclip.\n * Called by the webhook handler when it receives task messages.\n *\n * @param message - The incoming TaskMessage from Agrenting\n * @returns Formatted comment body for Paperclip\n */\nexport function processIncomingMessage(\n message: TaskMessage\n): string {\n const senderName = message.sender_name ?? \"Agent\";\n return formatAgentResponse(senderName, message.content);\n}\n","import { AgrentingClient } from \"./client.js\";\nimport type {\n AgrentingAdapterConfig,\n AgrentingExecutionResult,\n AgrentingTaskStatus,\n AgentInfo,\n AgentProfile,\n BalanceInfo as BalanceInfoRaw,\n HireAgentResult,\n HireAgentOptions,\n PaymentInfo,\n ReassignTaskResult,\n SendMessageResult,\n TransactionInfo,\n DiscoverAgentsOptions,\n CreateTaskPaymentOptions,\n Hiring,\n TaskMessage,\n HiringMessage,\n Capability,\n AutoSelectOptions,\n} from \"./types.js\";\nimport {\n createCanonicalServerAdapter,\n paperclipSessionCodec,\n} from \"./paperclip.js\";\nimport { registerTaskMapping } from \"./webhook-handler.js\";\nimport { pollTaskUntilDone } from \"./polling.js\";\nimport { canSubmitTask } from \"./balance-monitor.js\";\nimport { verifyWebhookSignature } from \"./crypto.js\";\nimport { formatAgentResponse } from \"./comment-sync.js\";\n\nconst DEFAULT_WEBHOOK_PORT = 8765;\nconst MAX_WEBHOOK_BODY_SIZE = 1024 * 1024; // 1MB — prevent OOM from oversized bodies\nconst STALE_TASK_CLEANUP_INTERVAL_MS = 60_000; // 60s\nconst STALE_TASK_TTL_MS = 2 * 60 * 60 * 1000; // 2h — max age before cleanup sweeps it\n\n/** In-memory store for webhook listeners keyed by task ID */\nconst pendingTasks = new Map<\n string,\n {\n resolve: (result: AgrentingExecutionResult) => void;\n status: AgrentingTaskStatus;\n progressPercent: number;\n progressMessage?: string;\n startedAt: number;\n createdAt: number;\n settled: boolean;\n }\n>();\n\nlet webhookServer: ReturnType<typeof import(\"http\").createServer> | null = null;\nlet staleCleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n/**\n * Sweep pendingTasks for entries that are settled or older than the TTL,\n * removing them from the map to bound memory usage.\n */\nfunction sweepStaleTasks(): void {\n const now = Date.now();\n for (const [id, entry] of pendingTasks) {\n if (entry.settled || now - entry.createdAt > STALE_TASK_TTL_MS) {\n pendingTasks.delete(id);\n }\n }\n}\n\n/**\n * JSON Schema for Agrenting adapter configuration fields.\n * Used by Paperclip server to validate adapter config at creation time.\n */\nexport function getConfigSchema(): Record<string, unknown> {\n return {\n type: \"object\",\n required: [\"agrentingUrl\", \"apiKey\", \"agentDid\"],\n properties: {\n agrentingUrl: {\n type: \"string\",\n format: \"uri\",\n description: \"Agrenting platform URL (e.g. https://www.agrenting.com)\",\n default: \"https://www.agrenting.com\",\n },\n apiKey: {\n type: \"string\",\n description: \"Agrenting API key for authentication\",\n sensitive: true,\n },\n agentDid: {\n type: \"string\",\n description:\n \"Decentralized identifier of the target agent (did:agrenting:...)\",\n },\n webhookSecret: {\n type: \"string\",\n description: \"Webhook signing secret for task completion callbacks\",\n sensitive: true,\n },\n webhookCallbackUrl: {\n type: \"string\",\n format: \"uri\",\n description:\n \"URL where Agrenting should POST task events (e.g. https://your-host:8765/webhook)\",\n },\n pricingModel: {\n type: \"string\",\n enum: [\"fixed\", \"per-token\", \"subscription\"],\n description: \"Pricing model for this agent\",\n default: \"fixed\",\n },\n timeoutSec: {\n type: \"integer\",\n minimum: 10,\n maximum: 3600,\n description: \"Task timeout in seconds\",\n default: 600,\n },\n instructionsBundleMode: {\n type: \"string\",\n enum: [\"managed\", \"inline\"],\n description: \"How agent instructions are delivered\",\n default: \"inline\",\n },\n },\n };\n}\n\n/**\n * Validate the adapter configuration and test connectivity.\n */\nexport async function testEnvironment(\n config: AgrentingAdapterConfig\n): Promise<{ ok: boolean; message: string }> {\n const client = new AgrentingClient(config);\n return client.testConnection();\n}\n\n/**\n * Start an HTTP listener that receives webhook callbacks from Agrenting.\n * Returns the base URL of the listener (for registering with Agrenting).\n *\n * The listener resolves pending `execute()` calls when task events arrive.\n * Only call this once per process — subsequent calls return the existing server.\n */\nexport async function startWebhookListener(\n config: AgrentingAdapterConfig\n): Promise<string> {\n if (webhookServer) {\n const addr = webhookServer.address();\n const port =\n typeof addr === \"object\" && addr ? addr.port : DEFAULT_WEBHOOK_PORT;\n return `http://localhost:${port}/webhook`;\n }\n\n const http = await import(\"http\");\n const port = process.env.PAPERCLIP_WEBHOOK_PORT\n ? parseInt(process.env.PAPERCLIP_WEBHOOK_PORT, 10)\n : DEFAULT_WEBHOOK_PORT;\n\n return new Promise((resolve, reject) => {\n const server = http.createServer(async (req, res) => {\n if (req.method !== \"POST\" || req.url !== \"/webhook\") {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n let bodyChunks: Buffer[] = [];\n let bodyLength = 0;\n let bodyTooLarge = false;\n req.on(\"data\", (chunk: Buffer) => {\n bodyLength += chunk.length;\n if (bodyLength > MAX_WEBHOOK_BODY_SIZE) {\n bodyTooLarge = true;\n res.writeHead(413);\n res.end(\"Request body too large\");\n req.destroy();\n return;\n }\n bodyChunks.push(chunk);\n });\n\n req.on(\"end\", async () => {\n if (bodyTooLarge) return;\n const rawBody = Buffer.concat(bodyChunks).toString(\"utf8\");\n bodyChunks = []; // free reference for GC\n const taskId = req.headers[\"x-webhook-task-id\"] as string | undefined;\n const signature =\n (req.headers[\"x-webhook-signature\"] as string) || \"\";\n\n let payload: Record<string, unknown>;\n try {\n payload = JSON.parse(rawBody);\n } catch {\n res.writeHead(400);\n res.end(\"Invalid JSON\");\n return;\n }\n\n // Verify signature if secret is configured\n if (config.webhookSecret) {\n if (!signature) {\n res.writeHead(401);\n res.end(\"Missing signature\");\n return;\n }\n const valid = await verifyWebhookSignature(\n rawBody,\n signature,\n config.webhookSecret\n );\n if (!valid) {\n res.writeHead(401);\n res.end(\"Invalid signature\");\n return;\n }\n }\n\n // Extract task ID from payload if not in header\n const resolvedTaskId =\n taskId ??\n (payload.task_id as string) ??\n (payload.taskId as string);\n\n if (resolvedTaskId) {\n const pending = pendingTasks.get(resolvedTaskId);\n if (pending && !pending.settled) {\n const status = (payload.status as AgrentingTaskStatus) ?? pending.status;\n pending.status = status;\n pending.progressPercent =\n (payload.progress_percent as number) ?? pending.progressPercent;\n pending.progressMessage =\n (payload.progress_message as string) ?? pending.progressMessage;\n\n if (status === \"completed\") {\n pending.settled = true;\n pending.resolve({\n success: true,\n output: (payload.output as string) ?? JSON.stringify(payload.output ?? {}),\n taskId: resolvedTaskId,\n durationMs: Date.now() - pending.startedAt,\n });\n } else if (status === \"failed\") {\n pending.settled = true;\n pending.resolve({\n success: false,\n error:\n (payload.error_reason as string) ??\n \"Task failed with no reason provided\",\n taskId: resolvedTaskId,\n durationMs: Date.now() - pending.startedAt,\n });\n } else if (status === \"cancelled\") {\n pending.settled = true;\n pending.resolve({\n success: false,\n error: \"Task was cancelled\",\n taskId: resolvedTaskId,\n durationMs: Date.now() - pending.startedAt,\n });\n }\n }\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/plain\" });\n res.end(\"OK\");\n });\n });\n\n server.listen(port, () => {\n webhookServer = server;\n // Start periodic cleanup of stale entries\n if (!staleCleanupTimer) {\n staleCleanupTimer = setInterval(sweepStaleTasks, STALE_TASK_CLEANUP_INTERVAL_MS);\n staleCleanupTimer.unref();\n }\n resolve(`http://localhost:${port}/webhook`);\n });\n\n server.on(\"error\", reject);\n });\n}\n\nconst WEBHOOK_STOP_TIMEOUT_MS = 5_000;\n\n/**\n * Stop the webhook listener if it was started.\n * Closes all active connections and waits up to 5s for a clean shutdown.\n */\nexport async function stopWebhookListener(): Promise<void> {\n if (!webhookServer) {\n return;\n }\n\n if (staleCleanupTimer) {\n clearInterval(staleCleanupTimer);\n staleCleanupTimer = null;\n }\n\n const server = webhookServer;\n webhookServer = null;\n\n // Force-close all active connections (Node 18.2+) so server.close() doesn't hang\n if (\"closeAllConnections\" in server && typeof server.closeAllConnections === \"function\") {\n (server as import(\"http\").Server<typeof import(\"http\").IncomingMessage, typeof import(\"http\").ServerResponse>).closeAllConnections();\n }\n\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n resolve();\n }, WEBHOOK_STOP_TIMEOUT_MS);\n timeout.unref();\n\n server.close(() => {\n clearTimeout(timeout);\n resolve();\n });\n });\n}\n\n/**\n * Register a webhook with Agrenting to receive task lifecycle events.\n * Returns the webhook ID and secret key.\n */\nexport async function registerWebhook(\n config: AgrentingAdapterConfig,\n callbackUrl?: string\n): Promise<{\n id: string;\n secretKey: string;\n callbackUrl: string;\n}> {\n const client = new AgrentingClient(config);\n const url = callbackUrl ?? (await startWebhookListener(config));\n\n const result = await client.registerWebhook({\n callbackUrl: url,\n eventTypes: [\n \"task.created\",\n \"task.claimed\",\n \"task.in_progress\",\n \"task.completed\",\n \"task.failed\",\n \"task.cancelled\",\n ],\n });\n\n return {\n id: result.id,\n secretKey: result.secret_key,\n callbackUrl: result.callback_url,\n };\n}\n\n/**\n * Deregister a webhook from Agrenting to stop receiving task lifecycle events.\n * Use this to clean up orphaned webhooks when they are no longer needed.\n */\nexport async function deregisterWebhook(\n config: AgrentingAdapterConfig,\n webhookId: string\n): Promise<void> {\n const client = new AgrentingClient(config);\n await client.deleteWebhook(webhookId);\n}\n\n/**\n * Execute a task by submitting it to the Agrenting platform.\n *\n * Uses webhook callbacks when `webhookCallbackUrl` is configured in the adapter config\n * (or when `startWebhookListener()` has been called). Falls back to polling\n * when webhooks are not available.\n *\n * When `maxPrice` is provided, the task is created with a budget and escrow funds\n * are locked via `createTaskPayment()` after submission.\n */\nexport async function execute(\n config: AgrentingAdapterConfig,\n params: {\n input: string;\n capability: string;\n instructions?: string;\n /** Maximum price in USD to budget for this task. Triggers escrow payment. */\n maxPrice?: string;\n /** Payment type: \"crypto\" | \"escrow\" | \"nowpayments\". Defaults to \"crypto\". */\n paymentType?: string;\n }\n): Promise<AgrentingExecutionResult> {\n const client = new AgrentingClient(config);\n const startTime = Date.now();\n\n // Upload instructions if managed mode is configured\n if (\n config.instructionsBundleMode === \"managed\" &&\n params.instructions\n ) {\n await client.uploadDocument({\n name: \"instructions\",\n content: params.instructions,\n documentType: \"instructions\",\n });\n }\n\n // Pre-submission balance check (non-blocking — logs warning but doesn't prevent)\n const balanceCheck = await canSubmitTask({ config });\n if (!balanceCheck.ok) {\n // Log but don't block — let the task fail naturally\n console.warn(`[adapter-agrenting] ${balanceCheck.reason}`);\n }\n\n // Submit the task to Agrenting\n const task = await client.createTask({\n providerAgentId: config.agentDid,\n capability: params.capability,\n input: params.input,\n maxPrice: params.maxPrice,\n paymentType: params.paymentType,\n });\n\n const taskId = task.id;\n\n // Lock escrow funds if a max price was specified.\n // If payment fails, cancel the orphaned task to avoid leaving it stuck on the server.\n let payment: PaymentInfo | undefined;\n if (params.maxPrice) {\n try {\n const paymentOptions: CreateTaskPaymentOptions = {};\n if (params.paymentType) paymentOptions.paymentType = params.paymentType;\n payment = await client.createTaskPayment(taskId, paymentOptions);\n console.log(`[adapter-agrenting] Escrow locked for task ${taskId}: ${payment.amount} ${payment.currency} (${payment.status})`);\n } catch (err) {\n console.error(`[adapter-agrenting] Failed to lock escrow for task ${taskId}, cancelling orphaned task:`, err);\n try {\n await client.cancelTask(taskId);\n } catch {\n // Best-effort cleanup — log but don't throw, the payment error is the real problem\n }\n return {\n success: false,\n error: `Escrow payment failed: ${err instanceof Error ? err.message : String(err)}`,\n taskId,\n durationMs: Date.now() - startTime,\n };\n }\n }\n\n // Register for webhook callbacks only when webhook mode is actually configured.\n // The taskRegistry in webhook-handler.ts is for the Paperclip-side webhook handler\n // (issue status updates), while pendingTasks below is for the in-process listener\n // (resolving execute() promises). They serve different purposes.\n if (config.webhookCallbackUrl || config.webhookSecret) {\n registerTaskMapping(taskId, taskId, config.agrentingUrl, config);\n return executeWithWebhook(client, config, taskId, startTime);\n }\n\n // Fall back to polling — delegate to pollTaskUntilDone\n return executeWithPolling(config, taskId, startTime);\n}\n\n/**\n * Execute with webhook: register a listener, submit task, wait for callback.\n * Falls back to polling if no webhook received within the grace period.\n */\nasync function executeWithWebhook(\n _client: AgrentingClient,\n config: AgrentingAdapterConfig,\n taskId: string,\n startTime: number\n): Promise<AgrentingExecutionResult> {\n // Ensure the listener is running\n await startWebhookListener(config);\n\n const deadline = startTime + (config.timeoutSec ?? 600) * 1000;\n\n // AbortController for clean cancellation when webhook resolves first\n const abortController = new AbortController();\n\n // Register the pending task so the webhook handler can resolve it\n const pending = new Promise<AgrentingExecutionResult>((resolve) => {\n pendingTasks.set(taskId, {\n resolve,\n status: \"pending\",\n progressPercent: 0,\n startedAt: startTime,\n createdAt: Date.now(),\n settled: false,\n });\n }).then((result) => {\n // Webhook resolved — abort any in-flight polling\n abortController.abort();\n return result;\n });\n\n // Race between webhook callback and timeout\n const timeout = new Promise<AgrentingExecutionResult>((resolve) => {\n const ms = deadline - Date.now();\n setTimeout(() => {\n const entry = pendingTasks.get(taskId);\n if (entry && !entry.settled) {\n entry.settled = true;\n }\n resolve({\n success: false,\n error: `Task timed out after ${config.timeoutSec ?? 600}s`,\n taskId,\n durationMs: Date.now() - startTime,\n });\n }, Math.max(ms, 0));\n });\n\n // If webhook doesn't resolve within grace period, fall back to polling.\n // Polling is deferred so it only starts when the timeout actually fires,\n // avoiding wasted HTTP calls when the webhook wins.\n return Promise.race([pending, timeout.then(async (result) => {\n if (!result.success && result.error?.includes(\"timed out\")) {\n const pollingFallback = await pollTaskUntilDone({\n config,\n taskId,\n deadline,\n signal: abortController.signal,\n });\n return pollingFallback.result;\n }\n return result;\n })]);\n}\n\n/**\n * Execute with polling by delegating to pollTaskUntilDone.\n * Avoids reimplementing the backoff loop that polling.ts already provides.\n */\nasync function executeWithPolling(\n config: AgrentingAdapterConfig,\n taskId: string,\n startTime: number\n): Promise<AgrentingExecutionResult> {\n const deadline = startTime + (config.timeoutSec ?? 600) * 1000;\n const { result } = await pollTaskUntilDone({ config, taskId, deadline });\n return result;\n}\n\n/**\n * Get the current progress of a task including percentage and message.\n * Useful for progress monitoring in UI dashboards.\n */\nexport async function getTaskProgress(\n config: AgrentingAdapterConfig,\n taskId: string\n): Promise<{\n status: AgrentingTaskStatus;\n progressPercent: number;\n progressMessage?: string;\n timeline: Array<{\n event_type: string;\n timestamp: string;\n progress_percent?: number;\n progress_message?: string;\n }>;\n}> {\n const client = new AgrentingClient(config);\n const [progress, timeline] = await Promise.all([\n client.getTaskProgress(taskId),\n client.getTaskTimeline(taskId),\n ]);\n\n return {\n status: progress.status as AgrentingTaskStatus,\n progressPercent: progress.progress_percent,\n progressMessage: progress.progress_message,\n timeline: timeline.events,\n };\n}\n\n/**\n * Discover marketplace agents available for hire.\n * Filters by capability, price range, reputation, and availability.\n */\nexport async function discoverAgents(\n config: AgrentingAdapterConfig,\n options: DiscoverAgentsOptions = {}\n): Promise<AgentInfo[]> {\n const client = new AgrentingClient(config);\n return client.discoverAgents(options);\n}\n\n/**\n * Get the current platform balance including available, escrowed, and total amounts.\n */\nexport async function getBalance(\n config: AgrentingAdapterConfig\n): Promise<BalanceInfoRaw> {\n const client = new AgrentingClient(config);\n return client.getBalance();\n}\n\n/**\n * List recent ledger transactions.\n */\nexport async function getTransactions(\n config: AgrentingAdapterConfig,\n options: { limit?: number; offset?: number; type?: string } = {}\n): Promise<TransactionInfo[]> {\n const client = new AgrentingClient(config);\n return client.getTransactions(options);\n}\n\n/**\n * Deposit funds into the Agrenting ledger.\n */\nexport async function deposit(\n config: AgrentingAdapterConfig,\n params: { amount: string; currency?: string; paymentMethod?: string }\n): Promise<{ transaction_id: string; status: string; deposit_address?: string; payment_url?: string }> {\n const client = new AgrentingClient(config);\n return client.deposit(params);\n}\n\n/**\n * Withdraw funds from the Agrenting ledger to an external wallet.\n */\nexport async function withdraw(\n config: AgrentingAdapterConfig,\n params: { amount: string; currency?: string; withdrawalAddressId?: string }\n): Promise<{ transaction_id: string; status: string }> {\n const client = new AgrentingClient(config);\n return client.withdraw(params);\n}\n\n/**\n * Get the payment status and escrow details for a task.\n */\nexport async function getTaskPayment(\n config: AgrentingAdapterConfig,\n taskId: string\n): Promise<PaymentInfo | undefined> {\n const client = new AgrentingClient(config);\n try {\n return await client.getTaskPayment(taskId);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Cancel a running task.\n */\nexport async function cancelTask(\n config: AgrentingAdapterConfig,\n taskId: string\n): Promise<{ success: boolean; error?: string }> {\n const client = new AgrentingClient(config);\n try {\n await client.cancelTask(taskId);\n pendingTasks.delete(taskId);\n return { success: true };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : \"Failed to cancel task\",\n };\n }\n}\n\n// -------------------------------------------------------------------------\n// New adapter functions for hire, messaging, auto-select, and retry\n// -------------------------------------------------------------------------\n\n/** Task retry configuration */\nconst TASK_MAX_RETRIES = 2;\nconst TASK_RETRY_BASE_DELAY_MS = 1000; // 1s initial delay\nconst TASK_RETRY_MAX_DELAY_MS = 30_000; // 30s max delay\n\n/**\n * Hire an agent by DID. Returns hiring record and adapter config for auto-provisioning.\n * This is the primary entry point for the \"browse marketplace, click Hire\" flow.\n */\nexport async function hireAgent(\n config: AgrentingAdapterConfig,\n agentDid: string,\n options: HireAgentOptions\n): Promise<HireAgentResult> {\n const client = new AgrentingClient(config);\n return client.hireAgent(agentDid, options);\n}\n\n/**\n * Get full agent profile by DID.\n * Returns description, capabilities, pricing, reputation, and availability.\n */\nexport async function getAgentProfile(\n config: AgrentingAdapterConfig,\n agentDid: string\n): Promise<AgentProfile> {\n const client = new AgrentingClient(config);\n return client.getAgentProfile(agentDid);\n}\n\n/**\n * Send a message to an active task for bidirectional communication.\n * Used for sending follow-up instructions to the remote agent mid-task.\n */\nexport async function sendMessageToTask(\n config: AgrentingAdapterConfig,\n taskId: string,\n message: string\n): Promise<SendMessageResult> {\n const client = new AgrentingClient(config);\n return client.sendMessageToTask(taskId, { message });\n}\n\n/**\n * Get messages for a task (bidirectional comment history).\n */\nexport async function getTaskMessages(\n config: AgrentingAdapterConfig,\n taskId: string\n): Promise<TaskMessage[]> {\n const client = new AgrentingClient(config);\n return client.getTaskMessages(taskId);\n}\n\n/**\n * Reassign a failed/cancelled task to a different agent.\n * If newAgentDid is not provided, the system will auto-select a replacement.\n */\nexport async function reassignTask(\n config: AgrentingAdapterConfig,\n taskId: string,\n newAgentDid?: string\n): Promise<ReassignTaskResult> {\n const client = new AgrentingClient(config);\n return client.reassignTask(taskId, newAgentDid);\n}\n\n/**\n * List all available capabilities with descriptions and usage stats.\n * Helps with agent discovery and validation.\n */\nexport async function listCapabilities(\n config: AgrentingAdapterConfig\n): Promise<Capability[]> {\n const client = new AgrentingClient(config);\n return client.listCapabilities();\n}\n\n/**\n * Send a message to a hiring for communication with the hired agent.\n */\nexport async function sendMessageToHiring(\n config: AgrentingAdapterConfig,\n hiringId: string,\n message: string\n): Promise<HiringMessage> {\n const client = new AgrentingClient(config);\n return client.sendMessageToHiring(hiringId, message);\n}\n\n/**\n * Get messages for a hiring.\n */\nexport async function getHiringMessages(\n config: AgrentingAdapterConfig,\n hiringId: string\n): Promise<HiringMessage[]> {\n const client = new AgrentingClient(config);\n return client.getHiringMessages(hiringId);\n}\n\n/**\n * Retry a failed hiring.\n */\nexport async function retryHiring(\n config: AgrentingAdapterConfig,\n hiringId: string,\n options?: { reason?: string }\n): Promise<Hiring> {\n const client = new AgrentingClient(config);\n return client.retryHiring(hiringId, options);\n}\n\n/**\n * Get a hiring by ID.\n */\nexport async function getHiring(\n config: AgrentingAdapterConfig,\n hiringId: string\n): Promise<Hiring> {\n const client = new AgrentingClient(config);\n return client.getHiring(hiringId);\n}\n\n/**\n * List hirings for the authenticated agent.\n */\nexport async function listHirings(\n config: AgrentingAdapterConfig,\n options?: { status?: string; limit?: number; offset?: number }\n): Promise<Hiring[]> {\n const client = new AgrentingClient(config);\n return client.listHirings(options);\n}\n\n/** Cancel an active hiring and release its escrow according to Agrenting policy. */\nexport async function cancelHiring(\n config: AgrentingAdapterConfig,\n hiringId: string\n): Promise<Hiring> {\n const client = new AgrentingClient(config);\n return client.cancelHiring(hiringId);\n}\n\n/**\n * Auto-select mode: given a capability requirement, discover the best agent,\n * hire them, and return the adapter config for immediate use.\n *\n * Selection algorithm:\n * 1. Call listCapabilities() to validate capability exists\n * 2. Call GET /api/v1/agents filtered by capability\n * 3. Sort by: availability first, then reputation_score desc, then base_price asc\n * 4. Call hireAgent() to auto-provision\n * 5. Return adapter config\n */\nexport async function autoSelectAgent(\n config: AgrentingAdapterConfig,\n options: AutoSelectOptions\n): Promise<HireAgentResult & { selectedAgent: AgentProfile }> {\n const client = new AgrentingClient(config);\n\n // 1. Validate capability exists\n const capabilities = await client.listCapabilities();\n const capabilityExists = capabilities.some(\n (c) => c.name === options.capability || c.name.toLowerCase() === options.capability.toLowerCase()\n );\n if (!capabilityExists) {\n throw new Error(`Capability \"${options.capability}\" not found. Available: ${capabilities.map(c => c.name).join(\", \")}`);\n }\n\n // 2. Get agents filtered by capability\n const agents = await client.listAgentsByCapability(options.capability);\n if (agents.length === 0) {\n throw new Error(`No agents available for capability \"${options.capability}\"`);\n }\n\n // 3. Filter by options and sort\n let filtered = agents;\n\n // Filter by max price\n if (options.maxPrice) {\n const maxPriceNum = parseFloat(options.maxPrice);\n filtered = filtered.filter((a) => {\n if (!a.base_price) return true; // No price info = assume fits budget\n return parseFloat(a.base_price) <= maxPriceNum;\n });\n }\n\n // Filter by min reputation\n if (options.minReputation) {\n const minRep = options.minReputation;\n filtered = filtered.filter((a) => {\n if (!a.reputation_score) return false; // No reputation = excluded\n const reputation = Number(a.reputation_score);\n return Number.isFinite(reputation) && reputation >= minRep;\n });\n }\n\n if (filtered.length === 0) {\n throw new Error(\n `No agents match criteria for capability \"${options.capability}\" (maxPrice=${options.maxPrice ?? \"any\"}, minReputation=${options.minReputation ?? \"any\"})`\n );\n }\n\n // Sort: availability first, then by specified sort criteria\n const sortBy = options.sortBy ?? \"reputation_score\";\n\n // Prefer available agents if requested\n if (options.preferAvailable ?? true) {\n filtered.sort((a, b) => {\n const aAvail =\n (a.availability_status ?? a.availability ?? a.status) === \"available\"\n ? 0\n : 1;\n const bAvail =\n (b.availability_status ?? b.availability ?? b.status) === \"available\"\n ? 0\n : 1;\n if (aAvail !== bAvail) return aAvail - bAvail;\n return 0;\n });\n }\n\n // Secondary sort\n filtered.sort((a, b) => {\n if (sortBy === \"reputation_score\") {\n const aReputation = Number(a.reputation_score ?? 0);\n const bReputation = Number(b.reputation_score ?? 0);\n return (\n (Number.isFinite(bReputation) ? bReputation : 0) -\n (Number.isFinite(aReputation) ? aReputation : 0)\n );\n }\n if (sortBy === \"base_price\") {\n const aPrice = parseFloat(a.base_price ?? \"999999\");\n const bPrice = parseFloat(b.base_price ?? \"999999\");\n return aPrice - bPrice;\n }\n if (sortBy === \"availability\") {\n const aAvail =\n (a.availability_status ?? a.availability ?? a.status) === \"available\"\n ? 0\n : 1;\n const bAvail =\n (b.availability_status ?? b.availability ?? b.status) === \"available\"\n ? 0\n : 1;\n return aAvail - bAvail;\n }\n return 0;\n });\n\n // 4. Hire the best agent\n const selectedAgent = filtered[0];\n const hireResult = await client.hireAgent(selectedAgent.did, {\n taskDescription: options.taskDescription,\n capabilityRequested: options.capability,\n price: selectedAgent.base_price ?? options.maxPrice ?? \"0\",\n deliveryMode: \"output\",\n });\n\n // 5. Return combined result\n return {\n ...hireResult,\n selectedAgent,\n };\n}\n\n/**\n * Execute a task with retry logic.\n * If the task fails, it will be retried up to TASK_MAX_RETRIES times\n * with exponential backoff.\n */\nexport async function executeWithRetry(\n config: AgrentingAdapterConfig,\n params: {\n input: string;\n capability: string;\n instructions?: string;\n maxPrice?: string;\n paymentType?: string;\n maxRetries?: number;\n }\n): Promise<AgrentingExecutionResult> {\n const maxRetries = params.maxRetries ?? TASK_MAX_RETRIES;\n let lastResult: AgrentingExecutionResult | undefined;\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n lastResult = await execute(config, params);\n\n if (lastResult.success) {\n return lastResult;\n }\n\n // If task failed but we have retries remaining, wait and retry\n if (attempt < maxRetries && lastResult.error) {\n const delayMs = Math.min(\n TASK_RETRY_BASE_DELAY_MS * Math.pow(2, attempt),\n TASK_RETRY_MAX_DELAY_MS\n );\n console.warn(\n `[adapter-agrenting] Task failed on attempt ${attempt + 1}, retrying in ${delayMs}ms: ${lastResult.error}`\n );\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n continue;\n }\n\n return lastResult;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n\n if (attempt < maxRetries) {\n const delayMs = Math.min(\n TASK_RETRY_BASE_DELAY_MS * Math.pow(2, attempt),\n TASK_RETRY_MAX_DELAY_MS\n );\n console.warn(\n `[adapter-agrenting] Execution error on attempt ${attempt + 1}, retrying in ${delayMs}ms: ${lastError.message}`\n );\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n continue;\n }\n }\n }\n\n // All retries exhausted\n return {\n success: false,\n error: lastError?.message ?? lastResult?.error ?? \"Task failed after all retries\",\n taskId: lastResult?.taskId,\n durationMs: lastResult?.durationMs ?? 0,\n };\n}\n\n/**\n * Forward a comment from Paperclip to the Agrenting task.\n * Used for bidirectional comment sync when the user adds a comment\n * to a Paperclip issue that has an active Agrenting task.\n */\nexport async function forwardCommentToAgrenting(\n config: AgrentingAdapterConfig,\n taskId: string,\n comment: string,\n authorName?: string\n): Promise<SendMessageResult | null> {\n const client = new AgrentingClient(config);\n\n // Format the comment for Agrenting\n const formattedComment = authorName\n ? `[${authorName}]: ${comment}`\n : comment;\n\n try {\n return await client.sendMessageToTask(taskId, { message: formattedComment });\n } catch (err) {\n // Log but don't throw — comment sync is non-critical\n console.error(\n `[adapter-agrenting] Failed to forward comment to task ${taskId}:`,\n err instanceof Error ? err.message : String(err)\n );\n return null;\n }\n}\n\n/**\n * Process incoming Agrenting messages and format them for Paperclip.\n * Called by the webhook handler when it receives task messages.\n */\nexport function processIncomingMessage(\n message: TaskMessage\n): string {\n const senderName = message.sender_name ?? \"Agent\";\n return formatAgentResponse(senderName, message.content);\n}\n\n// ─── Legacy pre-0.4 Paperclip compatibility surface ────────────────────────\n// Kept as named exports for callers that adopted the package's earlier\n// task-oriented adapter shape. The current package-root ServerAdapterModule is\n// implemented in paperclip.ts.\n\n/** Paperclip skill shape (subset of the canonical Paperclip Skill). */\nexport interface PaperclipSkill {\n id: string;\n name: string;\n description?: string;\n}\n\n/**\n * Detect a sensible default model/provider for the configured Agrenting agent.\n * Paperclip calls this to pre-populate the adapter UI when an agent is\n * created. Returns null if no info is available.\n */\nexport async function detectModel(\n config: Pick<AgrentingAdapterConfig, \"agrentingUrl\" | \"apiKey\" | \"agentDid\">\n): Promise<{ provider: string; model: string } | null> {\n if (!config.agentDid) return null;\n try {\n const profile = await getAgentProfile(config as AgrentingAdapterConfig, config.agentDid);\n const provider = (profile as { ai_provider?: string }).ai_provider ?? null;\n const model = (profile as { ai_model?: string }).ai_model ?? null;\n if (provider && model) return { provider, model };\n } catch {\n // Surface as \"no detection\" rather than a hard error — Paperclip falls\n // back to user input.\n }\n return null;\n}\n\n/**\n * Enumerate the configured Agrenting agent's capabilities and map them to\n * Paperclip's Skill shape.\n */\nexport async function listSkills(\n config: AgrentingAdapterConfig\n): Promise<PaperclipSkill[]> {\n const profile = await getAgentProfile(config, config.agentDid);\n const capabilities = profile.capabilities ?? [];\n return capabilities.map((cap) => ({\n id: `${config.agentDid}:${cap}`,\n name: cap,\n description: `Capability \"${cap}\" of agent ${config.agentDid}`,\n }));\n}\n\n/**\n * Reconcile the agent's current capabilities against Paperclip's local skill\n * registry. Returns sets to add and remove.\n */\nexport async function syncSkills(\n config: AgrentingAdapterConfig,\n existing: PaperclipSkill[]\n): Promise<{ added: PaperclipSkill[]; removed: PaperclipSkill[] }> {\n const remote = await listSkills(config);\n const remoteIds = new Set(remote.map((s) => s.id));\n const existingIds = new Set(existing.map((s) => s.id));\n return {\n added: remote.filter((s) => !existingIds.has(s.id)),\n removed: existing.filter((s) => !remoteIds.has(s.id)),\n };\n}\n\n/**\n * Session codec — Paperclip uses this to serialise session state across\n * heartbeats. Hirings carry no rich session state, so we pass JSON through.\n */\nexport const sessionCodec = paperclipSessionCodec;\n\n/**\n * Legacy `AgentAdapter.invoke`. Forwards to {@link execute}.\n */\nexport async function invoke(\n config: AgrentingAdapterConfig,\n params: {\n input: string;\n capability: string;\n instructions?: string;\n maxPrice?: string;\n paymentType?: string;\n }\n): Promise<AgrentingExecutionResult> {\n return execute(config, params);\n}\n\n/**\n * Legacy `AgentAdapter.status`. Returns the current run status.\n */\nexport async function status(\n config: AgrentingAdapterConfig,\n taskId: string\n): Promise<{\n status: AgrentingTaskStatus;\n progressPercent: number;\n progressMessage?: string;\n}> {\n const progress = await getTaskProgress(config, taskId);\n return {\n status: progress.status,\n progressPercent: progress.progressPercent,\n progressMessage: progress.progressMessage,\n };\n}\n\n/**\n * Legacy `AgentAdapter.cancel`. Cancels a running task; throws on failure\n * so Paperclip can treat the call as a void Promise.\n */\nexport async function cancel(\n config: AgrentingAdapterConfig,\n taskId: string\n): Promise<void> {\n const result = await cancelTask(config, taskId);\n if (!result.success) {\n throw new Error(result.error ?? \"Failed to cancel task\");\n }\n}\n\n/**\n * Create the server-side adapter module.\n * Paperclip plugin loaders call this factory from the package root. The\n * current ServerAdapterModule members are combined with explicitly named\n * compatibility helpers for pre-0.4 consumers.\n */\nexport function createServerAdapter() {\n const canonical = createCanonicalServerAdapter();\n return {\n ...canonical,\n name: \"agrenting\" as const,\n // Legacy helpers remain available under explicit names. The canonical\n // Paperclip keys above use AdapterExecutionContext and structured tests.\n legacyExecute: execute,\n legacyTestEnvironment: testEnvironment,\n getLegacyConfigSchema: getConfigSchema,\n startWebhookListener,\n stopWebhookListener,\n registerWebhook,\n deregisterWebhook,\n getTaskProgress,\n getTaskPayment,\n cancelTask,\n discoverAgents,\n getAgentProfile,\n hireAgent,\n sendMessageToTask,\n getTaskMessages,\n reassignTask,\n listCapabilities,\n sendMessageToHiring,\n getHiringMessages,\n retryHiring,\n cancelHiring,\n getHiring,\n listHirings,\n autoSelectAgent,\n executeWithRetry,\n forwardCommentToAgrenting,\n processIncomingMessage,\n getBalance,\n getTransactions,\n deposit,\n withdraw,\n // Legacy pre-0.4 contract additions:\n invoke,\n status,\n cancel,\n legacyDetectModel: detectModel,\n legacyListSkills: listSkills,\n legacySyncSkills: syncSkills,\n };\n}\n","/**\n * Exportable Paperclip Apps v2 gallery descriptor.\n *\n * Paperclip's current gallery is compiled into the Paperclip repository, so\n * this package cannot register itself at runtime. Keep this descriptor aligned\n * with Paperclip's AppGalleryEntry contract for a future upstream gallery PR.\n */\nexport interface AgrentingAppGalleryEntry {\n key: string;\n name: string;\n logoUrl: string;\n tagline: string;\n description?: string;\n authKind: \"oauth\" | \"api_key\" | \"none\";\n transportTemplate: {\n transport: \"remote_http\";\n url: string;\n };\n credentialFields: Array<{\n label: string;\n configPath: string;\n helpUrl: string;\n required?: boolean;\n placement?: \"header\" | \"env\";\n key?: string;\n prefix?: string | null;\n }>;\n recommendedDefaults: Record<string, unknown>;\n urlPatterns: string[];\n}\n\nexport const agrentingAppGalleryEntry = {\n key: \"agrenting\",\n name: \"Agrenting\",\n logoUrl:\n \"https://www.google.com/s2/favicons?domain=agrenting.com&sz=64\",\n tagline: \"Discover and hire governed remote AI agents.\",\n description:\n \"Give Paperclip agents governed access to discover, hire, monitor, and cancel remote agents in the Agrenting marketplace.\",\n authKind: \"api_key\",\n transportTemplate: {\n transport: \"remote_http\",\n url: \"https://agrenting.com/mcp/hirer\",\n },\n credentialFields: [\n {\n label: \"Agrenting API key\",\n configPath: \"credentials.authorization\",\n helpUrl: \"https://agrenting.com/dashboard/api-keys\",\n required: true,\n placement: \"header\",\n key: \"Authorization\",\n prefix: \"Bearer \",\n },\n ],\n recommendedDefaults: {\n access: \"all_agents\",\n askFirstRiskLevels: [\"write\", \"destructive\"],\n },\n urlPatterns: [\"https://agrenting.com/mcp/hirer*\"],\n} satisfies AgrentingAppGalleryEntry;\n"],"mappings":"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","names":["port","status","forwardCommentToAgrenting","processIncomingMessage"]}