stable-harness 0.0.87 → 0.0.88
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 +1 -1
- package/docs/guides/integration-guide.md +11 -5
- package/docs/protocols/http-runtime.md +51 -3
- package/node_modules/@stable-harness/adapter-deepagents/package.json +2 -2
- package/node_modules/@stable-harness/adapter-langgraph/package.json +2 -2
- package/node_modules/@stable-harness/core/package.json +3 -3
- 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 +16 -0
- package/node_modules/@stable-harness/protocols/dist/src/http-events.js +1 -0
- package/node_modules/@stable-harness/protocols/dist/src/http-server.js +1 -1
- package/node_modules/@stable-harness/protocols/package.json +2 -2
- package/node_modules/@stable-harness/tool-gateway/package.json +1 -1
- package/node_modules/@stable-harness/workspace-yaml/package.json +2 -2
- package/package.json +10 -10
- package/packages/adapter-deepagents/package.json +2 -2
- package/packages/adapter-langgraph/package.json +2 -2
- package/packages/cli/package.json +8 -8
- package/packages/core/package.json +3 -3
- package/packages/evaluation/package.json +2 -2
- package/packages/governance/package.json +1 -1
- package/packages/memory/package.json +1 -1
- package/packages/protocols/dist/src/http-events.d.ts +16 -0
- package/packages/protocols/dist/src/http-events.js +1 -0
- package/packages/protocols/dist/src/http-server.js +1 -1
- package/packages/protocols/package.json +2 -2
- package/packages/tool-gateway/package.json +1 -1
- package/packages/workspace-yaml/package.json +2 -2
package/README.md
CHANGED
|
@@ -219,9 +219,9 @@ This is constrained repair, not silent magic:
|
|
|
219
219
|
|
|
220
220
|
## Protocols
|
|
221
221
|
|
|
222
|
+
- Stable Runtime HTTP + SSE: [docs/protocols/http-runtime.md](docs/protocols/http-runtime.md)
|
|
222
223
|
- OpenAI-compatible facade: [docs/protocols/openai-compatible.md](docs/protocols/openai-compatible.md)
|
|
223
224
|
- LangGraph-compatible facade: [docs/protocols/langgraph-compatible.md](docs/protocols/langgraph-compatible.md)
|
|
224
|
-
- HTTP runtime protocol: [docs/protocols/http-runtime.md](docs/protocols/http-runtime.md)
|
|
225
225
|
|
|
226
226
|
## Documentation
|
|
227
227
|
|
|
@@ -88,13 +88,19 @@ Use this path when an existing product or evaluation harness already speaks
|
|
|
88
88
|
OpenAI-compatible chat completions. Stable Harness still owns workspace loading,
|
|
89
89
|
runtime events, tool-gateway policy, memory lifecycle, and adapter selection.
|
|
90
90
|
|
|
91
|
-
##
|
|
91
|
+
## Stable Runtime HTTP + SSE
|
|
92
92
|
|
|
93
|
-
Use
|
|
94
|
-
directly: request IDs, sessions, traces, approvals, cancellation,
|
|
95
|
-
inspection
|
|
93
|
+
Use Stable Runtime HTTP + SSE when the caller needs Stable Harness concepts
|
|
94
|
+
directly: request IDs, sessions, traces, spans, approvals, cancellation,
|
|
95
|
+
artifacts, memory lifecycle, runtime inspection, and real-time control-plane
|
|
96
|
+
updates.
|
|
96
97
|
|
|
97
|
-
|
|
98
|
+
This is the first-party protocol for Studio and product shells. OpenAI
|
|
99
|
+
compatible `/v1` and LangGraph-compatible servers are ecosystem facades; future
|
|
100
|
+
ACP, A2A, and AG-UI support should map to this protocol instead of adding new
|
|
101
|
+
runtime semantics.
|
|
102
|
+
|
|
103
|
+
See [Stable Runtime HTTP + SSE](../protocols/http-runtime.md).
|
|
98
104
|
|
|
99
105
|
## Backend Adapters
|
|
100
106
|
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Stable Runtime HTTP + SSE Protocol
|
|
2
2
|
|
|
3
|
-
The native
|
|
3
|
+
The native Stable Runtime protocol is the product control-plane contract. It is
|
|
4
|
+
the source of truth for first-party clients such as Studio, operator dashboards,
|
|
5
|
+
and embedded product shells.
|
|
6
|
+
|
|
7
|
+
OpenAI-compatible `/v1` and LangGraph-compatible servers are ecosystem
|
|
8
|
+
facades. ACP, A2A, and AG-UI should be added later as adapters over this
|
|
9
|
+
contract, not as new runtime semantics.
|
|
10
|
+
|
|
11
|
+
## HTTP Commands And Queries
|
|
4
12
|
|
|
5
13
|
`POST /requests` is a protocol adapter over `RuntimeRequest`. It may pass these
|
|
6
14
|
stable fields through to the runtime:
|
|
@@ -22,8 +30,9 @@ runtime requests.
|
|
|
22
30
|
Inspection endpoints expose normalized runtime state:
|
|
23
31
|
|
|
24
32
|
- `GET /inspect`
|
|
25
|
-
- `GET /requests
|
|
33
|
+
- `GET /requests?sessionId=...&agentId=...&state=...`
|
|
26
34
|
- `GET /requests/:id`
|
|
35
|
+
- `POST /requests/:id/cancel`
|
|
27
36
|
- `DELETE /requests/:id`
|
|
28
37
|
- `GET /runs/:id/trace`
|
|
29
38
|
- `GET /runs/:id/spans`
|
|
@@ -33,6 +42,12 @@ Inspection endpoints expose normalized runtime state:
|
|
|
33
42
|
- `GET /workflows/:id/mermaid`
|
|
34
43
|
- `GET /workflows/:id/plan`
|
|
35
44
|
|
|
45
|
+
Approval endpoints expose operator decisions:
|
|
46
|
+
|
|
47
|
+
- `GET /approvals?status=pending`
|
|
48
|
+
- `POST /approvals/:id/approve`
|
|
49
|
+
- `POST /approvals/:id/reject`
|
|
50
|
+
|
|
36
51
|
Memory endpoints expose the native runtime memory store when one is configured:
|
|
37
52
|
|
|
38
53
|
- `POST /memories`
|
|
@@ -53,3 +68,36 @@ Each span includes `spanId`, optional `parentSpanId`, `kind`, `name`, `status`,
|
|
|
53
68
|
event references, and timing when the stored events include `emittedAt`.
|
|
54
69
|
Clients should render hierarchy from `parentSpanId` instead of inferring it from
|
|
55
70
|
display labels.
|
|
71
|
+
|
|
72
|
+
## SSE Runtime Events
|
|
73
|
+
|
|
74
|
+
`GET /events` streams normalized `RuntimeEvent` records as Server-Sent Events.
|
|
75
|
+
It replays matching stored events first, then streams new events from
|
|
76
|
+
`runtime.subscribe`.
|
|
77
|
+
|
|
78
|
+
Supported filters:
|
|
79
|
+
|
|
80
|
+
- `requestId`
|
|
81
|
+
- `sessionId`
|
|
82
|
+
- `agentId`
|
|
83
|
+
- `types`, as comma-separated event names or prefix globs such as
|
|
84
|
+
`runtime.request.*,runtime.approval.*`
|
|
85
|
+
- `since`, as an emitted-at timestamp cursor
|
|
86
|
+
|
|
87
|
+
Example:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
GET /events?sessionId=customer-123&types=runtime.request.*,runtime.approval.*
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Event format:
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
event: runtime.request.started
|
|
97
|
+
id: <eventId>
|
|
98
|
+
data: {"type":"runtime.request.started","eventId":"...","requestId":"...","sessionId":"...","agentId":"...","emittedAt":"..."}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This stream is for runtime/control-plane updates. OpenAI chat streaming remains
|
|
102
|
+
scoped to a single `/v1/chat/completions` response and must not become the
|
|
103
|
+
first-party control-plane event source.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/adapter-deepagents",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"@langchain/node-vfs": "^0.1.4",
|
|
16
16
|
"@langchain/ollama": "^1.2.7",
|
|
17
17
|
"@langchain/openai": "^1.4.5",
|
|
18
|
-
"@stable-harness/core": "0.0.
|
|
18
|
+
"@stable-harness/core": "0.0.88",
|
|
19
19
|
"deepagents": "^1.10.1",
|
|
20
20
|
"langchain": "^1.4.0"
|
|
21
21
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/adapter-langgraph",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
"types": "dist/src/index.d.ts",
|
|
12
12
|
"peerDependencies": {
|
|
13
13
|
"@langchain/langgraph": "^1.3.0",
|
|
14
|
-
"@stable-harness/core": "0.0.
|
|
14
|
+
"@stable-harness/core": "0.0.88"
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
".": "./dist/index.js"
|
|
12
12
|
},
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"@stable-harness/governance": "0.0.
|
|
15
|
-
"@stable-harness/memory": "0.0.
|
|
14
|
+
"@stable-harness/governance": "0.0.88",
|
|
15
|
+
"@stable-harness/memory": "0.0.88"
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import type { StableHarnessRuntime } from "@stable-harness/core";
|
|
3
|
+
export type RuntimeEventFilter = {
|
|
4
|
+
requestId?: string;
|
|
5
|
+
sessionId?: string;
|
|
6
|
+
agentId?: string;
|
|
7
|
+
types?: string[];
|
|
8
|
+
since?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function readRuntimeEventFilter(url: string | undefined): RuntimeEventFilter | undefined;
|
|
11
|
+
export declare function streamRuntimeEvents(input: {
|
|
12
|
+
runtime: StableHarnessRuntime;
|
|
13
|
+
request: IncomingMessage;
|
|
14
|
+
response: ServerResponse;
|
|
15
|
+
filter: RuntimeEventFilter;
|
|
16
|
+
}): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function readRuntimeEventFilter(e){if(!e?.startsWith("/events"))return;const t=new URL(e,"http://stable-harness.local");if("/events"!==t.pathname)return;const n=t.searchParams.get("types")?.split(",").map(e=>e.trim()).filter(Boolean);return{...readParam(t,"requestId")?{requestId:readParam(t,"requestId")}:{},...readParam(t,"sessionId")?{sessionId:readParam(t,"sessionId")}:{},...readParam(t,"agentId")?{agentId:readParam(t,"agentId")}:{},...n&&n.length>0?{types:n}:{},...readParam(t,"since")?{since:readParam(t,"since")}:{}}}export function streamRuntimeEvents(e){e.response.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"}),e.response.write(": stable-harness runtime event stream\n\n"),e.response.flushHeaders();for(const t of function replayEvents(e,t){return e.inspect().runs.flatMap(e=>e.events).filter(e=>matchesEventFilter(e,t))}(e.runtime,e.filter))writeRuntimeEvent(e.response,t);const t=e.runtime.subscribe(t=>{matchesEventFilter(t,e.filter)&&writeRuntimeEvent(e.response,t)});e.request.on("close",()=>{t(),e.response.end()})}function matchesEventFilter(e,t){return matchesValue(t.requestId,e.requestId)&&matchesValue(t.sessionId,e.sessionId)&&matchesValue(t.agentId,e.agentId)&&function matchesTypeFilter(e,t){return!t||0===t.length||t.some(t=>t.endsWith("*")?e.startsWith(t.slice(0,-1)):e===t)}(e.type,t.types)&&function matchesSince(e,t){return!t||e.eventId!==t&&Boolean(e.emittedAt&&e.emittedAt>t)}(e,t.since)}function matchesValue(e,t){return!e||e===t}function writeRuntimeEvent(e,t){e.write(`event: ${t.type}\n`),t.eventId&&e.write(`id: ${t.eventId}\n`),e.write(`data: ${JSON.stringify(t)}\n\n`)}function readParam(e,t){const n=e.searchParams.get(t);return n&&n.trim()?n:void 0}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createServer as e}from"node:http";import{compileWorkflowPlan as t,projectRuntimeTrace as
|
|
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(u){return e((e,i)=>{!async function handleHttpRequest(e,u,i){try{await async function routeHttpRequest(e,u,i){(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,u,i)||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,u,i)||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:u,response:i})||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("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,u,i)||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,u,i)||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,u,i)||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,u,i)||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 u=function readReplayRequestId(e){const t=(e??"").match(/^\/requests\/([^/]+)\/replay$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(t.url);if("GET"===t.method&&u){const t=e.exportReplayBundle(u);return sendJson(o,t?200:404,t??{error:"run_not_found"}),!0}return!1}(e,u,i)||sendJson(i,404,{error:"not_found"})}(e,u,i)}catch(e){sendJson(i,500,{error:e instanceof Error?e.message:String(e)})}}(u,e,i)})}function readRunState(e){return"queued"===e||"running"===e||"completed"===e||"failed"===e||"cancelled"===e?e:void 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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/protocols",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -10,6 +10,6 @@
|
|
|
10
10
|
"main": "dist/src/index.js",
|
|
11
11
|
"types": "dist/src/index.d.ts",
|
|
12
12
|
"peerDependencies": {
|
|
13
|
-
"@stable-harness/core": "0.0.
|
|
13
|
+
"@stable-harness/core": "0.0.88"
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/workspace-yaml",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
".": "./dist/index.js"
|
|
12
12
|
},
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"@stable-harness/core": "0.0.
|
|
14
|
+
"@stable-harness/core": "0.0.88"
|
|
15
15
|
}
|
|
16
16
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stable-harness",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Stable application runtime and operator control plane for agent workspaces.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -75,21 +75,21 @@
|
|
|
75
75
|
"packages/*"
|
|
76
76
|
],
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@easynet/better-call": "^0.1.
|
|
78
|
+
"@easynet/better-call": "^0.1.70",
|
|
79
79
|
"@langchain/core": "^1.1.46",
|
|
80
80
|
"@langchain/langgraph": "^1.3.0",
|
|
81
81
|
"@langchain/langgraph-api": "^1.2.1",
|
|
82
82
|
"@langchain/node-vfs": "^0.1.4",
|
|
83
83
|
"@langchain/ollama": "^1.2.7",
|
|
84
84
|
"@langchain/openai": "^1.4.5",
|
|
85
|
-
"@stable-harness/adapter-deepagents": "0.0.
|
|
86
|
-
"@stable-harness/adapter-langgraph": "0.0.
|
|
87
|
-
"@stable-harness/core": "0.0.
|
|
88
|
-
"@stable-harness/governance": "0.0.
|
|
89
|
-
"@stable-harness/memory": "0.0.
|
|
90
|
-
"@stable-harness/protocols": "0.0.
|
|
91
|
-
"@stable-harness/tool-gateway": "0.0.
|
|
92
|
-
"@stable-harness/workspace-yaml": "0.0.
|
|
85
|
+
"@stable-harness/adapter-deepagents": "0.0.88",
|
|
86
|
+
"@stable-harness/adapter-langgraph": "0.0.88",
|
|
87
|
+
"@stable-harness/core": "0.0.88",
|
|
88
|
+
"@stable-harness/governance": "0.0.88",
|
|
89
|
+
"@stable-harness/memory": "0.0.88",
|
|
90
|
+
"@stable-harness/protocols": "0.0.88",
|
|
91
|
+
"@stable-harness/tool-gateway": "0.0.88",
|
|
92
|
+
"@stable-harness/workspace-yaml": "0.0.88",
|
|
93
93
|
"deepagents": "^1.10.1",
|
|
94
94
|
"langchain": "^1.4.0",
|
|
95
95
|
"yaml": "^2.8.2",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/adapter-deepagents",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"@langchain/node-vfs": "^0.1.4",
|
|
16
16
|
"@langchain/ollama": "^1.2.7",
|
|
17
17
|
"@langchain/openai": "^1.4.5",
|
|
18
|
-
"@stable-harness/core": "0.0.
|
|
18
|
+
"@stable-harness/core": "0.0.88",
|
|
19
19
|
"deepagents": "^1.10.1",
|
|
20
20
|
"langchain": "^1.4.0"
|
|
21
21
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/adapter-langgraph",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
"types": "dist/src/index.d.ts",
|
|
12
12
|
"peerDependencies": {
|
|
13
13
|
"@langchain/langgraph": "^1.3.0",
|
|
14
|
-
"@stable-harness/core": "0.0.
|
|
14
|
+
"@stable-harness/core": "0.0.88"
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"types": "dist/src/index.d.ts",
|
|
15
15
|
"peerDependencies": {
|
|
16
16
|
"@langchain/langgraph-api": "^1.2.1",
|
|
17
|
-
"@stable-harness/adapter-deepagents": "0.0.
|
|
18
|
-
"@stable-harness/adapter-langgraph": "0.0.
|
|
19
|
-
"@stable-harness/core": "0.0.
|
|
20
|
-
"@stable-harness/memory": "0.0.
|
|
21
|
-
"@stable-harness/protocols": "0.0.
|
|
22
|
-
"@stable-harness/tool-gateway": "0.0.
|
|
23
|
-
"@stable-harness/workspace-yaml": "0.0.
|
|
17
|
+
"@stable-harness/adapter-deepagents": "0.0.88",
|
|
18
|
+
"@stable-harness/adapter-langgraph": "0.0.88",
|
|
19
|
+
"@stable-harness/core": "0.0.88",
|
|
20
|
+
"@stable-harness/memory": "0.0.88",
|
|
21
|
+
"@stable-harness/protocols": "0.0.88",
|
|
22
|
+
"@stable-harness/tool-gateway": "0.0.88",
|
|
23
|
+
"@stable-harness/workspace-yaml": "0.0.88"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
".": "./dist/index.js"
|
|
12
12
|
},
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"@stable-harness/governance": "0.0.
|
|
15
|
-
"@stable-harness/memory": "0.0.
|
|
14
|
+
"@stable-harness/governance": "0.0.88",
|
|
15
|
+
"@stable-harness/memory": "0.0.88"
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/evaluation",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -10,6 +10,6 @@
|
|
|
10
10
|
"main": "dist/src/index.js",
|
|
11
11
|
"types": "dist/src/index.d.ts",
|
|
12
12
|
"peerDependencies": {
|
|
13
|
-
"@stable-harness/core": "0.0.
|
|
13
|
+
"@stable-harness/core": "0.0.88"
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import type { StableHarnessRuntime } from "@stable-harness/core";
|
|
3
|
+
export type RuntimeEventFilter = {
|
|
4
|
+
requestId?: string;
|
|
5
|
+
sessionId?: string;
|
|
6
|
+
agentId?: string;
|
|
7
|
+
types?: string[];
|
|
8
|
+
since?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function readRuntimeEventFilter(url: string | undefined): RuntimeEventFilter | undefined;
|
|
11
|
+
export declare function streamRuntimeEvents(input: {
|
|
12
|
+
runtime: StableHarnessRuntime;
|
|
13
|
+
request: IncomingMessage;
|
|
14
|
+
response: ServerResponse;
|
|
15
|
+
filter: RuntimeEventFilter;
|
|
16
|
+
}): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function readRuntimeEventFilter(e){if(!e?.startsWith("/events"))return;const t=new URL(e,"http://stable-harness.local");if("/events"!==t.pathname)return;const n=t.searchParams.get("types")?.split(",").map(e=>e.trim()).filter(Boolean);return{...readParam(t,"requestId")?{requestId:readParam(t,"requestId")}:{},...readParam(t,"sessionId")?{sessionId:readParam(t,"sessionId")}:{},...readParam(t,"agentId")?{agentId:readParam(t,"agentId")}:{},...n&&n.length>0?{types:n}:{},...readParam(t,"since")?{since:readParam(t,"since")}:{}}}export function streamRuntimeEvents(e){e.response.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"}),e.response.write(": stable-harness runtime event stream\n\n"),e.response.flushHeaders();for(const t of function replayEvents(e,t){return e.inspect().runs.flatMap(e=>e.events).filter(e=>matchesEventFilter(e,t))}(e.runtime,e.filter))writeRuntimeEvent(e.response,t);const t=e.runtime.subscribe(t=>{matchesEventFilter(t,e.filter)&&writeRuntimeEvent(e.response,t)});e.request.on("close",()=>{t(),e.response.end()})}function matchesEventFilter(e,t){return matchesValue(t.requestId,e.requestId)&&matchesValue(t.sessionId,e.sessionId)&&matchesValue(t.agentId,e.agentId)&&function matchesTypeFilter(e,t){return!t||0===t.length||t.some(t=>t.endsWith("*")?e.startsWith(t.slice(0,-1)):e===t)}(e.type,t.types)&&function matchesSince(e,t){return!t||e.eventId!==t&&Boolean(e.emittedAt&&e.emittedAt>t)}(e,t.since)}function matchesValue(e,t){return!e||e===t}function writeRuntimeEvent(e,t){e.write(`event: ${t.type}\n`),t.eventId&&e.write(`id: ${t.eventId}\n`),e.write(`data: ${JSON.stringify(t)}\n\n`)}function readParam(e,t){const n=e.searchParams.get(t);return n&&n.trim()?n:void 0}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createServer as e}from"node:http";import{compileWorkflowPlan as t,projectRuntimeTrace as
|
|
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(u){return e((e,i)=>{!async function handleHttpRequest(e,u,i){try{await async function routeHttpRequest(e,u,i){(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,u,i)||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,u,i)||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:u,response:i})||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("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,u,i)||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,u,i)||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,u,i)||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,u,i)||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 u=function readReplayRequestId(e){const t=(e??"").match(/^\/requests\/([^/]+)\/replay$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(t.url);if("GET"===t.method&&u){const t=e.exportReplayBundle(u);return sendJson(o,t?200:404,t??{error:"run_not_found"}),!0}return!1}(e,u,i)||sendJson(i,404,{error:"not_found"})}(e,u,i)}catch(e){sendJson(i,500,{error:e instanceof Error?e.message:String(e)})}}(u,e,i)})}function readRunState(e){return"queued"===e||"running"===e||"completed"===e||"failed"===e||"cancelled"===e?e:void 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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/protocols",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -10,6 +10,6 @@
|
|
|
10
10
|
"main": "dist/src/index.js",
|
|
11
11
|
"types": "dist/src/index.d.ts",
|
|
12
12
|
"peerDependencies": {
|
|
13
|
-
"@stable-harness/core": "0.0.
|
|
13
|
+
"@stable-harness/core": "0.0.88"
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/workspace-yaml",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*.js",
|
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
".": "./dist/index.js"
|
|
12
12
|
},
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"@stable-harness/core": "0.0.
|
|
14
|
+
"@stable-harness/core": "0.0.88"
|
|
15
15
|
}
|
|
16
16
|
}
|