stable-harness 0.0.140 → 0.0.144
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -17
- package/dist/index.js +1 -1
- package/dist/runtime/skills/skill-metadata.js +1 -1
- package/dist/workspace/compile.js +1 -1
- package/docs/0.1.0-tool-guard-benchmark.zh.md +5 -5
- package/docs/architecture/system-architecture.zh.md +3 -3
- package/docs/evaluation/0.1.0-bfcl-targeted-model-matrix.zh.md +306 -306
- package/docs/evaluation/0.1.0-bfcl-targeted-review-matrix.zh.md +1 -1
- package/docs/evaluation/0.1.0-bfcl-tool-guard.zh.md +1 -1
- package/docs/granite-tool-calling-comparison.zh.md +8 -8
- package/docs/guides/getting-started.md +14 -6
- package/docs/guides/index.md +5 -3
- package/docs/guides/integration-guide.md +44 -43
- package/docs/guides/operator-runbook.md +51 -3
- package/docs/guides/runtime-governance-proof.md +4 -4
- package/docs/guides/workspace-authoring.md +2 -2
- package/docs/guides/workspace-docker-build.md +3 -3
- package/docs/memory/0.1.0-memory-design.zh.md +20 -0
- package/docs/memory/0.1.0-step-09-deepagents-native-memory.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-langmem-shaped-provider.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-memory-adapter-projection.zh.md +3 -3
- package/docs/memory/0.1.0-step-09-memory-contract.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-memory-governance-approval.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-memory-lifecycle-hooks.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-memory-maintenance-boundary.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-memory-persistence-boundary.zh.md +1 -1
- package/docs/protocols/coverage-matrix.md +114 -0
- package/docs/protocols/http-runtime.md +31 -8
- package/docs/protocols/langgraph-compatible.md +75 -17
- package/docs/protocols/openai-compatible.md +25 -7
- package/docs/protocols/{agent-protocols.md → protocol-facades.md} +76 -18
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/adapter.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin/task-inventory.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-call-repair.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-tool-policy.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/gateway/tool-failure-events.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/raw-tool-call-parser.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/stream-events.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/substrate/checkpoint.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/tool-repeat-visibility.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/trace-projection.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/vfs-backend.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/package.json +2 -2
- package/node_modules/@stable-harness/adapter-langgraph/dist/src/graph.js +1 -1
- package/node_modules/@stable-harness/adapter-langgraph/dist/src/index.js +1 -1
- package/node_modules/@stable-harness/adapter-langgraph/dist/src/runtime.js +1 -1
- package/node_modules/@stable-harness/adapter-langgraph/dist/src/skill-providers.js +1 -1
- package/node_modules/@stable-harness/adapter-langgraph/dist/src/types.d.ts +1 -0
- package/node_modules/@stable-harness/adapter-langgraph/package.json +2 -2
- package/node_modules/@stable-harness/core/dist/boundary-scan.js +1 -1
- package/node_modules/@stable-harness/core/dist/index.d.ts +1 -0
- package/node_modules/@stable-harness/core/dist/index.js +1 -1
- package/node_modules/@stable-harness/core/dist/memory-plugins/shared.js +1 -1
- package/node_modules/@stable-harness/core/dist/memory-plugins.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/event-evidence.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/execution-review.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/synthesis/fields.js +1 -1
- package/node_modules/@stable-harness/core/dist/recovery/execution-contract.js +1 -1
- package/node_modules/@stable-harness/core/dist/recovery/tool-call-structure.js +1 -1
- package/node_modules/@stable-harness/core/dist/recovery/tool-call.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/direct-tool-call.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/inspection/methods.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/inspection/replay.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/persistence/artifacts.d.ts +4 -0
- package/node_modules/@stable-harness/core/dist/runtime/persistence/artifacts.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/persistence/queue.d.ts +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/persistence/queue.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/persistence/stores.d.ts +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/persistence/stores.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/persistence/system-data.d.ts +34 -0
- package/node_modules/@stable-harness/core/dist/runtime/persistence/system-data.js +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/recovery/adapter-result.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/recovery/non-focused-recovery.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime.js +1 -1
- package/node_modules/@stable-harness/core/dist/workflows/index.d.ts +20 -0
- package/node_modules/@stable-harness/core/dist/workflows/index.js +1 -1
- package/node_modules/@stable-harness/core/package.json +3 -3
- package/node_modules/@stable-harness/governance/dist/src/approval-queue.d.ts +1 -0
- package/node_modules/@stable-harness/governance/dist/src/approval-queue.js +1 -1
- package/node_modules/@stable-harness/governance/dist/src/index.d.ts +1 -1
- package/node_modules/@stable-harness/governance/dist/src/index.js +1 -1
- package/node_modules/@stable-harness/governance/package.json +1 -1
- package/node_modules/@stable-harness/memory/package.json +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/http-events.d.ts +2 -0
- package/node_modules/@stable-harness/protocols/dist/src/http-events.js +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/http-server.d.ts +5 -1
- package/node_modules/@stable-harness/protocols/dist/src/http-server.js +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/index.d.ts +3 -3
- package/node_modules/@stable-harness/protocols/dist/src/index.js +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/openai-compatible.js +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/openai-payload.d.ts +89 -0
- package/node_modules/@stable-harness/protocols/dist/src/openai-payload.js +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/{agent-protocols.d.ts → protocol-facades.d.ts} +4 -10
- package/node_modules/@stable-harness/protocols/dist/src/protocol-facades.js +1 -0
- package/node_modules/@stable-harness/protocols/dist/src/protocol-utils.d.ts +505 -0
- package/node_modules/@stable-harness/protocols/dist/src/protocol-utils.js +1 -0
- package/node_modules/@stable-harness/protocols/package.json +2 -2
- package/node_modules/@stable-harness/tool-gateway/dist/src/argument-guard.js +1 -1
- package/node_modules/@stable-harness/tool-gateway/dist/src/schema-validation.js +1 -1
- package/node_modules/@stable-harness/tool-gateway/package.json +1 -1
- package/node_modules/@stable-harness/workspace-yaml/dist/boundary-scan.js +1 -1
- package/node_modules/@stable-harness/workspace-yaml/dist/discovery.js +1 -1
- package/node_modules/@stable-harness/workspace-yaml/dist/documents.js +1 -1
- package/node_modules/@stable-harness/workspace-yaml/dist/loader.js +1 -1
- package/node_modules/@stable-harness/workspace-yaml/dist/workflows.js +1 -1
- package/node_modules/@stable-harness/workspace-yaml/package.json +2 -2
- package/package.json +12 -11
- package/packages/adapter-deepagents/dist/src/adapter.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/builtin/task-inventory.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/builtin-call-repair.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/builtin-tool-policy.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/gateway/tool-failure-events.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/raw-tool-call-parser.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/stream-events.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/substrate/checkpoint.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/tool-repeat-visibility.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/trace-projection.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/vfs-backend.js +1 -1
- package/packages/adapter-deepagents/package.json +2 -2
- package/packages/adapter-langgraph/dist/src/graph.js +1 -1
- package/packages/adapter-langgraph/dist/src/index.js +1 -1
- package/packages/adapter-langgraph/dist/src/runtime.js +1 -1
- package/packages/adapter-langgraph/dist/src/skill-providers.js +1 -1
- package/packages/adapter-langgraph/dist/src/types.d.ts +1 -0
- package/packages/adapter-langgraph/package.json +2 -2
- package/packages/cli/dist/src/args.d.ts +3 -2
- package/packages/cli/dist/src/args.js +1 -1
- package/packages/cli/dist/src/build.js +1 -1
- package/packages/cli/dist/src/cli.js +1 -1
- package/packages/cli/dist/src/console/session.js +1 -1
- package/packages/cli/dist/src/daemon/client.d.ts +4 -3
- package/packages/cli/dist/src/daemon/client.js +1 -1
- package/packages/cli/dist/src/init.js +1 -1
- package/packages/cli/dist/src/langgraph/agent-server-compat.d.ts +8 -0
- package/packages/cli/dist/src/langgraph/agent-server-compat.js +1 -0
- package/packages/cli/dist/src/langgraph/store-projection.d.ts +1 -0
- package/packages/cli/dist/src/langgraph/store-projection.js +1 -0
- package/packages/cli/dist/src/langgraph-official.js +1 -1
- package/packages/cli/dist/src/memory/providers.js +1 -1
- package/packages/cli/dist/src/server/gateway.d.ts +12 -0
- package/packages/cli/dist/src/server/gateway.js +1 -0
- package/packages/cli/dist/src/server/protocol-defaults.d.ts +7 -0
- package/packages/cli/dist/src/server/protocol-defaults.js +1 -0
- package/packages/cli/dist/src/server/studio.d.ts +1 -0
- package/packages/cli/dist/src/server/studio.js +1 -0
- package/packages/cli/dist/src/server.js +1 -1
- package/packages/cli/package.json +8 -8
- package/packages/core/dist/boundary-scan.js +1 -1
- package/packages/core/dist/index.d.ts +1 -0
- package/packages/core/dist/index.js +1 -1
- package/packages/core/dist/memory-plugins/shared.js +1 -1
- package/packages/core/dist/memory-plugins.js +1 -1
- package/packages/core/dist/quality/event-evidence.js +1 -1
- package/packages/core/dist/quality/execution-review.js +1 -1
- package/packages/core/dist/quality/synthesis/fields.js +1 -1
- package/packages/core/dist/recovery/execution-contract.js +1 -1
- package/packages/core/dist/recovery/tool-call-structure.js +1 -1
- package/packages/core/dist/recovery/tool-call.js +1 -1
- package/packages/core/dist/runtime/direct-tool-call.js +1 -1
- package/packages/core/dist/runtime/inspection/methods.js +1 -1
- package/packages/core/dist/runtime/inspection/replay.js +1 -1
- package/packages/core/dist/runtime/persistence/artifacts.d.ts +4 -0
- package/packages/core/dist/runtime/persistence/artifacts.js +1 -1
- package/packages/core/dist/runtime/persistence/queue.d.ts +1 -0
- package/packages/core/dist/runtime/persistence/queue.js +1 -1
- package/packages/core/dist/runtime/persistence/stores.d.ts +1 -0
- package/packages/core/dist/runtime/persistence/stores.js +1 -1
- package/packages/core/dist/runtime/persistence/system-data.d.ts +34 -0
- package/packages/core/dist/runtime/persistence/system-data.js +1 -0
- package/packages/core/dist/runtime/recovery/adapter-result.js +1 -1
- package/packages/core/dist/runtime/recovery/non-focused-recovery.js +1 -1
- package/packages/core/dist/runtime.js +1 -1
- package/packages/core/dist/workflows/index.d.ts +20 -0
- package/packages/core/dist/workflows/index.js +1 -1
- package/packages/core/package.json +3 -3
- package/packages/evaluation/dist/src/benchmark.js +1 -1
- package/packages/evaluation/dist/src/run-record.js +1 -1
- package/packages/evaluation/dist/src/tool-call-metrics.js +1 -1
- package/packages/evaluation/package.json +2 -2
- package/packages/governance/dist/src/approval-queue.d.ts +1 -0
- package/packages/governance/dist/src/approval-queue.js +1 -1
- package/packages/governance/dist/src/index.d.ts +1 -1
- package/packages/governance/dist/src/index.js +1 -1
- package/packages/governance/package.json +1 -1
- package/packages/memory/package.json +1 -1
- package/packages/protocols/dist/src/http-events.d.ts +2 -0
- package/packages/protocols/dist/src/http-events.js +1 -1
- package/packages/protocols/dist/src/http-server.d.ts +5 -1
- package/packages/protocols/dist/src/http-server.js +1 -1
- package/packages/protocols/dist/src/index.d.ts +3 -3
- package/packages/protocols/dist/src/index.js +1 -1
- package/packages/protocols/dist/src/openai-compatible.js +1 -1
- package/packages/protocols/dist/src/openai-payload.d.ts +89 -0
- package/packages/protocols/dist/src/openai-payload.js +1 -1
- package/packages/protocols/dist/src/{agent-protocols.d.ts → protocol-facades.d.ts} +4 -10
- package/packages/protocols/dist/src/protocol-facades.js +1 -0
- package/packages/protocols/dist/src/protocol-utils.d.ts +505 -0
- package/packages/protocols/dist/src/protocol-utils.js +1 -0
- package/packages/protocols/package.json +2 -2
- package/packages/tool-gateway/dist/src/argument-guard.js +1 -1
- package/packages/tool-gateway/dist/src/schema-validation.js +1 -1
- package/packages/tool-gateway/package.json +1 -1
- package/packages/workspace-yaml/dist/boundary-scan.js +1 -1
- package/packages/workspace-yaml/dist/discovery.js +1 -1
- package/packages/workspace-yaml/dist/documents.js +1 -1
- package/packages/workspace-yaml/dist/loader.js +1 -1
- package/packages/workspace-yaml/dist/workflows.js +1 -1
- package/packages/workspace-yaml/package.json +2 -2
- package/node_modules/@stable-harness/protocols/dist/src/agent-protocols.js +0 -1
- package/packages/protocols/dist/src/agent-protocols.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createServer as e}from"node:http";import{compileWorkflowPlan as t,projectRuntimeTrace as n,projectRuntimeTraceSpans as r,renderStableHarnessPrometheusMetrics as o,renderWorkflowMermaid as s}from"@stable-harness/core";import{readRuntimeEventFilter as a,streamRuntimeEvents as d}from"./http-events.js";export function createHttpServer(i){return e((e,u)=>{!async function handleHttpRequest(e,i,u){try{await async function routeHttpRequest(e,i,u){(function handleSystemRoutes(e,t,n){return"GET"===t.method&&"/health"===t.url?(sendJson(n,200,{ok:!0}),!0):"GET"===t.method&&"/metrics"===t.url?(function sendText(e,t,n,r="text/plain; charset=utf-8"){e.writeHead(t,{"content-type":r}),e.end(n)}(n,200,o({runtime:e}),"text/plain; version=0.0.4; charset=utf-8"),!0):"GET"===t.method&&"/inspect"===t.url&&(sendJson(n,200,e.inspect()),!0)})(e,i,u)||function handleEventRoutes(e,t,n){const r=a(t.url);return!("GET"!==t.method||!r||(d({runtime:e,request:t,response:n,filter:r}),0))}(e,i,u)||await async function handleAdministrationRoutes(e){const{runtime:t,request:n,response:r}=e;if("GET"===n.method&&"/sessions"===n.url)return sendJson(r,200,t.listSessions()),!0;const o=function readSessionDeleteId(e){const t=(e??"").match(/^\/sessions\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(n.url);if("DELETE"===n.method&&o)return sendJson(r,200,t.deleteSession(o)),!0;const s=function readRequestDeleteId(e){const t=(e??"").match(/^\/requests\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(n.url);if("DELETE"===n.method&&s)return sendJson(r,200,t.deleteRequest(s)),!0;if("GET"===n.method&&n.url?.startsWith("/memories"))return sendJson(r,200,await t.listMemories(function readMemoryList(e){const t=new URL(e??"/memories","http://stable-harness.local"),n=t.searchParams.getAll("status").filter(e=>"active"===e||"stale"===e||"conflicted"===e||"archived"===e||"pending_review"===e);return{...t.searchParams.get("namespace")?{namespace:t.searchParams.get("namespace")}:{},...n.length>0?{statuses:n}:{}}}(n.url))),!0;if("POST"===n.method&&"/memories"===n.url){const e=await readJson(n);return sendJson(r,200,await t.memorize(e)),!0}if("POST"===n.method&&"/memories/recall"===n.url){const e=await readJson(n);return sendJson(r,200,await t.recallMemories(e)),!0}const a=function readMemoryArchiveId(e){const t=(e??"").match(/^\/memories\/([^/]+)\/archive$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(n.url);if("POST"===n.method&&a){const e=await readJson(n);return sendJson(r,200,await t.archiveMemory(a,"string"==typeof e.reason?e.reason:void 0)),!0}const d=function readMemoryUpdateId(e){const t=(e??"").match(/^\/memories\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(n.url);return!("PATCH"!==n.method||!d||(sendJson(r,200,await t.updateMemory({id:d,...await readJson(n)})),0))}({runtime:e,request:i,response:u})||await async function handleArtifactRoutes(e,t,n){const r=function readArtifactList(e){if(!e?.startsWith("/artifacts"))return;const t=new URL(e,"http://stable-harness.local");return"/artifacts"===t.pathname?{...t.searchParams.get("requestId")?{requestId:t.searchParams.get("requestId")}:{},...t.searchParams.get("sessionId")?{sessionId:t.searchParams.get("sessionId")}:{},...t.searchParams.get("agentId")?{agentId:t.searchParams.get("agentId")}:{}}:void 0}(t.url);if("POST"===t.method&&r){const r=function readArtifactImport(e){const t=readRecord(e.metadata);return{id:"string"==typeof e.id?e.id:"",kind:"string"==typeof e.kind?e.kind:"artifact",requestId:"string"==typeof e.requestId?e.requestId:"",..."string"==typeof e.sessionId?{sessionId:e.sessionId}:{},..."string"==typeof e.agentId?{agentId:e.agentId}:{},..."string"==typeof e.uri?{uri:e.uri}:{},...t?{metadata:t}:{},...void 0!==e.content?{content:e.content}:{},..."string"==typeof e.contentType?{contentType:e.contentType}:{},..."string"==typeof e.createdAt?{createdAt:e.createdAt}:{}}}(await readJson(t)),o=function validateArtifactImport(e){const t=[];return hasText(e.id)||t.push("id is required"),hasText(e.kind)||t.push("kind is required"),hasText(e.requestId)||t.push("requestId is required"),t}(r);if(o.length>0)return sendJson(n,400,{error:"artifact_import_invalid",issues:o}),!0;const s=e.importArtifact(r);return sendJson(n,s?201:404,s??{error:"artifact_import_target_not_found"}),!0}if("GET"===t.method&&r)return sendJson(n,200,e.listArtifacts(r)),!0;const o=function readArtifactContentId(e){const t=(e??"").match(/^\/artifacts\/([^/]+)\/content$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(t.url);if("GET"===t.method&&o){const t=e.getArtifact(o),r=e.readArtifact(o);return sendJson(n,t&&void 0!==r?200:404,t&&void 0!==r?{artifact:t,content:r}:{error:"artifact_content_not_found"}),!0}const s=function readArtifactId(e){const t=(e??"").match(/^\/artifacts\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(t.url);if("GET"===t.method&&s){const t=e.getArtifact(s);return sendJson(n,t?200:404,t??{error:"artifact_not_found"}),!0}return!1}(e,i,u)||await async function handleApprovalRoutes(e,t,n){const r=function readApprovalList(e){if(!e?.startsWith("/approvals"))return;const t=new URL(e,"http://stable-harness.local");if("/approvals"!==t.pathname)return;const n=t.searchParams.get("status");return{status:"pending"===n||"approved"===n||"rejected"===n?n:void 0}}(t.url);if("GET"===t.method&&r)return sendJson(n,200,await e.listApprovals(r.status)),!0;const o=function readApprovalDecision(e){const t=(e??"").match(/^\/approvals\/([^/]+)\/(approve|reject)$/u);if(t?.[1]&&t[2])return{id:decodeURIComponent(t[1]),status:"approve"===t[2]?"approved":"rejected"}}(t.url);if("POST"===t.method&&o){const t=await e.resolveApproval(o.id,o.status);return sendJson(n,t?200:404,t??{error:"approval_not_found"}),!0}return!1}(e,i,u)||await async function handleRequestRoutes(e,t,n){if("GET"===t.method&&"/requests"===t.url)return sendJson(n,200,e.listRequests()),!0;const r=function readRequestList(e){if(!e?.startsWith("/requests"))return;const t=new URL(e,"http://stable-harness.local");return"/requests"===t.pathname?{...t.searchParams.get("agentId")?{agentId:t.searchParams.get("agentId")}:{},...t.searchParams.get("sessionId")?{sessionId:t.searchParams.get("sessionId")}:{},...readRunState(t.searchParams.get("state"))?{state:readRunState(t.searchParams.get("state"))}:{}}:void 0}(t.url);if("GET"===t.method&&r)return sendJson(n,200,e.listRequests(r)),!0;const o=function readRequestCancelId(e){const t=(e??"").match(/^\/requests\/([^/]+)\/cancel$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(t.url);if("POST"===t.method&&o){const r=await readJson(t);return e.cancel(o,"string"==typeof r.reason?r.reason:void 0),sendJson(n,200,e.inspectRequest(o)??{error:"request_not_found"}),!0}if("POST"===t.method&&"/requests"===t.url){const r=await readJson(t);return sendJson(n,200,await e.request(function readRuntimeRequest(e){const t=function readToolCall(e){if("object"!=typeof e||null===e)return;const t=e;return"string"==typeof t.toolId?{toolId:t.toolId,args:t.args}:void 0}(e.toolCall),n=function readWorkflow(e){const t=readRecord(e);if(t)return{..."string"==typeof t.workflowId?{workflowId:t.workflowId}:{},..."string"==typeof t.routeId?{routeId:t.routeId}:{},...void 0!==t.input?{input:t.input}:{},..."object"==typeof t.metadata&&t.metadata?{metadata:t.metadata}:{}}}(e.workflow),r=function readMemory(e){const t=readRecord(e);if(t)return{..."string"==typeof t.namespace?{namespace:t.namespace}:{},...!1===t.recall||readRecord(t.recall)?{recall:t.recall}:{},...Array.isArray(t.candidates)?{candidates:t.candidates}:{}}}(e.memory),o=readRecord(e.metadata);return{input:"string"==typeof e.input?e.input:"",..."string"==typeof e.agentId?{agentId:e.agentId}:{},..."string"==typeof e.sessionId?{sessionId:e.sessionId}:{},..."string"==typeof e.requestId?{requestId:e.requestId}:{},..."string"==typeof e.parentRunId?{parentRunId:e.parentRunId}:{},...t?{toolCall:t}:{},...n?{workflow:n}:{},...r?{memory:r}:{},...o?{metadata:o}:{}}}(r))),!0}return!1}(e,i,u)||function handleWorkflowRoutes(e,n,r){if("GET"===n.method&&"/workflows"===n.url)return sendJson(r,200,e.inspect().workflows),!0;const o=function readWorkflowMermaidId(e){const t=(e??"").match(/^\/workflows\/([^/]+)\/mermaid$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(n.url);if("GET"===n.method&&o){const t=e.getWorkflow(o);return sendJson(r,t?200:404,t?{mermaid:s(t)}:{error:"workflow_not_found"}),!0}const a=function readWorkflowPlanId(e){const t=(e??"").match(/^\/workflows\/([^/]+)\/plan$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(n.url);if("GET"===n.method&&a){const n=e.getWorkflow(a);return sendJson(r,n?200:404,n?t(n):{error:"workflow_not_found"}),!0}return!1}(e,i,u)||function handleRunInspectionRoutes(e,t,o){const s=function readRequestInspectionId(e){const t=(e??"").match(/^\/requests\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(t.url);if("GET"===t.method&&s){const t=e.inspectRequest(s);return sendJson(o,t?200:404,t??{error:"request_not_found"}),!0}const a=function readTraceRequestId(e){const t=(e??"").match(/^\/runs\/([^/]+)\/trace$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(t.url);if("GET"===t.method&&a){const t=e.getRun(a);return sendJson(o,t?200:404,t?n(t):{error:"run_not_found"}),!0}const d=function readSpanRequestId(e){const t=(e??"").match(/^\/runs\/([^/]+)\/spans$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(t.url);if("GET"===t.method&&d){const t=e.getRun(d);return sendJson(o,t?200:404,t?r(t):{error:"run_not_found"}),!0}const i=function readReplayRequestId(e){const t=(e??"").match(/^\/requests\/([^/]+)\/replay$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(t.url);if("GET"===t.method&&i){const t=e.exportReplayBundle(i);return sendJson(o,t?200:404,t??{error:"run_not_found"}),!0}return!1}(e,i,u)||sendJson(u,404,{error:"not_found"})}(e,i,u)}catch(e){sendJson(u,500,{error:e instanceof Error?e.message:String(e)})}}(i,e,u)})}function readRunState(e){return"queued"===e||"running"===e||"completed"===e||"failed"===e||"cancelled"===e?e:void 0}function hasText(e){return"string"==typeof e&&e.trim().length>0}function readRecord(e){return"object"!=typeof e||null===e||Array.isArray(e)?void 0:e}function sendJson(e,t,n){e.writeHead(t,{"content-type":"application/json"}),e.end(JSON.stringify(n))}async function readJson(e){const t=[];for await(const n of e)t.push(Buffer.isBuffer(n)?n:Buffer.from(n));return 0===t.length?{}:JSON.parse(Buffer.concat(t).toString("utf8"))}
|
|
1
|
+
import{createServer as t}from"node:http";import{compileWorkflowPlan as e,projectRuntimeTrace as r,projectRuntimeTraceSpans as n,renderStableHarnessPrometheusMetrics as o,renderWorkflowMermaid as s}from"@stable-harness/core";import{readRunScopedEventFilter as a,readRuntimeEventFilter as i,streamRuntimeEvents as u}from"./http-events.js";import{readJson as d,sendJson as c}from"./protocol-utils.js";export function createHttpServer(e,r={}){return t((t,n)=>{!function isAuthorized(t,e){return!e.bearerToken||t.headers.authorization===`Bearer ${e.bearerToken}`}(t,r)?c(n,401,{error:"unauthorized"}):handleStableRuntimeHttpRequest(e,t,n)})}export async function handleStableRuntimeHttpRequest(t,f,l){try{await async function routeHttpRequest(t,f,l){(function handleSystemRoutes(t,e,r){return"GET"===e.method&&"/health"===e.url?(c(r,200,{ok:!0}),!0):"GET"===e.method&&"/metrics"===e.url?(function sendText(t,e,r,n="text/plain; charset=utf-8"){t.writeHead(e,{"content-type":n}),t.end(r)}(r,200,o({runtime:t}),"text/plain; version=0.0.4; charset=utf-8"),!0):"GET"===e.method&&"/inspect"===e.url&&(c(r,200,t.inspect()),!0)})(t,f,l)||function handleEventRoutes(t,e,r){const n=a(e.url)??i(e.url);return!("GET"!==e.method||!n)&&(u({runtime:t,request:e,response:r,filter:n}),!0)}(t,f,l)||await async function handleAdministrationRoutes(t){const{runtime:e,request:r,response:n}=t;if("GET"===r.method&&"/sessions"===r.url)return c(n,200,e.listSessions()),!0;const o=function readSessionDeleteId(t){const e=(t??"").match(/^\/sessions\/([^/]+)$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(r.url);if("DELETE"===r.method&&o)return c(n,200,e.deleteSession(o)),!0;const s=function readRequestDeleteId(t){const e=(t??"").match(/^\/(?:requests|runs)\/([^/]+)$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(r.url);if("DELETE"===r.method&&s)return c(n,200,e.deleteRequest(s)),!0;if("GET"===r.method&&r.url?.startsWith("/memories"))return c(n,200,await e.listMemories(function readMemoryList(t){const e=new URL(t??"/memories","http://stable-harness.local"),r=e.searchParams.getAll("status").filter(t=>"active"===t||"stale"===t||"conflicted"===t||"archived"===t||"pending_review"===t);return{...e.searchParams.get("namespace")?{namespace:e.searchParams.get("namespace")}:{},...r.length>0?{statuses:r}:{}}}(r.url))),!0;if("POST"===r.method&&"/memories"===r.url){const t=await d(r);return c(n,200,await e.memorize(t)),!0}if("POST"===r.method&&"/memories/recall"===r.url){const t=await d(r);return c(n,200,await e.recallMemories(t)),!0}const a=function readMemoryArchiveId(t){const e=(t??"").match(/^\/memories\/([^/]+)\/archive$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(r.url);if("POST"===r.method&&a){const t=await d(r);return c(n,200,await e.archiveMemory(a,"string"==typeof t.reason?t.reason:void 0)),!0}const i=function readMemoryUpdateId(t){const e=(t??"").match(/^\/memories\/([^/]+)$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(r.url);return!("PATCH"!==r.method||!i)&&(c(n,200,await e.updateMemory({id:i,...await d(r)})),!0)}({runtime:t,request:f,response:l})||await async function handleArtifactRoutes(t,e,r){const n=function readArtifactList(t){if(!t?.startsWith("/artifacts"))return;const e=new URL(t,"http://stable-harness.local");return"/artifacts"===e.pathname?{...e.searchParams.get("requestId")?{requestId:e.searchParams.get("requestId")}:{},...e.searchParams.get("sessionId")?{sessionId:e.searchParams.get("sessionId")}:{},...e.searchParams.get("agentId")?{agentId:e.searchParams.get("agentId")}:{}}:void 0}(e.url);if("POST"===e.method&&n){const n=function readArtifactImport(t){const e=readRecord(t.metadata);return{id:"string"==typeof t.id?t.id:"",kind:"string"==typeof t.kind?t.kind:"artifact",requestId:"string"==typeof t.requestId?t.requestId:"",..."string"==typeof t.sessionId?{sessionId:t.sessionId}:{},..."string"==typeof t.agentId?{agentId:t.agentId}:{},..."string"==typeof t.uri?{uri:t.uri}:{},...e?{metadata:e}:{},...void 0!==t.content?{content:t.content}:{},..."string"==typeof t.contentType?{contentType:t.contentType}:{},..."string"==typeof t.createdAt?{createdAt:t.createdAt}:{}}}(await d(e)),o=function validateArtifactImport(t){const e=[];return hasText(t.id)||e.push("id is required"),hasText(t.kind)||e.push("kind is required"),hasText(t.requestId)||e.push("requestId is required"),e}(n);if(o.length>0)return c(r,400,{error:"artifact_import_invalid",issues:o}),!0;const s=t.importArtifact(n);return c(r,s?201:404,s??{error:"artifact_import_target_not_found"}),!0}if("GET"===e.method&&n)return c(r,200,t.listArtifacts(n)),!0;const o=function readArtifactContentId(t){const e=(t??"").match(/^\/artifacts\/([^/]+)\/content$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(e.url);if("GET"===e.method&&o){const e=t.getArtifact(o),n=t.readArtifact(o);return c(r,e&&void 0!==n?200:404,e&&void 0!==n?{artifact:e,content:n}:{error:"artifact_content_not_found"}),!0}const s=function readArtifactId(t){const e=(t??"").match(/^\/artifacts\/([^/]+)$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(e.url);if("GET"===e.method&&s){const e=t.getArtifact(s);return c(r,e?200:404,e??{error:"artifact_not_found"}),!0}return!1}(t,f,l)||await async function handleApprovalRoutes(t,e,r){const n=function readApprovalList(t){if(!t?.startsWith("/approvals"))return;const e=new URL(t,"http://stable-harness.local");if("/approvals"!==e.pathname)return;const r=e.searchParams.get("status");return{status:"pending"===r||"approved"===r||"rejected"===r?r:void 0}}(e.url);if("GET"===e.method&&n)return c(r,200,await t.listApprovals(n.status)),!0;const o=function readApprovalDecision(t){const e=(t??"").match(/^\/approvals\/([^/]+)\/(approve|reject)$/u);if(e?.[1]&&e[2])return{id:decodeURIComponent(e[1]),status:"approve"===e[2]?"approved":"rejected"}}(e.url);if("POST"===e.method&&o){const e=await t.resolveApproval(o.id,o.status);return c(r,e?200:404,e??{error:"approval_not_found"}),!0}return!1}(t,f,l)||await async function handleRequestRoutes(t,e,r){if("GET"===e.method&&("/requests"===e.url||"/runs"===e.url))return c(r,200,t.listRequests()),!0;const n=function readRequestList(t){if(!t||!t.startsWith("/requests")&&!t.startsWith("/runs"))return;const e=new URL(t,"http://stable-harness.local");return"/requests"===e.pathname||"/runs"===e.pathname?{...e.searchParams.get("agentId")?{agentId:e.searchParams.get("agentId")}:{},...e.searchParams.get("sessionId")?{sessionId:e.searchParams.get("sessionId")}:{},...readRunState(e.searchParams.get("state"))?{state:readRunState(e.searchParams.get("state"))}:{}}:void 0}(e.url);if("GET"===e.method&&n)return c(r,200,t.listRequests(n)),!0;const o=function readRequestCancelId(t){const e=(t??"").match(/^\/(?:requests|runs)\/([^/]+)\/cancel$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(e.url);if("POST"===e.method&&o){const n=await d(e);return t.cancel(o,"string"==typeof n.reason?n.reason:void 0),c(r,200,t.inspectRequest(o)??{error:"request_not_found"}),!0}if("POST"===e.method&&("/requests"===e.url||"/runs"===e.url)){const n=await d(e);return c(r,200,await t.request(function readRuntimeRequest(t){const e=function readToolCall(t){if("object"!=typeof t||null===t)return;const e=t;return"string"==typeof e.toolId?{toolId:e.toolId,args:e.args}:void 0}(t.toolCall),r=function readWorkflow(t){const e=readRecord(t);if(e)return{..."string"==typeof e.workflowId?{workflowId:e.workflowId}:{},..."string"==typeof e.routeId?{routeId:e.routeId}:{},...void 0!==e.input?{input:e.input}:{},..."object"==typeof e.metadata&&e.metadata?{metadata:e.metadata}:{}}}(t.workflow),n=function readMemory(t){const e=readRecord(t);if(e)return{..."string"==typeof e.namespace?{namespace:e.namespace}:{},...!1===e.recall||readRecord(e.recall)?{recall:e.recall}:{},...Array.isArray(e.candidates)?{candidates:e.candidates}:{}}}(t.memory),o=readRecord(t.metadata);return{input:"string"==typeof t.input?t.input:"",..."string"==typeof t.agentId?{agentId:t.agentId}:{},..."string"==typeof t.sessionId?{sessionId:t.sessionId}:{},..."string"==typeof t.requestId?{requestId:t.requestId}:{},..."string"==typeof t.parentRunId?{parentRunId:t.parentRunId}:{},...e?{toolCall:e}:{},...r?{workflow:r}:{},...n?{memory:n}:{},...o?{metadata:o}:{}}}(n))),!0}return!1}(t,f,l)||function handleWorkflowRoutes(t,r,n){if("GET"===r.method&&"/workflows"===r.url)return c(n,200,t.inspect().workflows),!0;const o=function readWorkflowMermaidId(t){const e=(t??"").match(/^\/workflows\/([^/]+)\/mermaid$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(r.url);if("GET"===r.method&&o){const e=t.getWorkflow(o);return c(n,e?200:404,e?{mermaid:s(e)}:{error:"workflow_not_found"}),!0}const a=function readWorkflowPlanId(t){const e=(t??"").match(/^\/workflows\/([^/]+)\/plan$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(r.url);if("GET"===r.method&&a){const r=t.getWorkflow(a);return c(n,r?200:404,r?e(r):{error:"workflow_not_found"}),!0}return!1}(t,f,l)||function handleRunInspectionRoutes(t,e,o){const s=function readRequestInspectionId(t){const e=(t??"").match(/^\/(?:requests|runs)\/([^/]+)$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(e.url);if("GET"===e.method&&s){const e=t.inspectRequest(s);return c(o,e?200:404,e??{error:"request_not_found"}),!0}const a=function readTraceRequestId(t){const e=(t??"").match(/^\/runs\/([^/]+)\/trace$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(e.url);if("GET"===e.method&&a){const e=t.getRun(a);return c(o,e?200:404,e?r(e):{error:"run_not_found"}),!0}const i=function readSpanRequestId(t){const e=(t??"").match(/^\/runs\/([^/]+)\/spans$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(e.url);if("GET"===e.method&&i){const e=t.getRun(i);return c(o,e?200:404,e?n(e):{error:"run_not_found"}),!0}const u=function readReplayRequestId(t){const e=(t??"").match(/^\/(?:requests|runs)\/([^/]+)\/replay$/u);return e?.[1]?decodeURIComponent(e[1]):void 0}(e.url);if("GET"===e.method&&u){const e=t.exportReplayBundle(u);return c(o,e?200:404,e??{error:"run_not_found"}),!0}return!1}(t,f,l)||c(l,404,{error:"not_found"})}(t,f,l)}catch(t){const e=t instanceof Error?t.message:String(t);c(l,500,{error:e})}}function readRunState(t){return"queued"===t||"running"===t||"completed"===t||"failed"===t||"cancelled"===t?t:void 0}function hasText(t){return"string"==typeof t&&t.trim().length>0}function readRecord(t){return"object"!=typeof t||null===t||Array.isArray(t)?void 0:t}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createInProcessClient } from "./in-process-client.js";
|
|
2
|
-
export { createAgentProtocolHttpServer, handleAcpJsonRpcMessage } from "./
|
|
3
|
-
export type { AgentProtocolServerOptions } from "./
|
|
4
|
-
export { createHttpServer } from "./http-server.js";
|
|
2
|
+
export { createAgentProtocolHttpServer, handleAcpJsonRpcMessage } from "./protocol-facades.js";
|
|
3
|
+
export type { AgentProtocolServerOptions } from "./protocol-facades.js";
|
|
4
|
+
export { createHttpServer, handleStableRuntimeHttpRequest } from "./http-server.js";
|
|
5
5
|
export { createOpenAiCompatibleHttpServer } from "./openai-compatible.js";
|
|
6
6
|
export type { OpenAiCompatibleServerOptions } from "./openai-compatible.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{createInProcessClient}from"./in-process-client.js";export{createAgentProtocolHttpServer,handleAcpJsonRpcMessage}from"./
|
|
1
|
+
export{createInProcessClient}from"./in-process-client.js";export{createAgentProtocolHttpServer,handleAcpJsonRpcMessage}from"./protocol-facades.js";export{createHttpServer,handleStableRuntimeHttpRequest}from"./http-server.js";export{createOpenAiCompatibleHttpServer}from"./openai-compatible.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createServer as e}from"node:http";import{projectRuntimeTrace as r,renderStableHarnessPrometheusMetrics as
|
|
1
|
+
import{createServer as e}from"node:http";import{projectRuntimeTrace as r,projectRuntimeTraceSpans as t,renderStableHarnessPrometheusMetrics as n}from"@stable-harness/core";import{createCapabilitiesResponse as o,createModelsResponse as s,resolveAgentId as a,toChatCompletion as i,toResponsesObject as d,toResponsesRuntimeRequest as c,toRuntimeErrorResponse as u,toStoredResponsesObject as l,toRuntimeRequest as p}from"./openai-payload.js";import{createContentChunk as f,createRoleChunk as m,createStopChunk as v,missingFinalDelta as h,writeChatSse as y,writeErrorSse as g,writeRuntimeStreamEvent as w,writeSseHeaders as O}from"./openai-stream.js";import{readRunScopedEventFilter as _,streamRuntimeEvents as S}from"./http-events.js";export function createOpenAiCompatibleHttpServer(R,T={}){const E=function resolveServerOptions(e,r){const t=function readOpenAiProtocolConfig(e){const r=readRecord(e)??{};return readRecord(r.openaiCompatible)??readRecord(r["openai-compatible"])??readRecord(r.openai)??{}}(e.getRuntimePolicy().protocols);return{bearerToken:r.bearerToken??readConfigString(t.bearerToken),corsOrigins:r.corsOrigins??(n=t.corsOrigins,Array.isArray(n)?n.filter(e=>"string"==typeof e&&e.trim().length>0):void 0),modelAgentMap:r.modelAgentMap??readStringRecord(t.modelAgentMap),defaultModel:r.defaultModel??readConfigString(t.defaultModel)};var n}(R,T);return e(async(e,T)=>{try{if(function applyCorsHeaders(e,r,t){const n=function allowedCorsOrigin(e,r){if(e)return r.corsOrigins?.includes("*")?"*":r.corsOrigins?.includes(e)||function isLoopbackOrigin(e){try{const r=new URL(e);return"http:"===r.protocol&&["localhost","127.0.0.1","[::1]"].includes(r.hostname)}catch{return!1}}(e)?e:void 0}(e.headers.origin,t);n&&(r.setHeader("access-control-allow-origin",n),r.setHeader("vary","origin"))}(e,T,E),function handleCors(e,r){return"OPTIONS"===e.method&&(r.writeHead(204,{"access-control-allow-headers":"authorization, content-type, idempotency-key","access-control-allow-methods":"GET, POST, OPTIONS"}),r.end(),!0)}(e,T))return;if(!function isAuthorized(e,r){return!r.bearerToken||e.headers.authorization===`Bearer ${r.bearerToken}`}(e,E))return void sendJson(T,401,{error:{message:"unauthorized",type:"invalid_request_error"}});if("GET"===e.method&&"/v1/models"===e.url)return void sendJson(T,200,s(R,E));if("GET"===e.method&&"/v1/capabilities"===e.url)return void sendJson(T,200,o());if("GET"===e.method&&"/v1/stable-harness/inspect"===e.url)return void sendJson(T,200,R.inspect());if("GET"===e.method&&"/metrics"===e.url)return void function sendText(e,r,t,n){e.writeHead(r,{"content-type":n,"access-control-allow-headers":"authorization, content-type, idempotency-key","access-control-allow-methods":"GET, POST, OPTIONS"}),e.end(t)}(T,200,n({runtime:R}),"text/plain; version=0.0.4; charset=utf-8");if(function handleStableHarnessRunInspection(e,n,o){const s=function readStableHarnessRunInspection(e){const r=new URL(e??"/","http://stable-harness.local"),t=r.pathname.match(/^\/v1\/stable-harness\/runs\/([^/]+)\/(trace|spans|replay|events)$/u);if(t?.[1]&&t[2]){if("events"===t[2]){const e=_(`/runs/${t[1]}/events${r.search}`);return e?{kind:"events",filter:e}:void 0}return"trace"===t[2]||"spans"===t[2]||"replay"===t[2]?{kind:t[2],requestId:decodeURIComponent(t[1])}:void 0}}(n.url);if("GET"!==n.method||!s)return!1;if("events"===s.kind)return S({runtime:e,request:n,response:o,filter:s.filter,headers:{"access-control-allow-headers":"authorization, content-type, idempotency-key","access-control-allow-methods":"GET, POST, OPTIONS"}}),!0;const a=e.getRun(s.requestId);if("trace"===s.kind)return sendJson(o,a?200:404,a?r(a):{error:{message:"run_not_found",type:"invalid_request_error"}}),!0;if("spans"===s.kind)return sendJson(o,a?200:404,a?t(a):{error:{message:"run_not_found",type:"invalid_request_error"}}),!0;const i=e.exportReplayBundle(s.requestId);return sendJson(o,i?200:404,i??{error:{message:"run_not_found",type:"invalid_request_error"}}),!0}(R,e,T))return;const q=function readApprovalList(e){if(!e?.startsWith("/v1/approvals"))return;const r=new URL(e,"http://stable-harness.local");if("/v1/approvals"!==r.pathname)return;const t=r.searchParams.get("status");return{status:"pending"===t||"approved"===t||"rejected"===t?t:void 0}}(e.url);if("GET"===e.method&&q)return void sendJson(T,200,{data:await R.listApprovals(q.status)});const J=function readApprovalDecision(e){const r=(e??"").match(/^\/v1\/approvals\/([^/]+)\/(approve|reject)$/u);if(r?.[1]&&r[2])return{id:decodeURIComponent(r[1]),status:"approve"===r[2]?"approved":"rejected"}}(e.url);if("POST"===e.method&&J){const e=await R.resolveApproval(J.id,J.status);return void sendJson(T,e?200:404,e?{data:e}:{error:{message:"approval_not_found",type:"invalid_request_error"}})}if("POST"===e.method&&"/v1/chat/completions"===e.url)return void await async function handleChatCompletion(e,r,t,n){const o=await readJson(r);if(o.model&&!a(o.model,e,n))return void sendJson(t,404,{error:{message:`model_not_found: ${o.model}`,type:"invalid_request_error"}});const s=p(o,e,n,{sessionId:readHeaderString(r.headers["x-stable-harness-session-id"])});if(o.stream)return void await async function streamChatCompletion(e,r,t,n){O(r,{"access-control-allow-headers":"authorization, content-type, idempotency-key","access-control-allow-methods":"GET, POST, OPTIONS"}),y(r,m(n.requestId,t.model));let o="";const s=e.subscribe(e=>{e.requestId===n.requestId&&(o+=w(r,e,n.requestId,t.model)??"")});try{const s=await e.request(n);if(isRuntimeError(s))return g(r,u(s)),r.write("data: [DONE]\n\n"),void r.end();const a=h(o,s.output);a&&y(r,f(n.requestId,t.model,a)),y(r,v(n.requestId,t.model)),r.write("data: [DONE]\n\n"),r.end()}finally{s()}}(e,t,o,s);const d=await e.request(s);isRuntimeError(d)?sendJson(t,runtimeErrorStatus(d),u(d)):sendJson(t,200,i(o,d))}(R,e,T,E);if("POST"===e.method&&"/v1/responses"===e.url)return void await async function handleResponsesCreate(e,r,t,n){const o=await readJson(r);if(o.model&&!a(o.model,e,n))return void sendJson(t,404,{error:{message:`model_not_found: ${o.model}`,type:"invalid_request_error"}});const s=c(o,e,n);if(o.stream)return void await async function streamResponses(e,r,t,n){O(r,{"access-control-allow-headers":"authorization, content-type, idempotency-key","access-control-allow-methods":"GET, POST, OPTIONS"}),writeResponseSse(r,"response.created",{type:"response.created",response:{id:n.requestId,status:"in_progress"}});try{const o=await e.request(n);if(isRuntimeError(o))return writeResponseSse(r,"error",u(o)),r.write("data: [DONE]\n\n"),void r.end();writeResponseSse(r,"response.output_text.delta",{type:"response.output_text.delta",delta:o.output,item_id:`${o.requestId}-message`}),writeResponseSse(r,"response.completed",{type:"response.completed",response:d(t,o)}),r.write("data: [DONE]\n\n"),r.end()}catch(e){writeResponseSse(r,"error",{error:{message:e instanceof Error?e.message:String(e),type:"server_error"}}),r.write("data: [DONE]\n\n"),r.end()}}(e,t,o,s);const i=await e.request(s);isRuntimeError(i)?sendJson(t,runtimeErrorStatus(i),u(i)):sendJson(t,200,d(o,i))}(R,e,T,E);const I=function readResponsesRequest(e){const r=(e??"").match(/^\/v1\/responses\/([^/]+)\/cancel$/u);if(r?.[1])return{id:decodeURIComponent(r[1]),action:"cancel"};const t=(e??"").match(/^\/v1\/responses\/([^/]+)$/u);return t?.[1]?{id:decodeURIComponent(t[1]),action:"retrieve"}:void 0}(e.url);if(I)return void function handleResponsesLifecycle(e,r,t,n,o){if("DELETE"===r.method)return void sendJson(t,200,{id:n,object:"response",deleted:e.deleteRequest(n).deletedCount>0});"cancel"===o&&"POST"===r.method&&e.cancel(n,"openai_responses_cancel");const s=e.inspectRequest(n);sendJson(t,s?200:404,s?l(n,s):{error:{message:"response_not_found",type:"invalid_request_error"}})}(R,e,T,I.id,I.action);sendJson(T,404,{error:{message:"not_found",type:"invalid_request_error"}})}catch(e){sendJson(T,400,{error:{message:e instanceof Error?e.message:String(e),type:"invalid_request_error"}})}})}function writeResponseSse(e,r,t){e.write(`event: ${r}\n`),e.write(`data: ${JSON.stringify(t)}\n\n`)}function isRuntimeError(e){return"failed"===e.state||"cancelled"===e.state}function runtimeErrorStatus(e){return"cancelled"===e.state?409:500}function readRecord(e){return"object"!=typeof e||null===e||Array.isArray(e)?void 0:e}function readStringRecord(e){const r=readRecord(e);if(r)return Object.fromEntries(Object.entries(r).filter(e=>"string"==typeof e[1]))}function readConfigString(e){if("string"!=typeof e||!e.trim())return;const r=e.match(/^\$\{env:([A-Za-z_][A-Za-z0-9_]*)(?::-(.*))?\}$/u);return r?process.env[r[1]]??r[2]:e}function readHeaderString(e){const r=Array.isArray(e)?e[0]:e;return r&&r.trim()?r:void 0}function sendJson(e,r,t,n){e.writeHead(r,{"content-type":"application/json","access-control-allow-headers":"authorization, content-type, idempotency-key","access-control-allow-methods":"GET, POST, OPTIONS"}),e.end(JSON.stringify(t))}async function readJson(e){const r=[];for await(const t of e)r.push(Buffer.isBuffer(t)?t:Buffer.from(t));return 0===r.length?{}:JSON.parse(Buffer.concat(r).toString("utf8"))}
|
|
@@ -11,6 +11,17 @@ export type ChatCompletionRequest = {
|
|
|
11
11
|
user?: string;
|
|
12
12
|
metadata?: Record<string, unknown>;
|
|
13
13
|
};
|
|
14
|
+
export type ResponsesRequest = {
|
|
15
|
+
model?: string;
|
|
16
|
+
input?: unknown;
|
|
17
|
+
instructions?: string;
|
|
18
|
+
stream?: boolean;
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
previous_response_id?: string;
|
|
21
|
+
conversation?: string | {
|
|
22
|
+
id?: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
14
25
|
export type ChatProtocolContext = {
|
|
15
26
|
sessionId?: string;
|
|
16
27
|
};
|
|
@@ -32,6 +43,22 @@ export declare function toRuntimeRequest(body: ChatCompletionRequest, runtime: S
|
|
|
32
43
|
requestId: string;
|
|
33
44
|
agentId: string | undefined;
|
|
34
45
|
};
|
|
46
|
+
export declare function toResponsesRuntimeRequest(body: ResponsesRequest, runtime: StableHarnessRuntime, options: OpenAiCompatibleServerOptions): {
|
|
47
|
+
metadata: {
|
|
48
|
+
protocol: string;
|
|
49
|
+
openaiStream: boolean;
|
|
50
|
+
previousResponseId: string | undefined;
|
|
51
|
+
conversation: string | {
|
|
52
|
+
id?: string;
|
|
53
|
+
} | undefined;
|
|
54
|
+
model: string | undefined;
|
|
55
|
+
clientMetadata: Record<string, unknown> | undefined;
|
|
56
|
+
};
|
|
57
|
+
sessionId?: string | undefined;
|
|
58
|
+
input: string;
|
|
59
|
+
requestId: string;
|
|
60
|
+
agentId: string | undefined;
|
|
61
|
+
};
|
|
35
62
|
export declare function resolveAgentId(model: string | undefined, runtime: StableHarnessRuntime, options: OpenAiCompatibleServerOptions): string | undefined;
|
|
36
63
|
export declare function createModelsResponse(runtime: StableHarnessRuntime, options: OpenAiCompatibleServerOptions): {
|
|
37
64
|
object: string;
|
|
@@ -48,6 +75,20 @@ export declare function createCapabilitiesResponse(): {
|
|
|
48
75
|
streaming: boolean;
|
|
49
76
|
toolProgressEvents: boolean;
|
|
50
77
|
runtimeTrace: boolean;
|
|
78
|
+
runtimeSpans: boolean;
|
|
79
|
+
runtimeReplay: boolean;
|
|
80
|
+
runtimeEvents: {
|
|
81
|
+
replay: boolean;
|
|
82
|
+
filters: string[];
|
|
83
|
+
};
|
|
84
|
+
responsesApi: {
|
|
85
|
+
create: boolean;
|
|
86
|
+
retrieve: boolean;
|
|
87
|
+
delete: boolean;
|
|
88
|
+
cancel: boolean;
|
|
89
|
+
stream: boolean;
|
|
90
|
+
};
|
|
91
|
+
stableHarnessExtensions: string[];
|
|
51
92
|
};
|
|
52
93
|
export declare function toChatCompletion(body: ChatCompletionRequest, result: RuntimeResponse): {
|
|
53
94
|
id: string;
|
|
@@ -73,6 +114,54 @@ export declare function toChatCompletion(body: ChatCompletionRequest, result: Ru
|
|
|
73
114
|
state: import("@stable-harness/core").RuntimeRecordState;
|
|
74
115
|
};
|
|
75
116
|
};
|
|
117
|
+
export declare function toResponsesObject(body: ResponsesRequest, result: RuntimeResponse): {
|
|
118
|
+
id: string;
|
|
119
|
+
object: string;
|
|
120
|
+
created_at: number;
|
|
121
|
+
status: import("@stable-harness/core").RuntimeRecordState;
|
|
122
|
+
model: string;
|
|
123
|
+
output: {
|
|
124
|
+
id: string;
|
|
125
|
+
type: string;
|
|
126
|
+
status: string;
|
|
127
|
+
role: string;
|
|
128
|
+
content: {
|
|
129
|
+
type: string;
|
|
130
|
+
text: string;
|
|
131
|
+
annotations: never[];
|
|
132
|
+
}[];
|
|
133
|
+
}[];
|
|
134
|
+
output_text: string;
|
|
135
|
+
metadata: {
|
|
136
|
+
sessionId: string;
|
|
137
|
+
agentId: string;
|
|
138
|
+
state: import("@stable-harness/core").RuntimeRecordState;
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
export declare function toStoredResponsesObject(requestId: string, inspection: NonNullable<ReturnType<StableHarnessRuntime["inspectRequest"]>>): {
|
|
142
|
+
id: string;
|
|
143
|
+
object: string;
|
|
144
|
+
created_at: number;
|
|
145
|
+
status: string;
|
|
146
|
+
model: string;
|
|
147
|
+
output: {
|
|
148
|
+
id: string;
|
|
149
|
+
type: string;
|
|
150
|
+
status: string;
|
|
151
|
+
role: string;
|
|
152
|
+
content: {
|
|
153
|
+
type: string;
|
|
154
|
+
text: string;
|
|
155
|
+
annotations: never[];
|
|
156
|
+
}[];
|
|
157
|
+
}[];
|
|
158
|
+
output_text: string;
|
|
159
|
+
metadata: {
|
|
160
|
+
sessionId: string;
|
|
161
|
+
agentId: string;
|
|
162
|
+
state: import("@stable-harness/core").RuntimeRecordState;
|
|
163
|
+
};
|
|
164
|
+
};
|
|
76
165
|
export declare function toRuntimeErrorResponse(result: RuntimeResponse): {
|
|
77
166
|
error: {
|
|
78
167
|
message: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID as e}from"node:crypto";export function toRuntimeRequest(t,n,
|
|
1
|
+
import{randomUUID as e}from"node:crypto";export function toRuntimeRequest(t,s,n,o={}){const r=function messagesToInput(e){if(!Array.isArray(e)||0===e.length)throw new Error("messages must be a non-empty array");return e.map(e=>`${e.role??"user"}: ${contentToText(e.content)}`).join("\n\n")}(t.messages),a=readRequestId(t.metadata)??`chatcmpl-${e()}`,i=o.sessionId??readSessionId(t.metadata),u=normalizeOpenAiMessages(t.messages),p=i?function prependSessionMessages(e,t,s){if(function hasClientHistory(e){return e.some(e=>"assistant"===e.role)||e.filter(e=>"user"===e.role).length>1}(s))return s;const n=e.listRequests({sessionId:t,state:"completed"}).flatMap(t=>function inspectSessionTurn(e,t){const s=e.inspectRequest(t),n=s?.output?.trim(),o=function lastUserMessage(e){return normalizeOpenAiMessages(Array.isArray(e)?e:void 0).filter(e=>"user"===e.role&&e.content.trim()).at(-1)}(s?.metadata?.openaiMessages)?.content;return o&&n?[{role:"user",content:o},{role:"assistant",content:n}]:[]}(e,t.requestId)).slice(-12);return n.length>0?[...n,...s]:s}(s,i,u):u;return{input:r,requestId:a,agentId:resolveAgentId(t.model,s,n),...i?{sessionId:i}:{},metadata:{protocol:"openai-compatible",openaiStream:!0===t.stream,openaiMessages:p,openaiSessionHistory:p.length>u.length,model:t.model,user:t.user,clientMetadata:t.metadata}}}export function toResponsesRuntimeRequest(t,s,n){const o=function responseInputToText(e,t){const s="string"==typeof e?e:Array.isArray(e)?e.map(responseInputItemToText).filter(Boolean).join("\n\n"):"",n=[t?.trim()?`system: ${t.trim()}`:"",s].filter(Boolean).join("\n\n");if(!n)throw new Error("input must be a non-empty string or input item array");return n}(t.input,t.instructions),r=readRequestId(t.metadata)??`resp-${e()}`,a="string"==typeof t.conversation?t.conversation:t.conversation?.id,i=readSessionId(t.metadata)??a??t.previous_response_id;return{input:o,requestId:r,agentId:resolveAgentId(t.model,s,n),...i?{sessionId:i}:{},metadata:{protocol:"openai-responses",openaiStream:!0===t.stream,previousResponseId:t.previous_response_id,conversation:t.conversation,model:t.model,clientMetadata:t.metadata}}}function readSessionId(e){const t=e?.sessionId??e?.session_id??e?.conversationId??e?.conversation_id;return"string"==typeof t&&t.trim()?t:void 0}function readRequestId(e){const t=e?.requestId??e?.request_id;return"string"==typeof t&&t.trim()?t:void 0}export function resolveAgentId(e,t,s){if(!e)return;const n=s.modelAgentMap?.[e];return n||(t.inspect().agents.includes(e)?e:void 0)}export function createModelsResponse(e,t){const s=Object.keys(t.modelAgentMap??{});return{object:"list",data:[...new Set([...e.inspect().agents,...s])].sort().map(e=>({id:e,object:"model",created:0,owned_by:"stable-harness"}))}}export function createCapabilitiesResponse(){return{object:"stable_harness.capabilities",endpoints:["/v1/models","/v1/chat/completions","/v1/responses","/v1/responses/{response_id}","/v1/responses/{response_id}/cancel","/v1/capabilities","/v1/stable-harness/inspect","/metrics","/v1/stable-harness/runs/{request_id}/trace","/v1/stable-harness/runs/{request_id}/spans","/v1/stable-harness/runs/{request_id}/replay","/v1/stable-harness/runs/{request_id}/events","/runtime/v1/*"],streaming:!0,toolProgressEvents:!0,runtimeTrace:!0,runtimeSpans:!0,runtimeReplay:!0,runtimeEvents:{replay:!0,filters:["types","sessionId","agentId","since"]},responsesApi:{create:!0,retrieve:!0,delete:!0,cancel:!0,stream:!0},stableHarnessExtensions:["metadata.sessionId","metadata.requestId","conversation","previous_response_id"]}}export function toChatCompletion(e,t){return{id:t.requestId,object:"chat.completion",created:Math.floor(Date.now()/1e3),model:e.model??t.agentId,choices:[{index:0,message:{role:"assistant",content:t.output},finish_reason:"stop"}],usage:estimateUsage(e.messages,t.output),metadata:{sessionId:t.sessionId,agentId:t.agentId,state:t.state}}}export function toResponsesObject(e,t){const s="completed"===t.state;return{id:t.requestId,object:"response",created_at:Math.floor(Date.now()/1e3),status:s?"completed":t.state,model:e.model??t.agentId,output:[{id:`${t.requestId}-message`,type:"message",status:s?"completed":"incomplete",role:"assistant",content:[{type:"output_text",text:t.output,annotations:[]}]}],output_text:t.output,metadata:{sessionId:t.sessionId,agentId:t.agentId,state:t.state}}}export function toStoredResponsesObject(e,t){const s=t.summary.state;return{id:e,object:"response",created_at:Math.floor(new Date(t.summary.startedAt??Date.now()).getTime()/1e3),status:"completed"===s?"completed":s,model:t.summary.agentId,output:[{id:`${e}-message`,type:"message",status:"completed"===s?"completed":"incomplete",role:"assistant",content:[{type:"output_text",text:t.output??"",annotations:[]}]}],output_text:t.output??"",metadata:{sessionId:t.summary.sessionId,agentId:t.summary.agentId,state:s}}}export function toRuntimeErrorResponse(e){const t="cancelled"===e.state;return{error:{message:e.output||(t?"Runtime request was cancelled.":"Runtime request failed."),type:t?"request_cancelled":"server_error",code:t?"runtime_cancelled":"runtime_failed",param:null},metadata:{requestId:e.requestId,sessionId:e.sessionId,agentId:e.agentId,state:e.state}}}function responseInputItemToText(e){if("string"==typeof e)return e;const t="object"==typeof e&&null!==e?e:{},s="string"==typeof t.role?t.role:"user",n=t.content;return"string"==typeof n?`${s}: ${n}`:Array.isArray(n)?`${s}: ${n.map(responseContentPartToText).filter(Boolean).join("\n")}`:""}function responseContentPartToText(e){const t="object"==typeof e&&null!==e?e:{};return"string"==typeof t.text?t.text:"string"==typeof t.content?t.content:"string"==typeof t.input_text?t.input_text:""}function normalizeOpenAiMessages(e){return Array.isArray(e)?e.map(e=>({role:e.role??"user",content:contentToText(e.content)})):[]}function contentToText(e){if("string"==typeof e)return e;if(!Array.isArray(e))throw new Error("message content must be a string or content part array");return e.map(contentPartToText).join("\n")}function contentPartToText(e){if("object"!=typeof e||null===e)throw new Error("message content parts must be objects");const t=e;if("text"===t.type&&"string"==typeof t.text)return t.text;const s=t.image_url;if("image_url"===t.type&&"string"==typeof s?.url)return`[image:${s.url}]`;throw new Error("unsupported_content_type")}function estimateUsage(e,t){const s=estimateTokens(Array.isArray(e)?e.map(e=>contentToText(e.content)).join("\n"):""),n=estimateTokens(t);return{prompt_tokens:s,completion_tokens:n,total_tokens:s+n}}function estimateTokens(e){return e.trim()?Math.ceil(1.3*e.trim().split(/\s+/u).length):0}
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { type IncomingMessage, type ServerResponse } from "node:http";
|
|
2
|
-
import type
|
|
2
|
+
import { type StableHarnessRuntime } from "@stable-harness/core";
|
|
3
|
+
import { type JsonRpcMessage } from "./protocol-utils.js";
|
|
3
4
|
export type AgentProtocolServerOptions = {
|
|
4
5
|
baseUrl?: string;
|
|
5
|
-
enabledProtocols
|
|
6
|
+
enabledProtocols: Array<"acp" | "a2a" | "agui">;
|
|
6
7
|
bearerToken?: string;
|
|
7
8
|
};
|
|
8
|
-
|
|
9
|
-
jsonrpc?: string;
|
|
10
|
-
id?: string | number | null;
|
|
11
|
-
method?: string;
|
|
12
|
-
params?: unknown;
|
|
13
|
-
};
|
|
14
|
-
export declare function createAgentProtocolHttpServer(runtime: StableHarnessRuntime, options?: AgentProtocolServerOptions): import("node:http").Server<typeof IncomingMessage, typeof ServerResponse>;
|
|
9
|
+
export declare function createAgentProtocolHttpServer(runtime: StableHarnessRuntime, options: AgentProtocolServerOptions): import("node:http").Server<typeof IncomingMessage, typeof ServerResponse>;
|
|
15
10
|
export declare function handleAcpJsonRpcMessage(runtime: StableHarnessRuntime, message: JsonRpcMessage): Promise<{
|
|
16
11
|
jsonrpc: string;
|
|
17
12
|
id: string | number | null | undefined;
|
|
@@ -24,4 +19,3 @@ export declare function handleAcpJsonRpcMessage(runtime: StableHarnessRuntime, m
|
|
|
24
19
|
message: string;
|
|
25
20
|
};
|
|
26
21
|
} | undefined>;
|
|
27
|
-
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createServer as t}from"node:http";import{notifyA2aPush as e,createAcpInitializeResult as s,errorMessage as a,handleAgentControlRoute as n,handleAcpRunInspection as o,jsonRpcError as r,jsonRpcResult as i,matchPath as u,readA2aPushConfig as d,readJson as c,readPromptText as p,readRecord as m,readRunInspectionPath as l,readRuntimeRequestExtension as f,readSseReplayCursor as I,readString as h,sendJson as g,sendRunInspection as T,isTerminalState as A,storeA2aPushConfig as k,streamRuntimeEventReplay as _,toA2aArtifact as y,toA2aHistoryMessage as E,toAguiEvent as S,validateA2aVersion as q,writeSse as R,writeSseHeaders as v}from"./protocol-utils.js";export function createAgentProtocolHttpServer(e,o){if(0===o.enabledProtocols.length)throw new Error("enabledProtocols must include at least one protocol facade");const y=new Set(o.enabledProtocols),E=new Map;return t(async(t,w)=>{try{if("GET"===t.method&&"/health"===t.url)return void g(w,200,{ok:!0,protocols:[...y]});if(!function isAuthorized(t,e){return!e.bearerToken||t.headers.authorization===`Bearer ${e.bearerToken}`}(t,o))return void g(w,401,{error:"unauthorized"});if("GET"===t.method&&"/capabilities"===t.url)return void g(w,200,function createProtocolCapabilityManifest(t){return{protocol:"stable-harness-protocol-facade",protocols:[...t].sort().map(t=>({id:t,transports:"acp"===t?["stdio","http-jsonrpc"]:"a2a"===t?["http-json","sse"]:["http-sse"],session:"acp"===t?{level:"protocol-session",mapsTo:"sessionId",operatorApi:!1}:"a2a"===t?{level:"continuity",mapsTo:"contextId|taskId",operatorApi:!1}:{level:"continuity",mapsTo:"threadId|sessionId",operatorApi:!1}})),stableRuntime:{basePath:"/runtime/v1",session:{level:"operator-api",operatorApi:!0}}}}(y));if(await n(e,t,w))return;if(y.has("a2a")&&await async function handleA2a(t,e,s,a,n){if(!q(e,s))return!0;if("GET"===e.method&&("/.well-known/agent-card.json"===e.url||"/a2a/agent-card.json"===e.url))return g(s,200,function createAgentCard(t,e){const s=t.inspect();return{protocolVersion:"1.0",name:s.workspaceRoot.split(/[\\/]/u).filter(Boolean).at(-1)??"stable-harness",description:"Stable Harness runtime agent endpoint",version:process.env.STABLE_HARNESS_BUILD_VERSION??process.env.npm_package_version??"0.0.142",url:e.baseUrl?`${e.baseUrl.replace(/\/$/u,"")}/a2a`:"/a2a",preferredTransport:"HTTP+JSON",capabilities:{streaming:!0,pushNotifications:!0},defaultInputModes:["text/plain"],defaultOutputModes:["text/plain"],skills:s.agents.map(t=>({id:t,name:t,description:t}))}}(t,a)),!0;if("GET"===e.method&&"/a2a/inspect"===e.url)return g(s,200,t.inspect()),!0;const o=u(e.url,/^\/a2a\/tasks\/([^/]+):subscribe$/u);if("GET"===e.method&&o)return function streamA2aTask(t,e,s){const a=t.inspectRequest(e);if(!a)return void g(s,404,{error:"task_not_found"});if(v(s),R(s,{jsonrpc:"2.0",result:{task:toA2aTask(a)}}),A(a.summary.state))return void s.end();const n=t.subscribe(t=>{t.requestId===e&&R(s,{jsonrpc:"2.0",result:{event:toA2aEvent(t)}})});s.on("close",n)}(t,o,s),!0;const p=u(e.url,/^\/a2a\/tasks\/([^/]+):cancel$/u);if("POST"===e.method&&p)return t.cancel(p,"a2a_cancel"),g(s,200,{task:t.inspectRequest(p)}),!0;const f=l(e.url,/^\/a2a\/tasks\/([^/]+)\/(trace|spans|replay)$/u);if("GET"===e.method&&f)return T(t,s,f,"task_not_found"),!0;const I=u(e.url,/^\/a2a\/tasks\/([^/]+)$/u);if("GET"===e.method&&I){const e=t.inspectRequest(I);return g(s,e?200:404,e?{task:toA2aTask(e)}:{error:"task_not_found"}),!0}if("GET"===e.method&&"/a2a/tasks"===e.url)return g(s,200,{tasks:t.listRequests().map(toA2aTaskSummary)}),!0;const _=u(e.url,/^\/a2a\/tasks\/([^/]+)\/pushNotificationConfig$/u);if(_&&"GET"===e.method)return g(s,200,{taskId:_,pushNotificationConfig:n.get(_)??null}),!0;const y=u(e.url,/^\/a2a\/tasks\/([^/]+)\/pushNotificationConfig:set$/u);if(y&&"POST"===e.method){const t=d(await c(e));return t&&n.set(y,t),g(s,t?200:400,t?{taskId:y,pushNotificationConfig:t}:{error:"invalid_push_notification_config"}),!0}if("POST"===e.method&&"/a2a/message:send"===e.url){const a=await c(e),o=toA2aRuntimeRequest(a);k(n,o,a);const r=await runA2aRequestWithPush(t,o,n);return g(s,200,{task:toA2aTask(r)}),!0}return"POST"===e.method&&"/a2a/message:stream"===e.url?(await streamA2a(t,await c(e),s,void 0,n),!0):"POST"===e.method&&"/a2a/rpc"===e.url&&(await async function handleA2aRpc(t,e,s,a){if("SendMessage"===e.method){const n=m(e.params)??{},o=toA2aRuntimeRequest(n);k(a,o,n);const r=await runA2aRequestWithPush(t,o,a);return void g(s,200,i(e.id,{task:toA2aTask(r)}))}if("SendStreamingMessage"!==e.method){if("GetTask"===e.method){const a=h(m(e.params)?.id),n=a?t.inspectRequest(a):void 0;return void g(s,n?200:404,n?i(e.id,toA2aTask(n)):r(e.id,-32004,"task_not_found"))}if("ListTasks"!==e.method){if("CancelTask"===e.method){const a=h(m(e.params)?.id);a&&t.cancel(a,"a2a_cancel");const n=a?t.inspectRequest(a):void 0;return void g(s,n?200:404,n?i(e.id,toA2aTask(n)):r(e.id,-32004,"task_not_found"))}if("SetTaskPushNotificationConfig"===e.method){const t=m(e.params)??{},n=h(t.id)??h(t.taskId),o=d(t);return n&&o&&a.set(n,o),void g(s,n&&o?200:400,n&&o?i(e.id,{taskId:n,pushNotificationConfig:o}):r(e.id,-32602,"invalid_push_notification_config"))}if("GetTaskPushNotificationConfig"===e.method){const t=m(e.params)??{},n=h(t.id)??h(t.taskId);return void g(s,n&&a.has(n)?200:404,n?i(e.id,{taskId:n,pushNotificationConfig:a.get(n)??null}):r(e.id,-32602,"task_id_required"))}g(s,404,r(e.id,-32601,"method_not_found"))}else g(s,200,i(e.id,{tasks:t.listRequests().map(toA2aTaskSummary)}))}else await streamA2a(t,m(e.params)??{},s,e.id,a)}(t,await c(e),s,n),!0)}(e,t,w,o,E))return;if(y.has("agui")&&await async function handleAgui(t,e,s){if("GET"===e.method&&"/ag-ui/capabilities"===e.url)return g(s,200,{protocol:"ag-ui",transports:["http+sse"],events:["RUN_STARTED","TEXT_MESSAGE_START","TEXT_MESSAGE_CONTENT","TEXT_MESSAGE_END","TOOL_CALL_START","TOOL_CALL_RESULT","CUSTOM","RUN_FINISHED","RUN_ERROR"],state:{get:!0,events:!0,resume:"sse-last-event-id"}}),!0;if("GET"===e.method&&"/ag-ui/inspect"===e.url)return g(s,200,t.inspect()),!0;const n=u(e.url,/^\/ag-ui\/runs\/([^/]+)\/state$/u);if("GET"===e.method&&n){const e=t.inspectRequest(n);return g(s,e?200:404,e?function toAguiRunState(t,e){return{threadId:e.summary.sessionId,runId:t,status:e.summary.state,output:e.output,messages:e.output?[{id:`${t}-message`,role:"assistant",content:e.output}]:[],events:e.timeline.map(t=>S(t.event))}}(n,e):{error:"run_not_found"}),!0}const o=function readAguiRunInspection(t){return l(t,/^\/ag-ui\/runs\/([^/]+)\/(trace|spans|replay)$/u)}(e.url);if("GET"===e.method&&o)return T(t,s,o),!0;const r=u(e.url,/^\/ag-ui\/runs\/([^/]+)\/events(?:\?.*)?$/u);return"GET"===e.method&&r?(_(t,r,s,S,{afterEventId:I(e)}),!0):"POST"===e.method&&"/ag-ui/runs"===e.url&&(await async function streamAgui(t,e,s){const n=f(e),o=n?.requestId??h(e.runId)??crypto.randomUUID(),r=n?.sessionId??h(e.threadId)??h(e.sessionId)??`thread-${o}`,i=p(e);var u;v(s),R(s,{type:"RUN_STARTED",timestamp:Date.now(),threadId:r,runId:o,input:(u={body:e,input:i,threadId:r,runId:o},{threadId:u.threadId,runId:u.runId,messages:Array.isArray(u.body.messages)?u.body.messages:[{id:`${u.runId}-user`,role:"user",content:u.input}],tools:Array.isArray(u.body.tools)?u.body.tools:[],context:Array.isArray(u.body.context)?u.body.context:[]})});const d=t.subscribe(t=>{t.requestId===o&&R(s,S(t))});try{const a=await t.request(n??{input:i,requestId:o,sessionId:r,agentId:h(e.agentId),metadata:{protocol:"ag-ui"}}),u=`${o}-message`;a.output&&function writeAguiText(t,e,s){R(t,{type:"TEXT_MESSAGE_START",timestamp:Date.now(),messageId:e,role:"assistant"}),R(t,{type:"TEXT_MESSAGE_CONTENT",timestamp:Date.now(),messageId:e,delta:s}),R(t,{type:"TEXT_MESSAGE_END",timestamp:Date.now(),messageId:e})}(s,u,a.output),R(s,{type:"RUN_FINISHED",timestamp:Date.now(),threadId:r,runId:o,result:a.output})}catch(t){R(s,{type:"RUN_ERROR",timestamp:Date.now(),threadId:r,runId:o,message:a(t),code:"runtime_error"})}finally{d(),s.end()}}(t,await c(e),s),!0)}(e,t,w))return;if(y.has("acp")&&await async function handleAcp(t,e,a){if("GET"===e.method&&"/acp/capabilities"===e.url)return g(a,200,s(t)),!0;if("POST"===e.method&&"/acp"===e.url){const s=await c(e),n=await handleAcpJsonRpcMessage(t,s);return n?g(a,200,n):a.writeHead(204).end(),!0}return!1}(e,t,w))return;g(w,404,{error:"not_found"})}catch(t){g(w,400,{error:a(t)})}})}export async function handleAcpJsonRpcMessage(t,e){if(!e.id&&"session/cancel"===e.method){const s=h(m(e.params)?.sessionId);return void(s&&t.listRequests({sessionId:s,state:"running"}).forEach(e=>t.cancel(e.requestId,"acp_cancel")))}if("initialize"===e.method)return i(e.id,s(t,m(e.params)));if("session/new"===e.method)return i(e.id,{sessionId:`acp-${crypto.randomUUID()}`});if("session/load"===e.method)return i(e.id,{sessionId:h(m(e.params)?.sessionId)});if("session/list"===e.method)return i(e.id,{sessions:t.listSessions()});if("session/close"===e.method){const s=h(m(e.params)?.sessionId);return i(e.id,s?t.deleteSession(s):{deletedCount:0})}if("session/prompt"===e.method){const s=m(e.params)??{},a=f(s),n=await t.request(a??{input:p(s),sessionId:h(s.sessionId),agentId:h(s.agentId),metadata:{protocol:"acp",transport:"http-jsonrpc"}});return i(e.id,{stopReason:"completed"===n.state?"end_turn":"refusal",_meta:{requestId:n.requestId,output:n.output}})}if("runtime/inspect"===e.method)return i(e.id,t.inspect());return o(t,e)||r(e.id,-32601,"method_not_found")}async function streamA2a(t,s,a,n,o){const r=toA2aRuntimeRequest(s);var i;o&&k(o,r,s),v(a),R(a,{jsonrpc:"2.0",id:n,result:{task:(i=r,{id:i.requestId??crypto.randomUUID(),contextId:i.sessionId,status:{state:"submitted",timestamp:(new Date).toISOString()},metadata:{agentId:i.agentId}})}});const u=t.subscribe(t=>{if(t.requestId===r.requestId){const s=toA2aEvent(t);R(a,{jsonrpc:"2.0",id:n,result:{event:s}}),o&&e(o,t.requestId,s)}});try{const e=await t.request(r);R(a,{jsonrpc:"2.0",id:n,result:{task:toA2aTask(e),final:!0}})}finally{u(),a.end()}}async function runA2aRequestWithPush(t,s,a){const n=t.subscribe(t=>{t.requestId===s.requestId&&e(a,t.requestId,toA2aEvent(t))});try{return await t.request(s)}finally{n()}}function toA2aRuntimeRequest(t){const e=f(t);if(e)return{...e,metadata:{...e.metadata,protocol:"a2a"}};const s=m(t.message)??t;return{input:p(s),requestId:h(t.requestId)??h(s.messageId),sessionId:h(t.taskId)??h(s.taskId)??h(s.contextId),agentId:h(t.agentId)??h(t.metadata&&m(t.metadata)?.agentId),metadata:{protocol:"a2a",configuration:t.configuration,metadata:t.metadata}}}function toA2aTask(t){const e="state"in t?t.state:t.summary.state,s="output"in t?t.output:t.output??"",a="requestId"in t?t.requestId:t.summary.requestId,n="sessionId"in t?t.sessionId:t.summary.sessionId,o=[...s?[{artifactId:`${a}-output`,name:"result",parts:[{kind:"text",text:s}]}]:[],..."artifacts"in t&&Array.isArray(t.artifacts)?t.artifacts.map(y):[]];return{id:a,contextId:n,status:{state:"completed"===e?"completed":e,message:s?{role:"agent",messageId:`${a}-response`,parts:[{kind:"text",text:s}]}:void 0,timestamp:(new Date).toISOString()},artifacts:o.length?o:void 0,..."state"in t?{}:{history:t.timeline.map(t=>E(t.index,t.event))}}}function toA2aTaskSummary(t){return{id:t.requestId,contextId:t.sessionId,status:{state:t.state},metadata:{agentId:t.agentId}}}function toA2aEvent(t){const e="runtime.request.completed"===t.type?{role:"agent",messageId:`${t.requestId}-response`,parts:[{kind:"text",text:t.output}]}:void 0;return{kind:"status-update",taskId:t.requestId,contextId:t.sessionId,status:{state:(s=t.type,"runtime.request.started"===s?"working":"runtime.request.completed"===s?"completed":"runtime.request.failed"===s?"failed":"runtime.request.cancelled"===s?"canceled":"working"),message:e,timestamp:(new Date).toISOString()},metadata:{stableHarnessEvent:t}};var s}
|