Files
PaperClipAI/server/src/adapters/http/execute.ts
T
DottaandPaperclip 4857799a88 feat(connections): deliver saved instructions to authorized agent turns (#15216)
Persist optional connection instructions and deliver authorized snapshots to agent execution prompts. Keep provider templates with each app definition, preserve edits and opt-outs, and replace sessions when guidance or access changes.

Use shared production settings across setup and Permissions, with source visibility in agent Instructions. Add the initial memory-provider defaults and managed Honcho workspace configuration. Include migration 0298 and regression coverage for generic providers, runtime delivery, authorization, and catalog regeneration.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-05 18:16:00 -05:00

66 lines
2.1 KiB
TypeScript

import type { AdapterExecutionContext, AdapterExecutionResult } from "../types.js";
import { asString, asNumber, parseObject } from "../utils.js";
import { guardedHttpAdapterFetch } from "./remote-fetch.js";
export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExecutionResult> {
const { config, runId, agent, context } = ctx;
const url = asString(config.url, "");
if (!url) throw new Error("HTTP adapter missing url");
const method = asString(config.method, "POST");
const timeoutMs = asNumber(config.timeoutMs, 0);
const headers = parseObject(config.headers) as Record<string, string>;
const payloadTemplate = parseObject(config.payloadTemplate);
const body = {
...payloadTemplate,
agentId: agent.id,
runId,
context,
connectionInstructions: context.connectionInstructions ?? null,
...(ctx.runtimeTools ? { paperclipRuntimeTools: ctx.runtimeTools } : {}),
};
const controller = new AbortController();
const timer = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
try {
// HTTP adapters have no child-process spawn event. Signal immediately
// before starting the remote request so dispatch gates can release without
// waiting for the endpoint to respond.
ctx.onDispatch?.();
const res = await guardedHttpAdapterFetch(url, {
method,
headers: {
"content-type": "application/json",
...headers,
},
body: JSON.stringify(body),
...(timer ? { signal: controller.signal } : {}),
});
if (!res.ok) {
throw new Error(`HTTP invoke failed with status ${res.status}`);
}
return {
exitCode: 0,
signal: null,
timedOut: false,
summary: `HTTP ${method} ${url}`,
};
} catch (err) {
if (timer && err instanceof Error && err.name === "AbortError") {
return {
exitCode: null,
signal: null,
timedOut: true,
errorMessage: `HTTP ${method} ${url} timed out after ${timeoutMs}ms`,
errorCode: "timeout",
};
}
throw err;
} finally {
if (timer) clearTimeout(timer);
}
}