stable-harness 0.0.143 → 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.
@@ -97,6 +97,8 @@ stable-harness serve -w .
97
97
  Clients can point at the fixed local gateway paths:
98
98
 
99
99
  ```text
100
+ stable-harness-studio: https://shs.easynet.world/?baseUrl=http%3A%2F%2F127.0.0.1%3A56789
101
+ LangSmith Studio: https://smith.langchain.com/studio/?baseUrl=http%3A%2F%2F127.0.0.1%3A56789%2Fprotocols%2Flanggraph
100
102
  Runtime API: http://127.0.0.1:56789/runtime/v1
101
103
  OpenAI-compatible: http://127.0.0.1:56789/protocols/openai/v1
102
104
  LangGraph-compatible: http://127.0.0.1:56789/protocols/langgraph
@@ -105,6 +107,9 @@ LangGraph-compatible: http://127.0.0.1:56789/protocols/langgraph
105
107
  The facade is a protocol adapter around the same Stable Harness runtime. It is
106
108
  not a separate execution path.
107
109
 
110
+ The hosted Stable Harness Studio also accepts an explicit gateway parameter:
111
+ `https://shs.easynet.world/?baseUrl=<stable-harness-gateway-url>`.
112
+
108
113
  ## Develop The Framework
109
114
 
110
115
  Clone the repository only when you are changing Stable Harness itself:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/adapter-deepagents",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -16,7 +16,7 @@
16
16
  "@langchain/node-vfs": "^0.1.4",
17
17
  "@langchain/ollama": "^1.2.7",
18
18
  "@langchain/openai": "^1.4.5",
19
- "@stable-harness/core": "0.0.143",
19
+ "@stable-harness/core": "0.0.144",
20
20
  "deepagents": "^1.10.1",
21
21
  "langchain": "^1.4.0"
22
22
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/adapter-langgraph",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -12,6 +12,6 @@
12
12
  "types": "dist/src/index.d.ts",
13
13
  "peerDependencies": {
14
14
  "@langchain/langgraph": "^1.3.0",
15
- "@stable-harness/core": "0.0.143"
15
+ "@stable-harness/core": "0.0.144"
16
16
  }
17
17
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/core",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -12,7 +12,7 @@
12
12
  ".": "./dist/index.js"
13
13
  },
14
14
  "peerDependencies": {
15
- "@stable-harness/governance": "0.0.143",
16
- "@stable-harness/memory": "0.0.143"
15
+ "@stable-harness/governance": "0.0.144",
16
+ "@stable-harness/memory": "0.0.144"
17
17
  }
18
18
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/governance",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/memory",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/protocols",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -11,6 +11,6 @@
11
11
  "main": "dist/src/index.js",
12
12
  "types": "dist/src/index.d.ts",
13
13
  "peerDependencies": {
14
- "@stable-harness/core": "0.0.143"
14
+ "@stable-harness/core": "0.0.144"
15
15
  }
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/tool-gateway",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/workspace-yaml",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -12,6 +12,6 @@
12
12
  ".": "./dist/index.js"
13
13
  },
14
14
  "peerDependencies": {
15
- "@stable-harness/core": "0.0.143"
15
+ "@stable-harness/core": "0.0.144"
16
16
  }
17
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stable-harness",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "type": "module",
5
5
  "description": "Stable application runtime and operator control plane for agent workspaces.",
6
6
  "license": "Apache-2.0",
@@ -83,14 +83,14 @@
83
83
  "@langchain/node-vfs": "^0.1.4",
84
84
  "@langchain/ollama": "^1.2.7",
85
85
  "@langchain/openai": "^1.4.5",
86
- "@stable-harness/adapter-deepagents": "0.0.143",
87
- "@stable-harness/adapter-langgraph": "0.0.143",
88
- "@stable-harness/core": "0.0.143",
89
- "@stable-harness/governance": "0.0.143",
90
- "@stable-harness/memory": "0.0.143",
91
- "@stable-harness/protocols": "0.0.143",
92
- "@stable-harness/tool-gateway": "0.0.143",
93
- "@stable-harness/workspace-yaml": "0.0.143",
86
+ "@stable-harness/adapter-deepagents": "0.0.144",
87
+ "@stable-harness/adapter-langgraph": "0.0.144",
88
+ "@stable-harness/core": "0.0.144",
89
+ "@stable-harness/governance": "0.0.144",
90
+ "@stable-harness/memory": "0.0.144",
91
+ "@stable-harness/protocols": "0.0.144",
92
+ "@stable-harness/tool-gateway": "0.0.144",
93
+ "@stable-harness/workspace-yaml": "0.0.144",
94
94
  "deepagents": "^1.10.1",
95
95
  "langchain": "^1.4.0",
96
96
  "yaml": "^2.8.2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/adapter-deepagents",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -16,7 +16,7 @@
16
16
  "@langchain/node-vfs": "^0.1.4",
17
17
  "@langchain/ollama": "^1.2.7",
18
18
  "@langchain/openai": "^1.4.5",
19
- "@stable-harness/core": "0.0.143",
19
+ "@stable-harness/core": "0.0.144",
20
20
  "deepagents": "^1.10.1",
21
21
  "langchain": "^1.4.0"
22
22
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/adapter-langgraph",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -12,6 +12,6 @@
12
12
  "types": "dist/src/index.d.ts",
13
13
  "peerDependencies": {
14
14
  "@langchain/langgraph": "^1.3.0",
15
- "@stable-harness/core": "0.0.143"
15
+ "@stable-harness/core": "0.0.144"
16
16
  }
17
17
  }
@@ -1 +1 @@
1
- import{createServer as t,request as o}from"node:http";import{createAgentProtocolHttpServer as a,createHttpServer as e,createOpenAiCompatibleHttpServer as r}from"@stable-harness/protocols";import{startOfficialLangGraphServer as n}from"../langgraph-official.js";import{defaultGatewayPort as s,defaultHost as i,defaultLangGraphWorkers as p,readPort as c}from"./protocol-defaults.js";export async function createGatewayServer(l,u){const h=readRecord(l.getRuntimePolicy().protocols)??{},g=protocolConfig(h,"gateway","server")??{},f=u.host??configString(g.host)??i,m=c(u.port,"--port")??c(process.env.STABLE_HARNESS_PORT,"STABLE_HARNESS_PORT")??c(process.env.STABLE_HARNESS_GATEWAY_PORT,"STABLE_HARNESS_GATEWAY_PORT")??c(g.port,"protocols.gateway.port")??s,d=`http://${f}:${m}`,b=function gatewayBearerToken(t,o){return configString(t.bearerToken)??configString(t.apiKey)??o.apiKey}(g,u),v=await async function startGatewayTargets(t,o,s,c){const l={stable:await startHttpTarget("runtime",e(t),i)},u=await async function optionalOpenAiTarget(t,o,a){return enabled(protocolConfig(o,"openaiCompatible","openai-compatible","openai"))?await startHttpTarget("openai",r(t,{bearerToken:a}),i):void 0}(t,o,c),h=await async function optionalFacadeTarget(t,o,e,r){const n=["acp","a2a","agui"].filter(t=>enabled(protocolConfig(o,t)));return n.length>0?await startHttpTarget("facades",a(t,{baseUrl:`${e}/protocols`,bearerToken:r,enabledProtocols:n}),i):void 0}(t,o,s,c),g=await async function optionalLangGraphTarget(t,o){return enabled(protocolConfig(o,"langgraph"))?await async function startLangGraphTarget(t,o){const a=protocolConfig(o,"langgraph")??{},e=await n(t,{host:configString(a.host)??i,port:0,nWorkers:(r=a.nWorkers,("number"==typeof r&&Number.isFinite(r)?r:"string"==typeof r&&r.trim()?Number(r):void 0)??p),...configStringArray(a.exposeAgents)?{exposeAgents:configStringArray(a.exposeAgents)}:{},...void 0!==a.env?{env:a.env}:{},...void 0!==a.envFile?{envFile:a.envFile}:{}});var r;return{name:"langgraph",baseUrl:e.url,cleanup:e.cleanup}}(t,o):void 0}(t,o);return u&&(l.openai=u),h&&(l.facades=h),g&&(l.langgraph=g),l}(l,h,d,b),P=t((t,a)=>{!function isAuthorized(t,o){return!o||t.headers.authorization===`Bearer ${o}`}(t,b)?sendJson(a,401,{error:"unauthorized"}):function handleGatewayRoute(t,o,a,e){if("GET"===o.method&&"/health"===o.url)return sendJson(a,200,{ok:!0,product:"stable-harness"}),!0;if("GET"===o.method&&"/ready"===o.url)return sendJson(a,200,{ok:!0,targets:Object.keys(e.targets).sort()}),!0;if("GET"===o.method&&"/version"===o.url)return sendJson(a,200,function versionBody(){return{product:"stable-harness",version:stableHarnessVersion(),apiVersion:"2026-05-22"}}()),!0;if("GET"===o.method&&"/manifest"===o.url)return sendJson(a,200,function manifestBody(t,o){return{product:"stable-harness",version:stableHarnessVersion(),apiVersion:"2026-05-22",baseUrl:o,runtime:{basePath:"/runtime/v1",apiVersion:"v1",capabilities:runtimeCapabilities(t)},protocols:{openai:{basePath:"/protocols/openai/v1",pathVersion:"v1",compatibility:"openai-compatible"},langgraph:{basePath:"/protocols/langgraph",compatibility:"langsmith-agent-server",features:["assistants","threads","runs","store","mcp","a2a"],limitations:["crons-upstream-unavailable"]},mcp:{basePath:"/protocols/mcp",protocolVersion:"2024-11-05",transport:"streamable-http"},a2a:{basePath:"/protocols/a2a",protocolVersion:"1.0"},acp:{basePath:"/protocols/acp"},agui:{basePath:"/protocols/ag-ui"}}}}(t,e.baseUrl)),!0;if("GET"===o.method&&"/protocols"===o.url)return sendJson(a,200,{basePath:"/protocols",protocols:{openai:{basePath:"/protocols/openai/v1",pathVersion:"v1",compatibility:"openai-compatible"},langgraph:{basePath:"/protocols/langgraph",compatibility:"langsmith-agent-server",features:["assistants","threads","runs","store","mcp","a2a"],limitations:["crons-upstream-unavailable"]},mcp:{basePath:"/protocols/mcp",protocolVersion:"2024-11-05",transport:"streamable-http"},a2a:{basePath:"/protocols/a2a",protocolVersion:"1.0"},acp:{basePath:"/protocols/acp"},agui:{basePath:"/protocols/ag-ui"}}}),!0;const r=function protocolVersionRoute(t){const o=new URL(t.url??"/","http://stable-harness.local").pathname.match(/^\/protocols\/(openai|langgraph|mcp|a2a|acp|ag-ui)\/version$/u);if(!o)return;const a={openai:{basePath:"/protocols/openai/v1",pathVersion:"v1",compatibility:"openai-compatible"},langgraph:{basePath:"/protocols/langgraph",compatibility:"langsmith-agent-server",features:["assistants","threads","runs","store","mcp","a2a"],limitations:["crons-upstream-unavailable"]},mcp:{basePath:"/protocols/mcp",protocolVersion:"2024-11-05",transport:"streamable-http"},a2a:{basePath:"/protocols/a2a",protocolVersion:"1.0"},acp:{basePath:"/protocols/acp"},agui:{basePath:"/protocols/ag-ui"}}["ag-ui"===o[1]?"agui":o[1]];return{id:o[1],...a}}(o);return!("GET"!==o.method||!r)&&(sendJson(a,200,r),!0)}(l,t,a,{baseUrl:d,targets:v})||function proxyGatewayRoute(t,a,e){const r=function resolveGatewayProxy(t){const o=new URL(t??"/","http://stable-harness.local");return isPathOrChild(o.pathname,"/runtime/v1")?{target:"stable",path:stripPrefix(o,"/runtime/v1")}:isPathOrChild(o.pathname,"/protocols/openai/v1")?{target:"openai",path:`/v1${stripPrefix(o,"/protocols/openai/v1")}`}:isPathOrChild(o.pathname,"/protocols/acp")?{target:"facades",path:`/acp${stripProtocolPrefix(o,"/protocols/acp")}`}:isPathOrChild(o.pathname,"/protocols/a2a")?{target:"facades",path:`/a2a${stripProtocolPrefix(o,"/protocols/a2a")}`}:isPathOrChild(o.pathname,"/protocols/ag-ui")?{target:"facades",path:`/ag-ui${stripProtocolPrefix(o,"/protocols/ag-ui")}`}:isPathOrChild(o.pathname,"/protocols/langgraph")?{target:"langgraph",path:stripPrefix(o,"/protocols/langgraph")}:isPathOrChild(o.pathname,"/protocols/mcp")?{target:"langgraph",path:`/mcp${stripProtocolPrefix(o,"/protocols/mcp")}`}:void 0}(t.url);if(!r)return void sendJson(a,404,{error:"not_found"});const n=e[r.target];n?function proxyRequest(t,a,e,r){const n=new URL(r,e.baseUrl),s=o(n,{method:t.method,headers:{...t.headers,host:n.host}},t=>{a.writeHead(t.statusCode??502,t.headers),t.pipe(a)});s.on("error",t=>sendJson(a,502,{error:"bad_gateway",detail:t.message})),t.pipe(s)}(t,a,n,r.path):sendJson(a,404,{error:"protocol_not_enabled",protocol:r.target})}(t,a,v)});return{host:f,port:m,server:P,cleanup:async()=>async function closeTargets(t){await Promise.all(Object.values(t).map(t=>Promise.resolve(t.cleanup())))}(v)}}async function startHttpTarget(t,o,a){const e=await function listenOnRandomPort(t,o){return new Promise((a,e)=>{t.once("error",e),t.listen(0,o,()=>{t.off("error",e);const o=t.address();a("object"==typeof o&&o?o.port:0)})})}(o,a);return{name:t,baseUrl:`http://${a}:${e}`,cleanup:()=>function closeHttpServer(t){return new Promise((o,a)=>{t.closeAllConnections(),t.close(t=>t?a(t):o())})}(o)}}function isPathOrChild(t,o){return t===o||t.startsWith(`${o}/`)}function stripPrefix(t,o){return`${t.pathname.slice(o.length)||"/"}${t.search}`}function stripProtocolPrefix(t,o){return`${t.pathname.slice(o.length)}${t.search}`}function runtimeCapabilities(t){const o=t.inspect();return["runs","events","sessions","memory","approvals","artifacts","replay","workflows","trace","spans"].filter(t=>"workflows"!==t||o.workflows.length>0)}function stableHarnessVersion(){return process.env.STABLE_HARNESS_BUILD_VERSION??process.env.npm_package_version??"0.0.142"}function sendJson(t,o,a){t.writeHead(o,{"content-type":"application/json"}),t.end(JSON.stringify(a))}function protocolConfig(t,...o){for(const a of o){const o=readRecord(t[a]);if(o)return o}}function enabled(t){return!1!==t?.enabled}function readRecord(t){return"object"!=typeof t||null===t||Array.isArray(t)?void 0:t}function configString(t){if("string"!=typeof t||!t.trim())return;const o=t.match(/^\$\{env:([A-Za-z_][A-Za-z0-9_]*)(?::-(.*))?\}$/u);return o?process.env[o[1]]??o[2]:t}function configStringArray(t){if(Array.isArray(t)&&t.every(t=>"string"==typeof t))return t.filter(t=>t.trim()).map(t=>t.trim())}
1
+ import{createServer as t,request as o}from"node:http";import{createAgentProtocolHttpServer as a,createHttpServer as e,createOpenAiCompatibleHttpServer as r}from"@stable-harness/protocols";import{startOfficialLangGraphServer as n}from"../langgraph-official.js";import{defaultGatewayPort as s,defaultHost as i,defaultLangGraphWorkers as c,readPort as p}from"./protocol-defaults.js";import{renderStudioHtml as l}from"./studio.js";export async function createGatewayServer(h,u){const g=readRecord(h.getRuntimePolicy().protocols)??{},f=protocolConfig(g,"gateway","server")??{},m=u.host??configString(f.host)??i,d=p(u.port,"--port")??p(process.env.STABLE_HARNESS_PORT,"STABLE_HARNESS_PORT")??p(process.env.STABLE_HARNESS_GATEWAY_PORT,"STABLE_HARNESS_GATEWAY_PORT")??p(f.port,"protocols.gateway.port")??s,b=`http://${m}:${d}`,P=function gatewayBearerToken(t,o){return configString(t.bearerToken)??configString(t.apiKey)??o.apiKey}(f,u),v=await async function startGatewayTargets(t,o,s,p){const l={stable:await startHttpTarget("runtime",e(t),i)},h=await async function optionalOpenAiTarget(t,o,a){return enabled(protocolConfig(o,"openaiCompatible","openai-compatible","openai"))?await startHttpTarget("openai",r(t,{bearerToken:a}),i):void 0}(t,o,p),u=await async function optionalFacadeTarget(t,o,e,r){const n=["acp","a2a","agui"].filter(t=>enabled(protocolConfig(o,t)));return n.length>0?await startHttpTarget("facades",a(t,{baseUrl:`${e}/protocols`,bearerToken:r,enabledProtocols:n}),i):void 0}(t,o,s,p),g=await async function optionalLangGraphTarget(t,o){return enabled(protocolConfig(o,"langgraph"))?await async function startLangGraphTarget(t,o){const a=protocolConfig(o,"langgraph")??{},e=await n(t,{host:configString(a.host)??i,port:0,nWorkers:(r=a.nWorkers,("number"==typeof r&&Number.isFinite(r)?r:"string"==typeof r&&r.trim()?Number(r):void 0)??c),...configStringArray(a.exposeAgents)?{exposeAgents:configStringArray(a.exposeAgents)}:{},...void 0!==a.env?{env:a.env}:{},...void 0!==a.envFile?{envFile:a.envFile}:{}});var r;return{name:"langgraph",baseUrl:e.url,cleanup:e.cleanup}}(t,o):void 0}(t,o);return h&&(l.openai=h),u&&(l.facades=u),g&&(l.langgraph=g),l}(h,g,b,P),y=t((t,a)=>{"OPTIONS"!==t.method?function isAuthorized(t,o){return!o||t.headers.authorization===`Bearer ${o}`}(t,P)?function handleGatewayRoute(t,o,a,e){if("GET"===o.method&&"/health"===o.url)return sendJson(a,200,{ok:!0,product:"stable-harness"}),!0;const r=new URL(o.url??"/","http://stable-harness.local").pathname;if("GET"===o.method&&("/studio"===r||"/stable-harness-studio"===r))return function sendHtml(t,o,a){t.writeHead(o,{"content-type":"text/html; charset=utf-8","access-control-allow-origin":"*","access-control-allow-methods":"GET, POST, DELETE, OPTIONS","access-control-allow-headers":"authorization, content-type"}),t.end(a)}(a,200,l(e.baseUrl)),!0;if("GET"===o.method&&"/ready"===o.url)return sendJson(a,200,{ok:!0,targets:Object.keys(e.targets).sort()}),!0;if("GET"===o.method&&"/version"===o.url)return sendJson(a,200,function versionBody(){return{product:"stable-harness",version:stableHarnessVersion(),apiVersion:"2026-05-22"}}()),!0;if("GET"===o.method&&"/manifest"===o.url)return sendJson(a,200,function manifestBody(t,o){return{product:"stable-harness",version:stableHarnessVersion(),apiVersion:"2026-05-22",baseUrl:o,runtime:{basePath:"/runtime/v1",apiVersion:"v1",capabilities:runtimeCapabilities(t)},protocols:{openai:{basePath:"/protocols/openai/v1",pathVersion:"v1",compatibility:"openai-compatible"},langgraph:{basePath:"/protocols/langgraph",compatibility:"langsmith-agent-server",features:["assistants","threads","runs","store","mcp","a2a"],limitations:["crons-upstream-unavailable"]},mcp:{basePath:"/protocols/mcp",protocolVersion:"2024-11-05",transport:"streamable-http"},a2a:{basePath:"/protocols/a2a",protocolVersion:"1.0"},acp:{basePath:"/protocols/acp"},agui:{basePath:"/protocols/ag-ui"}}}}(t,e.baseUrl)),!0;if("GET"===o.method&&"/protocols"===o.url)return sendJson(a,200,{basePath:"/protocols",protocols:{openai:{basePath:"/protocols/openai/v1",pathVersion:"v1",compatibility:"openai-compatible"},langgraph:{basePath:"/protocols/langgraph",compatibility:"langsmith-agent-server",features:["assistants","threads","runs","store","mcp","a2a"],limitations:["crons-upstream-unavailable"]},mcp:{basePath:"/protocols/mcp",protocolVersion:"2024-11-05",transport:"streamable-http"},a2a:{basePath:"/protocols/a2a",protocolVersion:"1.0"},acp:{basePath:"/protocols/acp"},agui:{basePath:"/protocols/ag-ui"}}}),!0;const n=function protocolVersionRoute(t){const o=new URL(t.url??"/","http://stable-harness.local").pathname.match(/^\/protocols\/(openai|langgraph|mcp|a2a|acp|ag-ui)\/version$/u);if(!o)return;const a={openai:{basePath:"/protocols/openai/v1",pathVersion:"v1",compatibility:"openai-compatible"},langgraph:{basePath:"/protocols/langgraph",compatibility:"langsmith-agent-server",features:["assistants","threads","runs","store","mcp","a2a"],limitations:["crons-upstream-unavailable"]},mcp:{basePath:"/protocols/mcp",protocolVersion:"2024-11-05",transport:"streamable-http"},a2a:{basePath:"/protocols/a2a",protocolVersion:"1.0"},acp:{basePath:"/protocols/acp"},agui:{basePath:"/protocols/ag-ui"}}["ag-ui"===o[1]?"agui":o[1]];return{id:o[1],...a}}(o);return!("GET"!==o.method||!n)&&(sendJson(a,200,n),!0)}(h,t,a,{baseUrl:b,targets:v})||function proxyGatewayRoute(t,a,e){const r=function resolveGatewayProxy(t){const o=new URL(t??"/","http://stable-harness.local");return isPathOrChild(o.pathname,"/runtime/v1")?{target:"stable",path:stripPrefix(o,"/runtime/v1")}:isPathOrChild(o.pathname,"/protocols/openai/v1")?{target:"openai",path:`/v1${stripPrefix(o,"/protocols/openai/v1")}`}:isPathOrChild(o.pathname,"/protocols/acp")?{target:"facades",path:`/acp${stripProtocolPrefix(o,"/protocols/acp")}`}:isPathOrChild(o.pathname,"/protocols/a2a")?{target:"facades",path:`/a2a${stripProtocolPrefix(o,"/protocols/a2a")}`}:isPathOrChild(o.pathname,"/protocols/ag-ui")?{target:"facades",path:`/ag-ui${stripProtocolPrefix(o,"/protocols/ag-ui")}`}:isPathOrChild(o.pathname,"/protocols/langgraph")?{target:"langgraph",path:stripPrefix(o,"/protocols/langgraph")}:isPathOrChild(o.pathname,"/protocols/mcp")?{target:"langgraph",path:`/mcp${stripProtocolPrefix(o,"/protocols/mcp")}`}:void 0}(t.url);if(!r)return void sendJson(a,404,{error:"not_found"});const n=e[r.target];n?function proxyRequest(t,a,e,r){const n=new URL(r,e.baseUrl),s=o(n,{method:t.method,headers:{...t.headers,host:n.host}},t=>{a.writeHead(t.statusCode??502,{...t.headers,"access-control-allow-origin":"*","access-control-allow-methods":"GET, POST, DELETE, OPTIONS","access-control-allow-headers":"authorization, content-type"}),t.pipe(a)});s.on("error",t=>sendJson(a,502,{error:"bad_gateway",detail:t.message})),t.pipe(s)}(t,a,n,r.path):sendJson(a,404,{error:"protocol_not_enabled",protocol:r.target})}(t,a,v):sendJson(a,401,{error:"unauthorized"}):function sendCorsPreflight(t){t.writeHead(204,{"access-control-allow-origin":"*","access-control-allow-methods":"GET, POST, DELETE, OPTIONS","access-control-allow-headers":"authorization, content-type"}),t.end()}(a)});return{host:m,port:d,server:y,cleanup:async()=>async function closeTargets(t){await Promise.all(Object.values(t).map(t=>Promise.resolve(t.cleanup())))}(v)}}async function startHttpTarget(t,o,a){const e=await function listenOnRandomPort(t,o){return new Promise((a,e)=>{t.once("error",e),t.listen(0,o,()=>{t.off("error",e);const o=t.address();a("object"==typeof o&&o?o.port:0)})})}(o,a);return{name:t,baseUrl:`http://${a}:${e}`,cleanup:()=>function closeHttpServer(t){return new Promise((o,a)=>{t.closeAllConnections(),t.close(t=>t?a(t):o())})}(o)}}function isPathOrChild(t,o){return t===o||t.startsWith(`${o}/`)}function stripPrefix(t,o){return`${t.pathname.slice(o.length)||"/"}${t.search}`}function stripProtocolPrefix(t,o){return`${t.pathname.slice(o.length)}${t.search}`}function runtimeCapabilities(t){const o=t.inspect();return["runs","events","sessions","memory","approvals","artifacts","replay","workflows","trace","spans"].filter(t=>"workflows"!==t||o.workflows.length>0)}function stableHarnessVersion(){return process.env.STABLE_HARNESS_BUILD_VERSION??process.env.npm_package_version??"0.0.142"}function sendJson(t,o,a){t.writeHead(o,{"content-type":"application/json","access-control-allow-origin":"*","access-control-allow-methods":"GET, POST, DELETE, OPTIONS","access-control-allow-headers":"authorization, content-type"}),t.end(JSON.stringify(a))}function protocolConfig(t,...o){for(const a of o){const o=readRecord(t[a]);if(o)return o}}function enabled(t){return!1!==t?.enabled}function readRecord(t){return"object"!=typeof t||null===t||Array.isArray(t)?void 0:t}function configString(t){if("string"!=typeof t||!t.trim())return;const o=t.match(/^\$\{env:([A-Za-z_][A-Za-z0-9_]*)(?::-(.*))?\}$/u);return o?process.env[o[1]]??o[2]:t}function configStringArray(t){if(Array.isArray(t)&&t.every(t=>"string"==typeof t))return t.filter(t=>t.trim()).map(t=>t.trim())}
@@ -0,0 +1 @@
1
+ export declare function renderStudioHtml(baseUrl: string): string;
@@ -0,0 +1 @@
1
+ export function renderStudioHtml(n){return`<!doctype html>\n<html lang="en">\n<head>\n <meta charset="utf-8">\n <meta name="viewport" content="width=device-width, initial-scale=1">\n <title>Stable Harness Studio</title>\n <style>\n :root { color-scheme: light; --bg: #f7f8fa; --ink: #18202b; --muted: #667085; --line: #d8dee8; --panel: #ffffff; --accent: #0f766e; }\n * { box-sizing: border-box; }\n body { margin: 0; font: 14px/1.45 ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: var(--bg); color: var(--ink); }\n header { padding: 22px 28px 18px; border-bottom: 1px solid var(--line); background: #ffffff; }\n main { padding: 24px 28px 32px; max-width: 1180px; margin: 0 auto; }\n h1 { margin: 0 0 4px; font-size: 24px; font-weight: 680; letter-spacing: 0; }\n h2 { margin: 0 0 12px; font-size: 15px; font-weight: 680; letter-spacing: 0; }\n p { margin: 0; color: var(--muted); }\n a { color: var(--accent); text-decoration: none; }\n a:hover { text-decoration: underline; }\n .grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 16px; }\n .panel { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 16px; }\n .wide { grid-column: span 8; }\n .side { grid-column: span 4; }\n .full { grid-column: 1 / -1; }\n .metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }\n .metric { border: 1px solid var(--line); border-radius: 6px; padding: 12px; min-height: 72px; }\n .metric strong { display: block; font-size: 22px; line-height: 1.1; }\n .metric span, .label { color: var(--muted); font-size: 12px; }\n .links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }\n .link { border: 1px solid var(--line); border-radius: 6px; padding: 12px; min-height: 76px; overflow-wrap: anywhere; }\n .status { display: inline-flex; align-items: center; gap: 7px; color: #14532d; font-weight: 650; }\n .dot { width: 8px; height: 8px; border-radius: 50%; background: #16a34a; }\n table { width: 100%; border-collapse: collapse; }\n th, td { padding: 9px 8px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }\n th { color: var(--muted); font-size: 12px; font-weight: 650; }\n code { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 12px; }\n @media (max-width: 820px) { main, header { padding-left: 16px; padding-right: 16px; } .wide, .side { grid-column: 1 / -1; } .metrics, .links { grid-template-columns: 1fr; } }</style>\n</head>\n<body>\n <header>\n <h1>Stable Harness Studio</h1>\n <p>Runtime control plane for runs, protocols, traces, memory, approvals, artifacts, replay, and LangSmith-compatible access.</p>\n </header>\n <main class="grid">\n <section class="panel wide">\n <h2>Runtime</h2>\n <div class="metrics" id="metrics">${function loadingMetrics(){return["Agents","Runs","Sessions","Capabilities"].map(n=>`<div class="metric"><strong>-</strong><span>${n}</span></div>`).join("")}()}</div>\n </section>\n <section class="panel side">\n <h2>Gateway</h2>\n <p class="status"><span class="dot"></span><span id="status">Loading</span></p>\n <p style="margin-top:10px"><code id="gateway-url">${function escapeHtml(n){return n.replace(/[&<>"']/g,n=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[n]??n))}(n)}</code></p>\n </section>\n <section class="panel full">\n <h2>Studio Links</h2>\n <div class="links" id="links"></div>\n </section>\n <section class="panel full">\n <h2>Recent Runs</h2>\n <table>\n <thead><tr><th>Request</th><th>Agent</th><th>State</th><th>Started</th><th>Inspect</th></tr></thead>\n <tbody id="runs"><tr><td colspan="5" class="label">Loading</td></tr></tbody>\n </table>\n </section>\n </main>\n <script>${function studioScript(n){return`\n const embeddedBaseUrl = ${JSON.stringify(n)};\n const queryBaseUrl = new URLSearchParams(window.location.search).get("baseUrl");\n const baseUrl = normalizeBaseUrl(queryBaseUrl || embeddedBaseUrl || window.location.origin);\n document.getElementById("gateway-url").textContent = baseUrl;\n renderLinks();\n function normalizeBaseUrl(value) {\n return String(value || "").replace(/\\/+$/, "");\n }\n async function getJson(path) {\n const response = await fetch(baseUrl + path);\n if (!response.ok) throw new Error(path + " " + response.status);\n return response.json();\n }\n function esc(value) {\n return String(value ?? "").replace(/[&<>"']/g, (char) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[char]));\n }\n function metric(label, value) {\n return '<div class="metric"><strong>' + esc(value) + '</strong><span>' + esc(label) + '</span></div>';\n }\n function runRow(run) {\n const id = esc(run.requestId);\n return '<tr><td><code>' + id + '</code></td><td>' + esc(run.agentId) + '</td><td>' + esc(run.state) + '</td><td>' + esc(run.startedAt) + '</td><td><a href="' + baseUrl + '/runtime/v1/requests/' + id + '">request</a> · <a href="' + baseUrl + '/runtime/v1/runs/' + id + '/trace">trace</a> · <a href="' + baseUrl + '/runtime/v1/runs/' + id + '/spans">spans</a></td></tr>';\n }\n function renderLinks() {\n const links = [\n ["LangSmith Studio", "Open this workspace through the LangGraph-compatible Agent Server surface.", "https://smith.langchain.com/studio/?baseUrl=" + encodeURIComponent(baseUrl + "/protocols/langgraph")],\n ["LangGraph-compatible", "Assistants, threads, runs, store, MCP, A2A, and graph inspection.", baseUrl + "/protocols/langgraph"],\n ["Runtime API", "First-party Stable Harness control plane and SSE runtime surface.", baseUrl + "/runtime/v1"],\n ["Manifest", "Gateway version, runtime capabilities, protocols, and base paths.", baseUrl + "/manifest"],\n ["MCP", "Streamable HTTP MCP tool surface for workspace tools and exposed agents.", baseUrl + "/protocols/mcp"],\n ["AG-UI", "Run state, event stream, trace, spans, replay, approvals, and metrics.", baseUrl + "/protocols/ag-ui"]\n ];\n document.getElementById("links").innerHTML = links.map(([label, detail, href]) => '<div class="link"><a href="' + esc(href) + '">' + esc(label) + '</a><p>' + esc(detail) + '</p></div>').join("");\n }\n Promise.all([getJson("/manifest"), getJson("/runtime/v1/inspect")]).then(([manifest, inspect]) => {\n document.getElementById("status").textContent = manifest.product + " " + manifest.version;\n const runs = Array.isArray(inspect.runs) ? inspect.runs : [];\n document.getElementById("metrics").innerHTML = [\n metric("Agents", (inspect.agents || []).length),\n metric("Runs", runs.length),\n metric("Sessions", (inspect.sessions || []).length),\n metric("Capabilities", (manifest.runtime?.capabilities || []).length)\n ].join("");\n document.getElementById("runs").innerHTML = runs.length ? runs.slice(-12).reverse().map(runRow).join("") : '<tr><td colspan="5" class="label">No runs yet</td></tr>';\n }).catch((error) => {\n document.getElementById("status").textContent = "Unavailable";\n document.getElementById("runs").innerHTML = '<tr><td colspan="5">' + esc(error.message) + '</td></tr>';\n });\n `}(n)}<\/script>\n</body>\n</html>`}
@@ -1 +1 @@
1
- import{execFile as t}from"node:child_process";import{promisify as e}from"node:util";import{createGatewayServer as r}from"./server/gateway.js";import{defaultGatewayPort as n,defaultHost as s,readPort as o}from"./server/protocol-defaults.js";const a=e(t);export async function serveProtocol(t,e){const n=await async function createConfiguredServers(t,e){return[await r(t,e)]}(t,e),s=[];let o=0;for(const t of n){if(!await listen(t)){await t.cleanup(),process.stdout.write(`stable-harness gateway API already running on ${serverUrl(t)}\n`);continue}s.push(async()=>{await closeHttpServer(t.server),await t.cleanup()}),o+=1;const e=t.server.address(),r="object"==typeof e&&e?e.port:t.port;process.stdout.write(`stable-harness gateway API listening on ${serverUrl({...t,port:r})}\n`)}0!==o?await async function waitForShutdown(t){const e=setInterval(()=>{},864e5);await new Promise(r=>{const shutdown=()=>{clearInterval(e),Promise.allSettled(t.map(t=>t())).finally(()=>process.exit(0))};process.once("SIGINT",shutdown),process.once("SIGTERM",shutdown)})}(s):process.exit(0)}export async function stopProtocol(t,e){const r=[configuredGatewayTarget(t.runtime,e)],n=await Promise.all(r.map(async t=>({target:t,pids:await stableHarnessListenerPids(t.port)}))),s=[...new Set(n.flatMap(t=>t.pids))];for(const t of s)process.kill(t,"SIGTERM");for(const{target:t,pids:e}of n)0!==e.length?process.stdout.write(`stable-harness ${t.protocol} API stopped on ${t.host}:${t.port} pid=${e.join(",")}\n`):process.stdout.write(`stable-harness ${t.protocol} API not running on ${t.host}:${t.port}\n`)}function configuredGatewayTarget(t,e){const r=function protocolConfig(t,...e){for(const r of e){const e=readRecord(t[r]);if(e)return e}}(readRecord(t.protocols)??{},"gateway","server")??{};return{protocol:"gateway",host:e.host??function configString(t){if("string"!=typeof t||!t.trim())return;const e=t.match(/^\$\{env:([A-Za-z_][A-Za-z0-9_]*)(?::-(.*))?\}$/u);return e?process.env[e[1]]??e[2]:t}(r.host)??s,port:o(e.port,"--port")??o(process.env.STABLE_HARNESS_PORT,"STABLE_HARNESS_PORT")??o(process.env.STABLE_HARNESS_GATEWAY_PORT,"STABLE_HARNESS_GATEWAY_PORT")??o(r.port,"protocols.gateway.port")??n}}function readRecord(t){return"object"!=typeof t||null===t||Array.isArray(t)?void 0:t}async function listen(t){try{return await new Promise((e,r)=>{t.server.once("error",r),t.server.listen(t.port,t.host,()=>{t.server.off("error",r),e()})}),!0}catch(e){if(isAddressInUse(e)&&await async function isHttpServerAlreadyRunning(t){const e=await async function fetchJson(t,e={}){try{const r=await fetch(t,{headers:e});if(!r.ok)return;return await r.json()}catch{return}}(`http://${t.host}:${t.port}/health`);return!0===e?.ok&&"stable-harness"===e.product}(t))return!1;throw function portConflictError(t,e,r,n){return isAddressInUse(t)?new Error([`stable-harness ${e} port is already in use: ${r}:${n}.`,`Use --port <port>, update config/runtime/workspace.yaml, or stop the process currently listening on ${r}:${n}.`].join("\n")):t}(e,"gateway",t.host,t.port)}}function serverUrl(t){return`http://${t.host}:${t.port}`}function isAddressInUse(t){return"EADDRINUSE"===function readErrorCode(t){return"object"==typeof t&&null!==t&&"code"in t?t.code:void 0}(t)||String(t).includes("EADDRINUSE")}async function stableHarnessListenerPids(t){const e=await async function listenerPids(t){try{const{stdout:e}=await a("lsof",[`-tiTCP:${t}`,"-sTCP:LISTEN"]);return e.split(/\s+/u).map(t=>Number(t)).filter(t=>Number.isInteger(t)&&t>0)}catch{return[]}}(t);return(await Promise.all(e.map(async t=>{const e=await async function processCommand(t){try{const{stdout:e}=await a("ps",["-p",String(t),"-o","command="]);return e.trim()}catch{return""}}(t);return isStableHarnessStartCommand(e)?t:void 0}))).filter(t=>"number"==typeof t)}export function isStableHarnessStartCommand(t){if(function hasUnsafeCommandCharacters(t){return/[\u0000-\u001F\u007F;|`&<>]/u.test(t)}(t))return!1;const e=function splitCommandLine(t){const e=[];let r,n="";for(const s of t)'"'!==s&&"'"!==s||void 0!==r?s!==r?/\s/u.test(s)&&void 0===r?n&&(e.push(n),n=""):n+=s:r=void 0:r=s;return n&&e.push(n),e}(t),r=function stableHarnessCommandIndex(t){return isStableHarnessExecutableToken(t[0]??"")?0:function isNodeExecutableToken(t){const e=t.split(/[\\/]/u).at(-1);return"node"===e||"nodejs"===e}(t[0]??"")&&(isStableHarnessExecutableToken(t[1]??"")||function isStableHarnessScriptToken(t){if(hasTraversalSegment(t))return!1;const e=t.replaceAll("\\","/");return e.includes("/stable-harness/")&&e.endsWith("/packages/cli/dist/src/cli.js")}(t[1]??""))?1:-1}(e);return r>=0&&e.slice(r+1).includes("start")}function isStableHarnessExecutableToken(t){if(hasTraversalSegment(t))return!1;const e=t.split(/[\\/]/u).at(-1);return"stable-harness"===e||"botbotgo"===e}function hasTraversalSegment(t){return t.split(/[\\/]/u).some(t=>"."===t||".."===t)}async function closeHttpServer(t){await new Promise((e,r)=>{t.closeAllConnections(),t.close(t=>{t?r(t):e()})})}
1
+ import{execFile as t}from"node:child_process";import{promisify as e}from"node:util";import{createGatewayServer as r}from"./server/gateway.js";import{defaultGatewayPort as n,defaultHost as s,readPort as o}from"./server/protocol-defaults.js";const a=e(t);export async function serveProtocol(t,e){const n=await async function createConfiguredServers(t,e){return[await r(t,e)]}(t,e),s=[];let o=0;for(const t of n){const e=await listen(t),r=serverUrl(t);if(!e){await t.cleanup(),process.stdout.write(`stable-harness gateway API already running on ${r}\n${startupLinks(r)}`);continue}s.push(async()=>{await closeHttpServer(t.server),await t.cleanup()}),o+=1;const n=t.server.address(),a="object"==typeof n&&n?n.port:t.port,i=serverUrl({...t,port:a});process.stdout.write(`stable-harness gateway API listening on ${i}\n${startupLinks(i)}`)}0!==o?await async function waitForShutdown(t){const e=setInterval(()=>{},864e5);await new Promise(r=>{const shutdown=()=>{clearInterval(e),Promise.allSettled(t.map(t=>t())).finally(()=>process.exit(0))};process.once("SIGINT",shutdown),process.once("SIGTERM",shutdown)})}(s):process.exit(0)}export async function stopProtocol(t,e){const r=[configuredGatewayTarget(t.runtime,e)],n=await Promise.all(r.map(async t=>({target:t,pids:await stableHarnessListenerPids(t.port)}))),s=[...new Set(n.flatMap(t=>t.pids))];for(const t of s)process.kill(t,"SIGTERM");for(const{target:t,pids:e}of n)0!==e.length?process.stdout.write(`stable-harness ${t.protocol} API stopped on ${t.host}:${t.port} pid=${e.join(",")}\n`):process.stdout.write(`stable-harness ${t.protocol} API not running on ${t.host}:${t.port}\n`)}function configuredGatewayTarget(t,e){const r=function protocolConfig(t,...e){for(const r of e){const e=readRecord(t[r]);if(e)return e}}(readRecord(t.protocols)??{},"gateway","server")??{};return{protocol:"gateway",host:e.host??function configString(t){if("string"!=typeof t||!t.trim())return;const e=t.match(/^\$\{env:([A-Za-z_][A-Za-z0-9_]*)(?::-(.*))?\}$/u);return e?process.env[e[1]]??e[2]:t}(r.host)??s,port:o(e.port,"--port")??o(process.env.STABLE_HARNESS_PORT,"STABLE_HARNESS_PORT")??o(process.env.STABLE_HARNESS_GATEWAY_PORT,"STABLE_HARNESS_GATEWAY_PORT")??o(r.port,"protocols.gateway.port")??n}}function readRecord(t){return"object"!=typeof t||null===t||Array.isArray(t)?void 0:t}async function listen(t){try{return await new Promise((e,r)=>{t.server.once("error",r),t.server.listen(t.port,t.host,()=>{t.server.off("error",r),e()})}),!0}catch(e){if(isAddressInUse(e)&&await async function isHttpServerAlreadyRunning(t){const e=await async function fetchJson(t,e={}){try{const r=await fetch(t,{headers:e});if(!r.ok)return;return await r.json()}catch{return}}(`http://${t.host}:${t.port}/health`);return!0===e?.ok&&"stable-harness"===e.product}(t))return!1;throw function portConflictError(t,e,r,n){return isAddressInUse(t)?new Error([`stable-harness ${e} port is already in use: ${r}:${n}.`,`Use --port <port>, update config/runtime/workspace.yaml, or stop the process currently listening on ${r}:${n}.`].join("\n")):t}(e,"gateway",t.host,t.port)}}function serverUrl(t){return`http://${t.host}:${t.port}`}function startupLinks(t){return[`stable-harness-studio: ${stableHarnessStudioUrl(t)}`,`LangSmith Studio: ${langSmithStudioUrl(t)}`].join("\n")+"\n"}function stableHarnessStudioUrl(t){const e=process.env.STABLE_HARNESS_STUDIO_URL??"https://shs.easynet.world/",r=new URL(e);return r.searchParams.set("baseUrl",t),r.toString()}function langSmithStudioUrl(t){return`https://smith.langchain.com/studio/?baseUrl=${encodeURIComponent(`${t}/protocols/langgraph`)}`}function isAddressInUse(t){return"EADDRINUSE"===function readErrorCode(t){return"object"==typeof t&&null!==t&&"code"in t?t.code:void 0}(t)||String(t).includes("EADDRINUSE")}async function stableHarnessListenerPids(t){const e=await async function listenerPids(t){try{const{stdout:e}=await a("lsof",[`-tiTCP:${t}`,"-sTCP:LISTEN"]);return e.split(/\s+/u).map(t=>Number(t)).filter(t=>Number.isInteger(t)&&t>0)}catch{return[]}}(t);return(await Promise.all(e.map(async t=>{const e=await async function processCommand(t){try{const{stdout:e}=await a("ps",["-p",String(t),"-o","command="]);return e.trim()}catch{return""}}(t);return isStableHarnessStartCommand(e)?t:void 0}))).filter(t=>"number"==typeof t)}export function isStableHarnessStartCommand(t){if(function hasUnsafeCommandCharacters(t){return/[\u0000-\u001F\u007F;|`&<>]/u.test(t)}(t))return!1;const e=function splitCommandLine(t){const e=[];let r,n="";for(const s of t)'"'!==s&&"'"!==s||void 0!==r?s!==r?/\s/u.test(s)&&void 0===r?n&&(e.push(n),n=""):n+=s:r=void 0:r=s;return n&&e.push(n),e}(t),r=function stableHarnessCommandIndex(t){return isStableHarnessExecutableToken(t[0]??"")?0:function isNodeExecutableToken(t){const e=t.split(/[\\/]/u).at(-1);return"node"===e||"nodejs"===e}(t[0]??"")&&(isStableHarnessExecutableToken(t[1]??"")||function isStableHarnessScriptToken(t){if(hasTraversalSegment(t))return!1;const e=t.replaceAll("\\","/");return e.includes("/stable-harness/")&&e.endsWith("/packages/cli/dist/src/cli.js")}(t[1]??""))?1:-1}(e);return r>=0&&e.slice(r+1).includes("start")}function isStableHarnessExecutableToken(t){if(hasTraversalSegment(t))return!1;const e=t.split(/[\\/]/u).at(-1);return"stable-harness"===e||"botbotgo"===e}function hasTraversalSegment(t){return t.split(/[\\/]/u).some(t=>"."===t||".."===t)}async function closeHttpServer(t){await new Promise((e,r)=>{t.closeAllConnections(),t.close(t=>{t?r(t):e()})})}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/cli",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -15,12 +15,12 @@
15
15
  "types": "dist/src/index.d.ts",
16
16
  "peerDependencies": {
17
17
  "@langchain/langgraph-api": "^1.2.1",
18
- "@stable-harness/adapter-deepagents": "0.0.143",
19
- "@stable-harness/adapter-langgraph": "0.0.143",
20
- "@stable-harness/core": "0.0.143",
21
- "@stable-harness/memory": "0.0.143",
22
- "@stable-harness/protocols": "0.0.143",
23
- "@stable-harness/tool-gateway": "0.0.143",
24
- "@stable-harness/workspace-yaml": "0.0.143"
18
+ "@stable-harness/adapter-deepagents": "0.0.144",
19
+ "@stable-harness/adapter-langgraph": "0.0.144",
20
+ "@stable-harness/core": "0.0.144",
21
+ "@stable-harness/memory": "0.0.144",
22
+ "@stable-harness/protocols": "0.0.144",
23
+ "@stable-harness/tool-gateway": "0.0.144",
24
+ "@stable-harness/workspace-yaml": "0.0.144"
25
25
  }
26
26
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/core",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -12,7 +12,7 @@
12
12
  ".": "./dist/index.js"
13
13
  },
14
14
  "peerDependencies": {
15
- "@stable-harness/governance": "0.0.143",
16
- "@stable-harness/memory": "0.0.143"
15
+ "@stable-harness/governance": "0.0.144",
16
+ "@stable-harness/memory": "0.0.144"
17
17
  }
18
18
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/evaluation",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -11,6 +11,6 @@
11
11
  "main": "dist/src/index.js",
12
12
  "types": "dist/src/index.d.ts",
13
13
  "peerDependencies": {
14
- "@stable-harness/core": "0.0.143"
14
+ "@stable-harness/core": "0.0.144"
15
15
  }
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/governance",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/memory",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/protocols",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -11,6 +11,6 @@
11
11
  "main": "dist/src/index.js",
12
12
  "types": "dist/src/index.d.ts",
13
13
  "peerDependencies": {
14
- "@stable-harness/core": "0.0.143"
14
+ "@stable-harness/core": "0.0.144"
15
15
  }
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/tool-gateway",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/workspace-yaml",
3
- "version": "0.0.143",
3
+ "version": "0.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -12,6 +12,6 @@
12
12
  ".": "./dist/index.js"
13
13
  },
14
14
  "peerDependencies": {
15
- "@stable-harness/core": "0.0.143"
15
+ "@stable-harness/core": "0.0.144"
16
16
  }
17
17
  }