stable-harness 0.0.87 → 0.0.89

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.
Files changed (34) hide show
  1. package/README.md +1 -1
  2. package/docs/guides/integration-guide.md +11 -5
  3. package/docs/protocols/http-runtime.md +51 -3
  4. package/node_modules/@stable-harness/adapter-deepagents/package.json +2 -2
  5. package/node_modules/@stable-harness/adapter-langgraph/package.json +2 -2
  6. package/node_modules/@stable-harness/core/dist/quality/event-evidence.js +1 -1
  7. package/node_modules/@stable-harness/core/dist/quality/execution-review.js +1 -1
  8. package/node_modules/@stable-harness/core/dist/runtime/completion.js +1 -1
  9. package/node_modules/@stable-harness/core/package.json +3 -3
  10. package/node_modules/@stable-harness/governance/package.json +1 -1
  11. package/node_modules/@stable-harness/memory/package.json +1 -1
  12. package/node_modules/@stable-harness/protocols/dist/src/http-events.d.ts +16 -0
  13. package/node_modules/@stable-harness/protocols/dist/src/http-events.js +1 -0
  14. package/node_modules/@stable-harness/protocols/dist/src/http-server.js +1 -1
  15. package/node_modules/@stable-harness/protocols/package.json +2 -2
  16. package/node_modules/@stable-harness/tool-gateway/package.json +1 -1
  17. package/node_modules/@stable-harness/workspace-yaml/package.json +2 -2
  18. package/package.json +10 -10
  19. package/packages/adapter-deepagents/package.json +2 -2
  20. package/packages/adapter-langgraph/package.json +2 -2
  21. package/packages/cli/package.json +8 -8
  22. package/packages/core/dist/quality/event-evidence.js +1 -1
  23. package/packages/core/dist/quality/execution-review.js +1 -1
  24. package/packages/core/dist/runtime/completion.js +1 -1
  25. package/packages/core/package.json +3 -3
  26. package/packages/evaluation/package.json +2 -2
  27. package/packages/governance/package.json +1 -1
  28. package/packages/memory/package.json +1 -1
  29. package/packages/protocols/dist/src/http-events.d.ts +16 -0
  30. package/packages/protocols/dist/src/http-events.js +1 -0
  31. package/packages/protocols/dist/src/http-server.js +1 -1
  32. package/packages/protocols/package.json +2 -2
  33. package/packages/tool-gateway/package.json +1 -1
  34. 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
- ## HTTP Runtime Protocol
91
+ ## Stable Runtime HTTP + SSE
92
92
 
93
- Use the HTTP runtime protocol when the caller needs Stable Harness concepts
94
- directly: request IDs, sessions, traces, approvals, cancellation, and runtime
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
- See [HTTP runtime protocol](protocols/http-runtime.md).
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
- # HTTP Runtime Protocol
1
+ # Stable Runtime HTTP + SSE Protocol
2
2
 
3
- The native HTTP server exposes stable runtime state and request submission.
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.87",
3
+ "version": "0.0.89",
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.87",
18
+ "@stable-harness/core": "0.0.89",
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.87",
3
+ "version": "0.0.89",
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.87"
14
+ "@stable-harness/core": "0.0.89"
15
15
  }
16
16
  }
@@ -1 +1 @@
1
- export function hasPlanningEvidence(t){return t.some(t=>{const e=readAdapterEvent(t);return!!e&&("plan"===e.traceType||String(e.traceLabel??"").startsWith("plan.")||"write_todos"===e.toolId&&String(e.phase??"").startsWith("agent.tool."))})}export function successfulEvidenceToolIds(t){const e=t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return[t.toolId];const e=readAdapterEvent(t);return isToolResultEvent(e)&&"string"==typeof e.toolId&&isSuccessfulEvidenceEvent(e)?[e.toolId]:[]});return[...new Set(e)]}export function successfulEvidenceOutputs(t){return successfulEvidenceItems(t).map(t=>t.output)}export function successfulEvidenceItems(t){return t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return stringifyEvidence(t.output).map(e=>({source:t.toolId,output:e}));const e=readAdapterEvent(t),r=readToolSource(e);return isToolResultEvent(e)&&r?!isSuccessfulEvidenceEvent(e)||function isPlanningTool(t){return/^(?:write_todos|read_todos)$/u.test(t)}(r)?[]:stringifyEvidence(e.evidenceOutput??e.output).filter(t=>function isUsableEvidenceOutput(t,e){return"task"!==t||!function looksLikeUnexecutedToolIntent(t){const e=t.trim();return!(e.length>4e3)&&[/\b(?:I need to|I will|I'll|I am going to|I'm going to|Let me)\s+(?:call|use|run|invoke|get|fetch|check)\b[\s\S]{0,1200}\b(?:tool|function|system_time|web_search|url_text_fetch|task)\b/iu,/(?:我需要|我要|我会|我将|让我|我来|接下来我(?:会|将)?)\s*(?:先)?(?:调用|使用|运行|执行|检查|获取|查看)\b[\s\S]{0,1200}\b(?:工具|函数|system_time|web_search|url_text_fetch|task)\b/iu,/```(?:json)?\s*(?:system_time|web_search|url_text_fetch|task)\s*```/iu].some(t=>t.test(e))}(e)&&!function looksLikeDelegatedCommentary(t){const e=t.trim();return!(e.length>8e3)&&[/(?:这篇文章|this article)[\s\S]{0,1200}(?:我认为|我认同|打动我|值得深入探讨|特别认同|what I find|I think|I agree)/iu,/(?:你还有什么|还想深入探讨|would you like|do you want).{0,120}[??]\s*$/iu].some(t=>t.test(e))}(e)}(r,t)).map(t=>({source:r,output:t})):[]})}export function controlBlockers(t){const e=successfulEventIndexesBySource(t);return t.flatMap((t,r)=>{const n=readAdapterEvent(t),o=readControlStatus(n),s=readControlSource(n)??"tool";return o&&isBlockerStatus(o)?isResolvedByLaterCompletion(o)&&completedAfter(e,s,r)?[]:[`${s}:${o}`]:[]})}export function controlGaps(t){const e=new Set(successfulEvidenceItems(t).map(t=>t.source));return t.flatMap(t=>{const r=readAdapterEvent(t),n=readControlStatus(r),o=readControlSource(r)??"tool";return n&&isGapStatus(n)?e.has(o)&&isResolvedByLaterCompletion(n)?[]:[`${o}:${n}`]:[]})}export function omittedControlGaps(t,e){const r=successfulEventIndexesBySource(t),n=successfulEvidenceItems(t),o=function outputHasUnsupportedEvidenceClaims(t,e,r){const n=function evidenceCorpus(t,e){return[...e.map(t=>t.output),...t.flatMap(t=>"runtime.request.started"===t.type?[t.input??""]:[]),...t.flatMap(t=>"runtime.memory.recall.completed"===t.type?[t.context]:[])].join("\n")}(e,r).toLowerCase();return unsupportedTokens(t,n,/\b[A-Z][A-Z0-9]{1,12}-\d+\b/gu).length>0||unsupportedTokens(t,n,/\b[A-Za-z_$][A-Za-z0-9_$]*[A-Z][A-Za-z0-9_$]*\b/gu).filter(isCodeLikeIdentifier).length>=2}(e,t,n);return t.flatMap((t,s)=>{const u=readAdapterEvent(t),i=readControlStatus(u),a=readControlSource(u)??"tool";return i&&isGapStatus(i)?isResolvedByLaterCompletion(i)&&completedAfter(r,a,s)||!o&&function outputUsesPriorEvidence(t,e,r){const n=t.toLowerCase();return r.filter(t=>t.source===e).some(t=>{const e=t.output.trim();return!!e&&(!!n.includes(e.slice(0,500).toLowerCase())||function matchingEvidenceTokens(t,e){const r=new Set(["status","completed","success","recorded"]);return[...new Set(e.toLowerCase().match(/[a-z0-9][a-z0-9_.-]{1,}/gu)??[])].filter(t=>!r.has(t)).filter(e=>t.includes(e)).length}(n,e)>=2)})}(e,a,n)?[]:[`${a}:${i}`]:[]})}function stringifyEvidence(t){return"string"==typeof t?t.trim()?[t]:[]:null==t?[]:[JSON.stringify(t)]}function readAdapterEvent(t){if("runtime.adapter.event"===t.type&&isRecord(t.event))return t.event;const e=t;return isRecord(e)&&isToolResultEvent(e)?e:void 0}function isSuccessfulEvidenceEvent(t){const e=readEventStatus(t);return!e||/^(?:completed|success|ok|recorded)$/iu.test(e)}function isBlockerStatus(t){return/^(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input)$/iu.test(t)}function isGapStatus(t){return/^(?:dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)$/iu.test(t)}function isResolvedByLaterCompletion(t){return isGapStatus(t)||isBlockerStatus(t)}function successfulEventIndexesBySource(t){const e=new Map;return t.forEach((t,r)=>{const n=function successfulEventSource(t){if("runtime.tool.direct.completed"===t.type)return t.toolId;const e=readAdapterEvent(t),r=readToolSource(e);return isToolResultEvent(e)&&r&&isSuccessfulEvidenceEvent(e)?r:void 0}(t);n&&e.set(n,[...e.get(n)??[],r])}),e}function isToolResultEvent(t){return"deepagents.tool_execution.result"===t?.eventType||"agent.tool.result"===t?.phase||"agent.tool.result"===t?.type||"deepagents.tool_execution.result"===t?.type}function completedAfter(t,e,r){return(t.get(e)??[]).some(t=>t>r)}function unsupportedTokens(t,e,r){return[...new Set(t.match(r)??[])].filter(t=>!e.includes(t.toLowerCase()))}function isCodeLikeIdentifier(t){return!(t.length<8)&&(/(?:Service|Controller|Repository|Manager|Client|Resolver|Agent|Tool|Async)$/u.test(t)||/[a-z][A-Z]/u.test(t))}function readOutputStatus(t){if(isRecord(t)&&"string"==typeof t.status)return t.status;if("string"==typeof t){const e=parseJsonRecord(t);return"string"==typeof e?.status?e.status:t.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}}function parseJsonRecord(t){try{const e=JSON.parse(t);return isRecord(e)?e:void 0}catch{return}}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function readString(t){return"string"==typeof t&&t.trim()?t:void 0}function readEventStatus(t){return readString(t?.controlStatus)??readString(t?.status)??readOutputStatus(t?.output)}function readToolSource(t){return readString(t?.toolId)??readString(t?.toolName)??readString(t?.name)}function readControlStatus(t){const e=readEventStatus(t);return e&&isControlStatus(e)?e:findNestedControlStatus(t)}function readControlSource(t){return readToolSource(t)??findNestedToolSource(t)}function isControlStatus(t){return isGapStatus(t)||isBlockerStatus(t)}function findNestedControlStatus(t,e=0){if(e>5||null==t)return;if("string"==typeof t)return function readNestedStringStatus(t,e){const r=parseJsonRecord(t);if(r)return findNestedControlStatus(r,e+1);const n=t.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1];return n&&isControlStatus(n)?n:function readControlToken(t){const e=t.match(/\b(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input|dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)\b/iu)?.[0];return e&&isControlStatus(e)?e:void 0}(t)}(t,e);if(Array.isArray(t))return findFirstNested(t,t=>findNestedControlStatus(t,e+1));if(!isRecord(t))return;const r=readString(t.controlStatus)??readString(t.status);if(r&&isControlStatus(r))return r;const n=readOutputStatus(t.output);return n&&isControlStatus(n)?n:findFirstNested(Object.values(t),t=>findNestedControlStatus(t,e+1))}function findNestedToolSource(t,e=0){if(!(e>5||null==t)){if("string"==typeof t)return function readToolSourceFromText(t){const e=t.match(/["'](?:toolId|toolName|name)["']\s*:\s*["']([^"']+)["']/u)?.[1];return readString(e)}(t);if(Array.isArray(t))return findFirstNested(t,t=>findNestedToolSource(t,e+1));if(isRecord(t))return(readString(t.toolId)??readString(t.toolName)??readString(t.name))||findFirstNested(Object.values(t),t=>findNestedToolSource(t,e+1))}}function findFirstNested(t,e){for(const r of t){const t=e(r);if(void 0!==t)return t}}
1
+ export function hasPlanningEvidence(t){return t.some(t=>{const e=readAdapterEvent(t);return!!e&&("plan"===e.traceType||String(e.traceLabel??"").startsWith("plan.")||"write_todos"===e.toolId&&String(e.phase??"").startsWith("agent.tool."))})}export function successfulEvidenceToolIds(t){const e=t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return[t.toolId];const e=readAdapterEvent(t);return isToolResultEvent(e)&&"string"==typeof e.toolId&&isSuccessfulEvidenceEvent(e)?[e.toolId]:[]});return[...new Set(e)]}export function successfulEvidenceOutputs(t){return successfulEvidenceItems(t).map(t=>t.output)}export function successfulEvidenceItems(t){return t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return stringifyEvidence(t.output).map(e=>({source:t.toolId,output:e}));const e=readAdapterEvent(t),r=readToolSource(e);return isToolResultEvent(e)&&r?!isSuccessfulEvidenceEvent(e)||function isPlanningTool(t){return/^(?:write_todos|read_todos)$/u.test(t)}(r)?[]:stringifyEvidence(e.evidenceOutput??e.output).filter(t=>function isUsableEvidenceOutput(t,e){return"task"!==t||!function looksLikeUnexecutedToolIntent(t){const e=t.trim();return!(e.length>4e3)&&[/\b(?:I need to|I will|I'll|I am going to|I'm going to|Let me)\s+(?:call|use|run|invoke|get|fetch|check)\b[\s\S]{0,1200}\b(?:tool|function|system_time|web_search|url_text_fetch|task)\b/iu,/(?:我需要|我要|我会|我将|让我|我来|接下来我(?:会|将)?)\s*(?:先)?(?:调用|使用|运行|执行|检查|获取|查看)\b[\s\S]{0,1200}\b(?:工具|函数|system_time|web_search|url_text_fetch|task)\b/iu,/```(?:json)?\s*(?:system_time|web_search|url_text_fetch|task)\s*```/iu].some(t=>t.test(e))}(e)&&!function looksLikeDelegatedCommentary(t){const e=t.trim();return!(e.length>8e3)&&[/(?:这篇文章|this article)[\s\S]{0,1200}(?:我认为|我认同|打动我|值得深入探讨|特别认同|what I find|I think|I agree)/iu,/(?:你还有什么|还想深入探讨|would you like|do you want).{0,120}[??]\s*$/iu].some(t=>t.test(e))}(e)}(r,t)).map(t=>({source:r,output:t})):[]})}export function controlBlockers(t){const e=successfulEventIndexesBySource(t);return t.flatMap((t,r)=>{const n=readAdapterEvent(t),o=readControlStatus(n),s=readControlSource(n)??"tool";return o&&isBlockerStatus(o)?isResolvedByLaterCompletion(o)&&completedAfter(e,s,r)?[]:[`${s}:${o}`]:[]})}export function controlGaps(t){const e=new Set(successfulEvidenceItems(t).map(t=>t.source));return t.flatMap(t=>{const r=readAdapterEvent(t),n=readControlStatus(r),o=readControlSource(r)??"tool";return n&&isGapStatus(n)?e.has(o)&&isResolvedByLaterCompletion(n)?[]:[`${o}:${n}`]:[]})}export function omittedControlGaps(t,e){const r=successfulEventIndexesBySource(t),n=successfulEvidenceItems(t),o=function outputHasUnsupportedEvidenceClaims(t,e,r){const n=function evidenceCorpus(t,e){return[...e.map(t=>t.output),...t.flatMap(t=>"runtime.request.started"===t.type?[t.input??""]:[]),...t.flatMap(t=>"runtime.memory.recall.completed"===t.type?[t.context]:[])].join("\n")}(e,r).toLowerCase();return unsupportedTokens(t,n,/\b[A-Z][A-Z0-9]{1,12}-\d+\b/gu).length>0||unsupportedTokens(t,n,/\b[A-Za-z_$][A-Za-z0-9_$]*[A-Z][A-Za-z0-9_$]*\b/gu).filter(isCodeLikeIdentifier).length>=2}(e,t,n);return t.flatMap((t,s)=>{const u=readAdapterEvent(t),i=readControlStatus(u),a=readControlSource(u)??"tool";return i&&function isOmittedControlStatus(t){return isGapStatus(t)||isBlockerStatus(t)}(i)?isResolvedByLaterCompletion(i)&&completedAfter(r,a,s)||!o&&function outputUsesPriorEvidence(t,e,r){const n=t.toLowerCase();return r.filter(t=>t.source===e).some(t=>{const e=t.output.trim();return!!e&&(!!n.includes(e.slice(0,500).toLowerCase())||function matchingEvidenceTokens(t,e){const r=new Set(["status","completed","success","recorded"]);return[...new Set(e.toLowerCase().match(/[a-z0-9][a-z0-9_.-]{1,}/gu)??[])].filter(t=>!r.has(t)).filter(e=>t.includes(e)).length}(n,e)>=2)})}(e,a,n)?[]:[`${a}:${i}`]:[]})}function stringifyEvidence(t){return"string"==typeof t?t.trim()?[t]:[]:null==t?[]:[JSON.stringify(t)]}function readAdapterEvent(t){if("runtime.adapter.event"===t.type&&isRecord(t.event))return t.event;const e=t;return isRecord(e)&&isToolResultEvent(e)?e:void 0}function isSuccessfulEvidenceEvent(t){const e=readEventStatus(t);return!e||/^(?:completed|success|ok|recorded)$/iu.test(e)}function isBlockerStatus(t){return/^(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input|task_inventory_blocked)$/iu.test(t)}function isGapStatus(t){return/^(?:dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)$/iu.test(t)}function isResolvedByLaterCompletion(t){return isGapStatus(t)||isBlockerStatus(t)}function successfulEventIndexesBySource(t){const e=new Map;return t.forEach((t,r)=>{const n=function successfulEventSource(t){if("runtime.tool.direct.completed"===t.type)return t.toolId;const e=readAdapterEvent(t),r=readToolSource(e);return isToolResultEvent(e)&&r&&isSuccessfulEvidenceEvent(e)?r:void 0}(t);n&&e.set(n,[...e.get(n)??[],r])}),e}function isToolResultEvent(t){return"deepagents.tool_execution.result"===t?.eventType||"agent.tool.result"===t?.phase||"agent.tool.result"===t?.type||"deepagents.tool_execution.result"===t?.type}function completedAfter(t,e,r){return(t.get(e)??[]).some(t=>t>r)}function unsupportedTokens(t,e,r){return[...new Set(t.match(r)??[])].filter(t=>!e.includes(t.toLowerCase()))}function isCodeLikeIdentifier(t){return!(t.length<8)&&(/(?:Service|Controller|Repository|Manager|Client|Resolver|Agent|Tool|Async)$/u.test(t)||/[a-z][A-Z]/u.test(t))}function readOutputStatus(t){if(isRecord(t)&&"string"==typeof t.status)return t.status;if("string"==typeof t){const e=parseJsonRecord(t);return"string"==typeof e?.status?e.status:t.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}}function parseJsonRecord(t){try{const e=JSON.parse(t);return isRecord(e)?e:void 0}catch{return}}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function readString(t){return"string"==typeof t&&t.trim()?t:void 0}function readEventStatus(t){return readString(t?.controlStatus)??readString(t?.status)??readOutputStatus(t?.output)}function readToolSource(t){return readString(t?.toolId)??readString(t?.toolName)??readString(t?.name)}function readControlStatus(t){const e=function readInventoryRepairControlStatus(t){if("inventory.repair"===t?.phase&&"blocked"===t.status)return"task"===readInventoryRepairSource(t)?"task_inventory_blocked":"blocked"}(t);if(e)return e;const r=readEventStatus(t);return r&&isControlStatus(r)?r:findNestedControlStatus(t)}function readControlSource(t){return readToolSource(t)??readInventoryRepairSource(t)??findNestedToolSource(t)}function isControlStatus(t){return isGapStatus(t)||isBlockerStatus(t)}function findNestedControlStatus(t,e=0){if(e>5||null==t)return;if("string"==typeof t)return function readNestedStringStatus(t,e){const r=parseJsonRecord(t);if(r)return findNestedControlStatus(r,e+1);const n=t.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1];return n&&isControlStatus(n)?n:function readControlToken(t){const e=t.match(/\b(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input|task_inventory_blocked|dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)\b/iu)?.[0];return e&&isControlStatus(e)?e:void 0}(t)}(t,e);if(Array.isArray(t))return findFirstNested(t,t=>findNestedControlStatus(t,e+1));if(!isRecord(t))return;const r=readString(t.controlStatus)??readString(t.status);if(r&&isControlStatus(r))return r;const n=readOutputStatus(t.output);return n&&isControlStatus(n)?n:findFirstNested(Object.values(t),t=>findNestedControlStatus(t,e+1))}function findNestedToolSource(t,e=0){if(!(e>5||null==t)){if("string"==typeof t)return function readToolSourceFromText(t){const e=t.match(/["'](?:toolId|toolName|name)["']\s*:\s*["']([^"']+)["']/u)?.[1];return readString(e)}(t);if(Array.isArray(t))return findFirstNested(t,t=>findNestedToolSource(t,e+1));if(isRecord(t))return(readString(t.toolId)??readString(t.toolName)??readString(t.name))||findFirstNested(Object.values(t),t=>findNestedToolSource(t,e+1))}}function findFirstNested(t,e){for(const r of t){const t=e(r);if(void 0!==t)return t}}function readInventoryRepairSource(t){const e=isRecord(t?.diagnostic)?t.diagnostic:void 0;return readString(e?.layer)}
@@ -1 +1 @@
1
- import{controlBlockers as e,controlGaps as t,successfulEvidenceOutputs as n,successfulEvidenceToolIds as o}from"./event-evidence.js";const r=/(?<![\w.])(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?[%kKmMbBtTxX]?(?!\w)/gu;export const defaultExecutionEvaluatorRules=[function blockerIssues(t,n){return n.executionReview.stopOnBlocker?e(t.events).map(e=>({code:"control_blocker",message:`Execution produced a control blocker: ${e}`,recoverable:!1})):[]},function controlGapIssues(e,n){if(!n.executionReview.stopOnBlocker||!e.output?.text.trim())return[];const o=t(e.events).filter(t=>!function mentionsGap(e,t){const[n,o]=t.split(":"),r=e.toLowerCase();return r.includes(t.toLowerCase())||Boolean(n&&o&&r.includes(n.toLowerCase())&&r.includes(o.toLowerCase()))}(e.output?.text??"",t));return 0===o.length?[]:[{code:"unresolved_control_gap",message:`Final answer omitted unresolved runtime evidence gap(s): ${o.slice(0,8).join(", ")}`,recoverable:!0}]},function emptyFinalIssues(e,t){return!t.executionReview.rejectEmptyFinal||e.output?.text.trim()?[]:[{code:"empty_final_answer",message:"The final answer is empty.",recoverable:!0}]},function toolEvidenceIssues(e,t){return!t.executionReview.requireToolEvidence||o(e.events).length>0?[]:[{code:"missing_tool_evidence",message:"No successful tool or delegated-task evidence was observed.",recoverable:!0}]},function ungroundedNumberIssues(e,t){if(!t.executionReview.rejectUngroundedNumbers||!e.output?.text.trim())return[];const o=numberSet(n(e.events).join("\n"));if(0===o.size)return[];const r=[...numberSet(e.output.text)].filter(e=>!function isSupportedNumber(e,t){if(t.has(e))return!0;const n=Number.parseFloat(e);if(!Number.isFinite(n))return!1;for(const e of t){const t=Number.parseFloat(e);if(Number.isFinite(t)&&Math.abs(t-n)<=roundingTolerance(n))return!0}return!1}(e,o));return 0===r.length?[]:[{code:"ungrounded_numeric_claim",message:`Final answer contains numeric claims not found in successful tool evidence: ${r.slice(0,12).join(", ")}`,recoverable:!1}]}];export function reviewExecutionEvidence(e,t,n=defaultExecutionEvaluatorRules){if(!t.enabled||!t.executionReview.enabled)return{verdict:"pass",issues:[]};const o=evaluateExecutionRules(e,t,n);return 0===o.length?{verdict:"pass",issues:[]}:{verdict:o.some(e=>!e.recoverable)?"blocked":"continue_react",issues:o}}export function evaluateExecutionRules(e,t,n=defaultExecutionEvaluatorRules){return n.flatMap(n=>n(e,t))}function numberSet(e){const t=new Set;for(const n of e.matchAll(r)){const e=normalizeNumber(n[0]);e&&t.add(e)}return t}function normalizeNumber(e){const t=e.replace(/,/gu,"").replace(/^\+/u,"").replace(/[%kKmMbBtTxX]$/u,"").trim();if(t){if(/^\d+$/u.test(t)){const e=Number.parseInt(t,10);if(e>=1&&e<=20)return;return String(e)}return/^\d+\.\d+$/u.test(t)?t.replace(/0+$/u,"").replace(/\.$/u,""):void 0}}function roundingTolerance(e){return Math.abs(e)>=1e3?1:Math.abs(e)>=100?.1:Math.abs(e)>=10?.05:.005}
1
+ import{controlBlockers as e,controlGaps as t,successfulEvidenceOutputs as n,successfulEvidenceToolIds as o}from"./event-evidence.js";const r=/(?<![\w.])(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?[%kKmMbBtTxX]?(?!\w)/gu;export const defaultExecutionEvaluatorRules=[function blockerIssues(t,n){return n.executionReview.stopOnBlocker?e(t.events).map(e=>({code:"control_blocker",message:`Execution produced a control blocker: ${e}`,recoverable:!1})):[]},function controlGapIssues(e,n){if(!n.executionReview.stopOnBlocker||!e.output?.text.trim())return[];const o=t(e.events).filter(t=>!function mentionsGap(e,t){const[n,o]=t.split(":"),r=e.toLowerCase();return r.includes(t.toLowerCase())||function statusPhrases(e){if(!e)return[];const t=e.toLowerCase().replaceAll("_"," ");return"task_inventory_blocked"===e?[t,"workspace inventory","not in the workspace inventory"]:[t]}(o).some(e=>r.includes(e))||Boolean(n&&o&&r.includes(n.toLowerCase())&&r.includes(o.toLowerCase()))}(e.output?.text??"",t));return 0===o.length?[]:[{code:"unresolved_control_gap",message:`Final answer omitted unresolved runtime evidence gap(s): ${o.slice(0,8).join(", ")}`,recoverable:!0}]},function emptyFinalIssues(e,t){return!t.executionReview.rejectEmptyFinal||e.output?.text.trim()?[]:[{code:"empty_final_answer",message:"The final answer is empty.",recoverable:!0}]},function toolEvidenceIssues(e,t){return!t.executionReview.requireToolEvidence||o(e.events).length>0?[]:[{code:"missing_tool_evidence",message:"No successful tool or delegated-task evidence was observed.",recoverable:!0}]},function ungroundedNumberIssues(e,t){if(!t.executionReview.rejectUngroundedNumbers||!e.output?.text.trim())return[];const o=numberSet(n(e.events).join("\n"));if(0===o.size)return[];const r=[...numberSet(e.output.text)].filter(e=>!function isSupportedNumber(e,t){if(t.has(e))return!0;const n=Number.parseFloat(e);if(!Number.isFinite(n))return!1;for(const e of t){const t=Number.parseFloat(e);if(Number.isFinite(t)&&Math.abs(t-n)<=roundingTolerance(n))return!0}return!1}(e,o));return 0===r.length?[]:[{code:"ungrounded_numeric_claim",message:`Final answer contains numeric claims not found in successful tool evidence: ${r.slice(0,12).join(", ")}`,recoverable:!1}]}];export function reviewExecutionEvidence(e,t,n=defaultExecutionEvaluatorRules){if(!t.enabled||!t.executionReview.enabled)return{verdict:"pass",issues:[]};const o=evaluateExecutionRules(e,t,n);return 0===o.length?{verdict:"pass",issues:[]}:{verdict:o.some(e=>!e.recoverable)?"blocked":"continue_react",issues:o}}export function evaluateExecutionRules(e,t,n=defaultExecutionEvaluatorRules){return n.flatMap(n=>n(e,t))}function numberSet(e){const t=new Set;for(const n of e.matchAll(r)){const e=normalizeNumber(n[0]);e&&t.add(e)}return t}function normalizeNumber(e){const t=e.replace(/,/gu,"").replace(/^\+/u,"").replace(/[%kKmMbBtTxX]$/u,"").trim();if(t){if(/^\d+$/u.test(t)){const e=Number.parseInt(t,10);if(e>=1&&e<=20)return;return String(e)}return/^\d+\.\d+$/u.test(t)?t.replace(/0+$/u,"").replace(/\.$/u,""):void 0}}function roundingTolerance(e){return Math.abs(e)>=1e3?1:Math.abs(e)>=100?.1:Math.abs(e)>=10?.05:.005}
@@ -1 +1 @@
1
- import{omittedControlGaps as t}from"../quality/event-evidence.js";export function completeRun(e){const r=e.store.getRun(e.requestId);if("cancelled"===r?.state)return response(e,"cancelled",r.artifacts);!function assertDeliverableOutput(e,r){if(!e.text.trim())throw new Error("runtime_empty_output: Runtime request produced no user-facing output.");!function assertNoOmittedControlGaps(e,r){const s=t(r,e.text).filter(t=>!function mentionsGap(t,e){const[r,s]=e.split(":"),n=t.toLowerCase(),o=function statusPhrases(t){if(!t)return[];const e=t.toLowerCase().replaceAll("_"," ");return"repeated_tool_call_limit"===t?[e,"repeat limit"]:[e]}(s);return n.includes(e.toLowerCase())||Boolean(s&&n.includes(s.toLowerCase()))||o.some(t=>n.includes(t))||Boolean(r&&s&&n.includes(r.toLowerCase())&&n.includes(s.toLowerCase()))}(e.text,t));if(0!==s.length)throw new Error(`runtime_unresolved_control_gap: Runtime request produced unresolved control gap(s): ${s.slice(0,8).join(", ")}`)}(e,r)}(e.result,r?.events??[]);const s=(e.result.artifacts??[]).map(toPublicArtifact);r&&e.store.updateRun(e.requestId,{state:"completed",output:e.result.text,metadata:{...r.metadata,...e.result.metadata},artifacts:mergeArtifacts(r.artifacts,s),completedAt:(new Date).toISOString()});for(const t of e.result.artifacts??[])e.artifacts?.createArtifact({...t,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id});for(const t of s)e.emit({type:"runtime.artifact.created",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,artifact:t});return e.emit({type:"runtime.request.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,output:e.result.text}),response(e,"completed",e.store.getRun(e.requestId)?.artifacts)}export function failRun(t){const e=t.error instanceof Error?t.error.message:String(t.error);return t.store.getRun(t.requestId)&&t.store.updateRun(t.requestId,{state:"failed",error:e,completedAt:(new Date).toISOString()}),t.emit({type:"runtime.request.failed",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,error:e}),{requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,state:"failed",output:e}}function response(t,e,r){return{requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,state:e,output:t.result.text,metadata:t.result.metadata,artifacts:r??t.result.artifacts}}function mergeArtifacts(t,e){const r=new Map;for(const s of[...t??[],...e??[]])r.set(s.id,s);return[...r.values()]}function toPublicArtifact(t){return{id:t.id,kind:t.kind,...t.uri?{uri:t.uri}:{},...t.metadata?{metadata:t.metadata}:{}}}
1
+ import{omittedControlGaps as t}from"../quality/event-evidence.js";export function completeRun(e){const r=e.store.getRun(e.requestId);if("cancelled"===r?.state)return response(e,"cancelled",r.artifacts);!function assertDeliverableOutput(e,r){if(!e.text.trim())throw new Error("runtime_empty_output: Runtime request produced no user-facing output.");!function assertNoOmittedControlGaps(e,r){const s=t(r,e.text).filter(t=>!function mentionsGap(t,e){const[r,s]=e.split(":"),n=t.toLowerCase(),o=function statusPhrases(t){if(!t)return[];const e=t.toLowerCase().replaceAll("_"," ");return"task_inventory_blocked"===t?[e,"workspace inventory","not in the workspace inventory"]:"repeated_tool_call_limit"===t?[e,"repeat limit"]:[e]}(s);return n.includes(e.toLowerCase())||Boolean(s&&n.includes(s.toLowerCase()))||o.some(t=>n.includes(t))||Boolean(r&&s&&n.includes(r.toLowerCase())&&n.includes(s.toLowerCase()))}(e.text,t));if(0!==s.length)throw new Error(`runtime_unresolved_control_gap: Runtime request produced unresolved control gap(s): ${s.slice(0,8).join(", ")}`)}(e,r)}(e.result,r?.events??[]);const s=(e.result.artifacts??[]).map(toPublicArtifact);r&&e.store.updateRun(e.requestId,{state:"completed",output:e.result.text,metadata:{...r.metadata,...e.result.metadata},artifacts:mergeArtifacts(r.artifacts,s),completedAt:(new Date).toISOString()});for(const t of e.result.artifacts??[])e.artifacts?.createArtifact({...t,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id});for(const t of s)e.emit({type:"runtime.artifact.created",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,artifact:t});return e.emit({type:"runtime.request.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,output:e.result.text}),response(e,"completed",e.store.getRun(e.requestId)?.artifacts)}export function failRun(t){const e=t.error instanceof Error?t.error.message:String(t.error);return t.store.getRun(t.requestId)&&t.store.updateRun(t.requestId,{state:"failed",error:e,completedAt:(new Date).toISOString()}),t.emit({type:"runtime.request.failed",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,error:e}),{requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,state:"failed",output:e}}function response(t,e,r){return{requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,state:e,output:t.result.text,metadata:t.result.metadata,artifacts:r??t.result.artifacts}}function mergeArtifacts(t,e){const r=new Map;for(const s of[...t??[],...e??[]])r.set(s.id,s);return[...r.values()]}function toPublicArtifact(t){return{id:t.id,kind:t.kind,...t.uri?{uri:t.uri}:{},...t.metadata?{metadata:t.metadata}:{}}}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/core",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
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.87",
15
- "@stable-harness/memory": "0.0.87"
14
+ "@stable-harness/governance": "0.0.89",
15
+ "@stable-harness/memory": "0.0.89"
16
16
  }
17
17
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/governance",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist/**/*.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/memory",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist/**/*.js",
@@ -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 r,projectRuntimeTraceSpans as n,renderStableHarnessPrometheusMetrics as o,renderWorkflowMermaid as s}from"@stable-harness/core";export function createHttpServer(a){return e((e,d)=>{!async function handleHttpRequest(e,a,d){try{await async function routeHttpRequest(e,a,d){if("GET"===a.method&&"/health"===a.url)return void sendJson(d,200,{ok:!0});if("GET"===a.method&&"/metrics"===a.url)return void function sendText(e,t,r,n="text/plain; charset=utf-8"){e.writeHead(t,{"content-type":n}),e.end(r)}(d,200,o({runtime:e}),"text/plain; version=0.0.4; charset=utf-8");if("GET"===a.method&&"/inspect"===a.url)return void sendJson(d,200,e.inspect());if("GET"===a.method&&"/requests"===a.url)return void sendJson(d,200,e.listRequests());if(await async function handleAdministrationRoutes(e){const{runtime:t,request:r,response:n}=e;if("GET"===r.method&&"/sessions"===r.url)return sendJson(n,200,t.listSessions()),!0;const o=function readSessionDeleteId(e){const t=(e??"").match(/^\/sessions\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(r.url);if("DELETE"===r.method&&o)return sendJson(n,200,t.deleteSession(o)),!0;const s=function readRequestDeleteId(e){const t=(e??"").match(/^\/requests\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(r.url);if("DELETE"===r.method&&s)return sendJson(n,200,t.deleteRequest(s)),!0;if("GET"===r.method&&r.url?.startsWith("/memories"))return sendJson(n,200,await t.listMemories(function readMemoryList(e){const t=new URL(e??"/memories","http://stable-harness.local"),r=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")}:{},...r.length>0?{statuses:r}:{}}}(r.url))),!0;if("POST"===r.method&&"/memories"===r.url){const e=await readJson(r);return sendJson(n,200,await t.memorize(e)),!0}if("POST"===r.method&&"/memories/recall"===r.url){const e=await readJson(r);return sendJson(n,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}(r.url);if("POST"===r.method&&a){const e=await readJson(r);return sendJson(n,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}(r.url);return!("PATCH"!==r.method||!d||(sendJson(n,200,await t.updateMemory({id:d,...await readJson(r)})),0))}({runtime:e,request:a,response:d}))return;const i=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}(a.url);if("GET"===a.method&&i)return void sendJson(d,200,e.listArtifacts(i));const u=function readArtifactContentId(e){const t=(e??"").match(/^\/artifacts\/([^/]+)\/content$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&u){const t=e.getArtifact(u),r=e.readArtifact(u);return void sendJson(d,t&&void 0!==r?200:404,t&&void 0!==r?{artifact:t,content:r}:{error:"artifact_content_not_found"})}const c=function readArtifactId(e){const t=(e??"").match(/^\/artifacts\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&c){const t=e.getArtifact(c);return void sendJson(d,t?200:404,t??{error:"artifact_not_found"})}const f=function readApprovalList(e){if(!e?.startsWith("/approvals"))return;const t=new URL(e,"http://stable-harness.local");if("/approvals"!==t.pathname)return;const r=t.searchParams.get("status");return{status:"pending"===r||"approved"===r||"rejected"===r?r:void 0}}(a.url);if("GET"===a.method&&f)return void sendJson(d,200,await e.listApprovals(f.status));const m=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"}}(a.url);if("POST"===a.method&&m){const t=await e.resolveApproval(m.id,m.status);return void sendJson(d,t?200:404,t??{error:"approval_not_found"})}if("GET"===a.method&&"/workflows"===a.url)return void sendJson(d,200,e.inspect().workflows);const l=function readWorkflowMermaidId(e){const t=(e??"").match(/^\/workflows\/([^/]+)\/mermaid$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&l){const t=e.getWorkflow(l);return void sendJson(d,t?200:404,t?{mermaid:s(t)}:{error:"workflow_not_found"})}const p=function readWorkflowPlanId(e){const t=(e??"").match(/^\/workflows\/([^/]+)\/plan$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&p){const r=e.getWorkflow(p);return void sendJson(d,r?200:404,r?t(r):{error:"workflow_not_found"})}const h=function readRequestInspectionId(e){const t=(e??"").match(/^\/requests\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&h){const t=e.inspectRequest(h);return void sendJson(d,t?200:404,t??{error:"request_not_found"})}const v=function readTraceRequestId(e){const t=(e??"").match(/^\/runs\/([^/]+)\/trace$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&v){const t=e.getRun(v);return void sendJson(d,t?200:404,t?r(t):{error:"run_not_found"})}const I=function readSpanRequestId(e){const t=(e??"").match(/^\/runs\/([^/]+)\/spans$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&I){const t=e.getRun(I);return void sendJson(d,t?200:404,t?n(t):{error:"run_not_found"})}const w=function readReplayRequestId(e){const t=(e??"").match(/^\/requests\/([^/]+)\/replay$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&w){const t=e.exportReplayBundle(w);return void sendJson(d,t?200:404,t??{error:"run_not_found"})}if("POST"===a.method&&"/requests"===a.url){const t=await readJson(a);return void sendJson(d,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),r=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),n=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}:{},...r?{workflow:r}:{},...n?{memory:n}:{},...o?{metadata:o}:{}}}(t)))}sendJson(d,404,{error:"not_found"})}(e,a,d)}catch(e){sendJson(d,500,{error:e instanceof Error?e.message:String(e)})}}(a,e,d)})}function readRecord(e){return"object"!=typeof e||null===e||Array.isArray(e)?void 0:e}function sendJson(e,t,r){e.writeHead(t,{"content-type":"application/json"}),e.end(JSON.stringify(r))}async function readJson(e){const t=[];for await(const r of e)t.push(Buffer.isBuffer(r)?r:Buffer.from(r));return 0===t.length?{}:JSON.parse(Buffer.concat(t).toString("utf8"))}
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.87",
3
+ "version": "0.0.89",
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.87"
13
+ "@stable-harness/core": "0.0.89"
14
14
  }
15
15
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/tool-gateway",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist/**/*.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/workspace-yaml",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
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.87"
14
+ "@stable-harness/core": "0.0.89"
15
15
  }
16
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stable-harness",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
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.69",
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.87",
86
- "@stable-harness/adapter-langgraph": "0.0.87",
87
- "@stable-harness/core": "0.0.87",
88
- "@stable-harness/governance": "0.0.87",
89
- "@stable-harness/memory": "0.0.87",
90
- "@stable-harness/protocols": "0.0.87",
91
- "@stable-harness/tool-gateway": "0.0.87",
92
- "@stable-harness/workspace-yaml": "0.0.87",
85
+ "@stable-harness/adapter-deepagents": "0.0.89",
86
+ "@stable-harness/adapter-langgraph": "0.0.89",
87
+ "@stable-harness/core": "0.0.89",
88
+ "@stable-harness/governance": "0.0.89",
89
+ "@stable-harness/memory": "0.0.89",
90
+ "@stable-harness/protocols": "0.0.89",
91
+ "@stable-harness/tool-gateway": "0.0.89",
92
+ "@stable-harness/workspace-yaml": "0.0.89",
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.87",
3
+ "version": "0.0.89",
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.87",
18
+ "@stable-harness/core": "0.0.89",
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.87",
3
+ "version": "0.0.89",
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.87"
14
+ "@stable-harness/core": "0.0.89"
15
15
  }
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/cli",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
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.87",
18
- "@stable-harness/adapter-langgraph": "0.0.87",
19
- "@stable-harness/core": "0.0.87",
20
- "@stable-harness/memory": "0.0.87",
21
- "@stable-harness/protocols": "0.0.87",
22
- "@stable-harness/tool-gateway": "0.0.87",
23
- "@stable-harness/workspace-yaml": "0.0.87"
17
+ "@stable-harness/adapter-deepagents": "0.0.89",
18
+ "@stable-harness/adapter-langgraph": "0.0.89",
19
+ "@stable-harness/core": "0.0.89",
20
+ "@stable-harness/memory": "0.0.89",
21
+ "@stable-harness/protocols": "0.0.89",
22
+ "@stable-harness/tool-gateway": "0.0.89",
23
+ "@stable-harness/workspace-yaml": "0.0.89"
24
24
  }
25
25
  }
@@ -1 +1 @@
1
- export function hasPlanningEvidence(t){return t.some(t=>{const e=readAdapterEvent(t);return!!e&&("plan"===e.traceType||String(e.traceLabel??"").startsWith("plan.")||"write_todos"===e.toolId&&String(e.phase??"").startsWith("agent.tool."))})}export function successfulEvidenceToolIds(t){const e=t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return[t.toolId];const e=readAdapterEvent(t);return isToolResultEvent(e)&&"string"==typeof e.toolId&&isSuccessfulEvidenceEvent(e)?[e.toolId]:[]});return[...new Set(e)]}export function successfulEvidenceOutputs(t){return successfulEvidenceItems(t).map(t=>t.output)}export function successfulEvidenceItems(t){return t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return stringifyEvidence(t.output).map(e=>({source:t.toolId,output:e}));const e=readAdapterEvent(t),r=readToolSource(e);return isToolResultEvent(e)&&r?!isSuccessfulEvidenceEvent(e)||function isPlanningTool(t){return/^(?:write_todos|read_todos)$/u.test(t)}(r)?[]:stringifyEvidence(e.evidenceOutput??e.output).filter(t=>function isUsableEvidenceOutput(t,e){return"task"!==t||!function looksLikeUnexecutedToolIntent(t){const e=t.trim();return!(e.length>4e3)&&[/\b(?:I need to|I will|I'll|I am going to|I'm going to|Let me)\s+(?:call|use|run|invoke|get|fetch|check)\b[\s\S]{0,1200}\b(?:tool|function|system_time|web_search|url_text_fetch|task)\b/iu,/(?:我需要|我要|我会|我将|让我|我来|接下来我(?:会|将)?)\s*(?:先)?(?:调用|使用|运行|执行|检查|获取|查看)\b[\s\S]{0,1200}\b(?:工具|函数|system_time|web_search|url_text_fetch|task)\b/iu,/```(?:json)?\s*(?:system_time|web_search|url_text_fetch|task)\s*```/iu].some(t=>t.test(e))}(e)&&!function looksLikeDelegatedCommentary(t){const e=t.trim();return!(e.length>8e3)&&[/(?:这篇文章|this article)[\s\S]{0,1200}(?:我认为|我认同|打动我|值得深入探讨|特别认同|what I find|I think|I agree)/iu,/(?:你还有什么|还想深入探讨|would you like|do you want).{0,120}[??]\s*$/iu].some(t=>t.test(e))}(e)}(r,t)).map(t=>({source:r,output:t})):[]})}export function controlBlockers(t){const e=successfulEventIndexesBySource(t);return t.flatMap((t,r)=>{const n=readAdapterEvent(t),o=readControlStatus(n),s=readControlSource(n)??"tool";return o&&isBlockerStatus(o)?isResolvedByLaterCompletion(o)&&completedAfter(e,s,r)?[]:[`${s}:${o}`]:[]})}export function controlGaps(t){const e=new Set(successfulEvidenceItems(t).map(t=>t.source));return t.flatMap(t=>{const r=readAdapterEvent(t),n=readControlStatus(r),o=readControlSource(r)??"tool";return n&&isGapStatus(n)?e.has(o)&&isResolvedByLaterCompletion(n)?[]:[`${o}:${n}`]:[]})}export function omittedControlGaps(t,e){const r=successfulEventIndexesBySource(t),n=successfulEvidenceItems(t),o=function outputHasUnsupportedEvidenceClaims(t,e,r){const n=function evidenceCorpus(t,e){return[...e.map(t=>t.output),...t.flatMap(t=>"runtime.request.started"===t.type?[t.input??""]:[]),...t.flatMap(t=>"runtime.memory.recall.completed"===t.type?[t.context]:[])].join("\n")}(e,r).toLowerCase();return unsupportedTokens(t,n,/\b[A-Z][A-Z0-9]{1,12}-\d+\b/gu).length>0||unsupportedTokens(t,n,/\b[A-Za-z_$][A-Za-z0-9_$]*[A-Z][A-Za-z0-9_$]*\b/gu).filter(isCodeLikeIdentifier).length>=2}(e,t,n);return t.flatMap((t,s)=>{const u=readAdapterEvent(t),i=readControlStatus(u),a=readControlSource(u)??"tool";return i&&isGapStatus(i)?isResolvedByLaterCompletion(i)&&completedAfter(r,a,s)||!o&&function outputUsesPriorEvidence(t,e,r){const n=t.toLowerCase();return r.filter(t=>t.source===e).some(t=>{const e=t.output.trim();return!!e&&(!!n.includes(e.slice(0,500).toLowerCase())||function matchingEvidenceTokens(t,e){const r=new Set(["status","completed","success","recorded"]);return[...new Set(e.toLowerCase().match(/[a-z0-9][a-z0-9_.-]{1,}/gu)??[])].filter(t=>!r.has(t)).filter(e=>t.includes(e)).length}(n,e)>=2)})}(e,a,n)?[]:[`${a}:${i}`]:[]})}function stringifyEvidence(t){return"string"==typeof t?t.trim()?[t]:[]:null==t?[]:[JSON.stringify(t)]}function readAdapterEvent(t){if("runtime.adapter.event"===t.type&&isRecord(t.event))return t.event;const e=t;return isRecord(e)&&isToolResultEvent(e)?e:void 0}function isSuccessfulEvidenceEvent(t){const e=readEventStatus(t);return!e||/^(?:completed|success|ok|recorded)$/iu.test(e)}function isBlockerStatus(t){return/^(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input)$/iu.test(t)}function isGapStatus(t){return/^(?:dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)$/iu.test(t)}function isResolvedByLaterCompletion(t){return isGapStatus(t)||isBlockerStatus(t)}function successfulEventIndexesBySource(t){const e=new Map;return t.forEach((t,r)=>{const n=function successfulEventSource(t){if("runtime.tool.direct.completed"===t.type)return t.toolId;const e=readAdapterEvent(t),r=readToolSource(e);return isToolResultEvent(e)&&r&&isSuccessfulEvidenceEvent(e)?r:void 0}(t);n&&e.set(n,[...e.get(n)??[],r])}),e}function isToolResultEvent(t){return"deepagents.tool_execution.result"===t?.eventType||"agent.tool.result"===t?.phase||"agent.tool.result"===t?.type||"deepagents.tool_execution.result"===t?.type}function completedAfter(t,e,r){return(t.get(e)??[]).some(t=>t>r)}function unsupportedTokens(t,e,r){return[...new Set(t.match(r)??[])].filter(t=>!e.includes(t.toLowerCase()))}function isCodeLikeIdentifier(t){return!(t.length<8)&&(/(?:Service|Controller|Repository|Manager|Client|Resolver|Agent|Tool|Async)$/u.test(t)||/[a-z][A-Z]/u.test(t))}function readOutputStatus(t){if(isRecord(t)&&"string"==typeof t.status)return t.status;if("string"==typeof t){const e=parseJsonRecord(t);return"string"==typeof e?.status?e.status:t.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}}function parseJsonRecord(t){try{const e=JSON.parse(t);return isRecord(e)?e:void 0}catch{return}}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function readString(t){return"string"==typeof t&&t.trim()?t:void 0}function readEventStatus(t){return readString(t?.controlStatus)??readString(t?.status)??readOutputStatus(t?.output)}function readToolSource(t){return readString(t?.toolId)??readString(t?.toolName)??readString(t?.name)}function readControlStatus(t){const e=readEventStatus(t);return e&&isControlStatus(e)?e:findNestedControlStatus(t)}function readControlSource(t){return readToolSource(t)??findNestedToolSource(t)}function isControlStatus(t){return isGapStatus(t)||isBlockerStatus(t)}function findNestedControlStatus(t,e=0){if(e>5||null==t)return;if("string"==typeof t)return function readNestedStringStatus(t,e){const r=parseJsonRecord(t);if(r)return findNestedControlStatus(r,e+1);const n=t.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1];return n&&isControlStatus(n)?n:function readControlToken(t){const e=t.match(/\b(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input|dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)\b/iu)?.[0];return e&&isControlStatus(e)?e:void 0}(t)}(t,e);if(Array.isArray(t))return findFirstNested(t,t=>findNestedControlStatus(t,e+1));if(!isRecord(t))return;const r=readString(t.controlStatus)??readString(t.status);if(r&&isControlStatus(r))return r;const n=readOutputStatus(t.output);return n&&isControlStatus(n)?n:findFirstNested(Object.values(t),t=>findNestedControlStatus(t,e+1))}function findNestedToolSource(t,e=0){if(!(e>5||null==t)){if("string"==typeof t)return function readToolSourceFromText(t){const e=t.match(/["'](?:toolId|toolName|name)["']\s*:\s*["']([^"']+)["']/u)?.[1];return readString(e)}(t);if(Array.isArray(t))return findFirstNested(t,t=>findNestedToolSource(t,e+1));if(isRecord(t))return(readString(t.toolId)??readString(t.toolName)??readString(t.name))||findFirstNested(Object.values(t),t=>findNestedToolSource(t,e+1))}}function findFirstNested(t,e){for(const r of t){const t=e(r);if(void 0!==t)return t}}
1
+ export function hasPlanningEvidence(t){return t.some(t=>{const e=readAdapterEvent(t);return!!e&&("plan"===e.traceType||String(e.traceLabel??"").startsWith("plan.")||"write_todos"===e.toolId&&String(e.phase??"").startsWith("agent.tool."))})}export function successfulEvidenceToolIds(t){const e=t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return[t.toolId];const e=readAdapterEvent(t);return isToolResultEvent(e)&&"string"==typeof e.toolId&&isSuccessfulEvidenceEvent(e)?[e.toolId]:[]});return[...new Set(e)]}export function successfulEvidenceOutputs(t){return successfulEvidenceItems(t).map(t=>t.output)}export function successfulEvidenceItems(t){return t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return stringifyEvidence(t.output).map(e=>({source:t.toolId,output:e}));const e=readAdapterEvent(t),r=readToolSource(e);return isToolResultEvent(e)&&r?!isSuccessfulEvidenceEvent(e)||function isPlanningTool(t){return/^(?:write_todos|read_todos)$/u.test(t)}(r)?[]:stringifyEvidence(e.evidenceOutput??e.output).filter(t=>function isUsableEvidenceOutput(t,e){return"task"!==t||!function looksLikeUnexecutedToolIntent(t){const e=t.trim();return!(e.length>4e3)&&[/\b(?:I need to|I will|I'll|I am going to|I'm going to|Let me)\s+(?:call|use|run|invoke|get|fetch|check)\b[\s\S]{0,1200}\b(?:tool|function|system_time|web_search|url_text_fetch|task)\b/iu,/(?:我需要|我要|我会|我将|让我|我来|接下来我(?:会|将)?)\s*(?:先)?(?:调用|使用|运行|执行|检查|获取|查看)\b[\s\S]{0,1200}\b(?:工具|函数|system_time|web_search|url_text_fetch|task)\b/iu,/```(?:json)?\s*(?:system_time|web_search|url_text_fetch|task)\s*```/iu].some(t=>t.test(e))}(e)&&!function looksLikeDelegatedCommentary(t){const e=t.trim();return!(e.length>8e3)&&[/(?:这篇文章|this article)[\s\S]{0,1200}(?:我认为|我认同|打动我|值得深入探讨|特别认同|what I find|I think|I agree)/iu,/(?:你还有什么|还想深入探讨|would you like|do you want).{0,120}[??]\s*$/iu].some(t=>t.test(e))}(e)}(r,t)).map(t=>({source:r,output:t})):[]})}export function controlBlockers(t){const e=successfulEventIndexesBySource(t);return t.flatMap((t,r)=>{const n=readAdapterEvent(t),o=readControlStatus(n),s=readControlSource(n)??"tool";return o&&isBlockerStatus(o)?isResolvedByLaterCompletion(o)&&completedAfter(e,s,r)?[]:[`${s}:${o}`]:[]})}export function controlGaps(t){const e=new Set(successfulEvidenceItems(t).map(t=>t.source));return t.flatMap(t=>{const r=readAdapterEvent(t),n=readControlStatus(r),o=readControlSource(r)??"tool";return n&&isGapStatus(n)?e.has(o)&&isResolvedByLaterCompletion(n)?[]:[`${o}:${n}`]:[]})}export function omittedControlGaps(t,e){const r=successfulEventIndexesBySource(t),n=successfulEvidenceItems(t),o=function outputHasUnsupportedEvidenceClaims(t,e,r){const n=function evidenceCorpus(t,e){return[...e.map(t=>t.output),...t.flatMap(t=>"runtime.request.started"===t.type?[t.input??""]:[]),...t.flatMap(t=>"runtime.memory.recall.completed"===t.type?[t.context]:[])].join("\n")}(e,r).toLowerCase();return unsupportedTokens(t,n,/\b[A-Z][A-Z0-9]{1,12}-\d+\b/gu).length>0||unsupportedTokens(t,n,/\b[A-Za-z_$][A-Za-z0-9_$]*[A-Z][A-Za-z0-9_$]*\b/gu).filter(isCodeLikeIdentifier).length>=2}(e,t,n);return t.flatMap((t,s)=>{const u=readAdapterEvent(t),i=readControlStatus(u),a=readControlSource(u)??"tool";return i&&function isOmittedControlStatus(t){return isGapStatus(t)||isBlockerStatus(t)}(i)?isResolvedByLaterCompletion(i)&&completedAfter(r,a,s)||!o&&function outputUsesPriorEvidence(t,e,r){const n=t.toLowerCase();return r.filter(t=>t.source===e).some(t=>{const e=t.output.trim();return!!e&&(!!n.includes(e.slice(0,500).toLowerCase())||function matchingEvidenceTokens(t,e){const r=new Set(["status","completed","success","recorded"]);return[...new Set(e.toLowerCase().match(/[a-z0-9][a-z0-9_.-]{1,}/gu)??[])].filter(t=>!r.has(t)).filter(e=>t.includes(e)).length}(n,e)>=2)})}(e,a,n)?[]:[`${a}:${i}`]:[]})}function stringifyEvidence(t){return"string"==typeof t?t.trim()?[t]:[]:null==t?[]:[JSON.stringify(t)]}function readAdapterEvent(t){if("runtime.adapter.event"===t.type&&isRecord(t.event))return t.event;const e=t;return isRecord(e)&&isToolResultEvent(e)?e:void 0}function isSuccessfulEvidenceEvent(t){const e=readEventStatus(t);return!e||/^(?:completed|success|ok|recorded)$/iu.test(e)}function isBlockerStatus(t){return/^(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input|task_inventory_blocked)$/iu.test(t)}function isGapStatus(t){return/^(?:dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)$/iu.test(t)}function isResolvedByLaterCompletion(t){return isGapStatus(t)||isBlockerStatus(t)}function successfulEventIndexesBySource(t){const e=new Map;return t.forEach((t,r)=>{const n=function successfulEventSource(t){if("runtime.tool.direct.completed"===t.type)return t.toolId;const e=readAdapterEvent(t),r=readToolSource(e);return isToolResultEvent(e)&&r&&isSuccessfulEvidenceEvent(e)?r:void 0}(t);n&&e.set(n,[...e.get(n)??[],r])}),e}function isToolResultEvent(t){return"deepagents.tool_execution.result"===t?.eventType||"agent.tool.result"===t?.phase||"agent.tool.result"===t?.type||"deepagents.tool_execution.result"===t?.type}function completedAfter(t,e,r){return(t.get(e)??[]).some(t=>t>r)}function unsupportedTokens(t,e,r){return[...new Set(t.match(r)??[])].filter(t=>!e.includes(t.toLowerCase()))}function isCodeLikeIdentifier(t){return!(t.length<8)&&(/(?:Service|Controller|Repository|Manager|Client|Resolver|Agent|Tool|Async)$/u.test(t)||/[a-z][A-Z]/u.test(t))}function readOutputStatus(t){if(isRecord(t)&&"string"==typeof t.status)return t.status;if("string"==typeof t){const e=parseJsonRecord(t);return"string"==typeof e?.status?e.status:t.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}}function parseJsonRecord(t){try{const e=JSON.parse(t);return isRecord(e)?e:void 0}catch{return}}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function readString(t){return"string"==typeof t&&t.trim()?t:void 0}function readEventStatus(t){return readString(t?.controlStatus)??readString(t?.status)??readOutputStatus(t?.output)}function readToolSource(t){return readString(t?.toolId)??readString(t?.toolName)??readString(t?.name)}function readControlStatus(t){const e=function readInventoryRepairControlStatus(t){if("inventory.repair"===t?.phase&&"blocked"===t.status)return"task"===readInventoryRepairSource(t)?"task_inventory_blocked":"blocked"}(t);if(e)return e;const r=readEventStatus(t);return r&&isControlStatus(r)?r:findNestedControlStatus(t)}function readControlSource(t){return readToolSource(t)??readInventoryRepairSource(t)??findNestedToolSource(t)}function isControlStatus(t){return isGapStatus(t)||isBlockerStatus(t)}function findNestedControlStatus(t,e=0){if(e>5||null==t)return;if("string"==typeof t)return function readNestedStringStatus(t,e){const r=parseJsonRecord(t);if(r)return findNestedControlStatus(r,e+1);const n=t.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1];return n&&isControlStatus(n)?n:function readControlToken(t){const e=t.match(/\b(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input|task_inventory_blocked|dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)\b/iu)?.[0];return e&&isControlStatus(e)?e:void 0}(t)}(t,e);if(Array.isArray(t))return findFirstNested(t,t=>findNestedControlStatus(t,e+1));if(!isRecord(t))return;const r=readString(t.controlStatus)??readString(t.status);if(r&&isControlStatus(r))return r;const n=readOutputStatus(t.output);return n&&isControlStatus(n)?n:findFirstNested(Object.values(t),t=>findNestedControlStatus(t,e+1))}function findNestedToolSource(t,e=0){if(!(e>5||null==t)){if("string"==typeof t)return function readToolSourceFromText(t){const e=t.match(/["'](?:toolId|toolName|name)["']\s*:\s*["']([^"']+)["']/u)?.[1];return readString(e)}(t);if(Array.isArray(t))return findFirstNested(t,t=>findNestedToolSource(t,e+1));if(isRecord(t))return(readString(t.toolId)??readString(t.toolName)??readString(t.name))||findFirstNested(Object.values(t),t=>findNestedToolSource(t,e+1))}}function findFirstNested(t,e){for(const r of t){const t=e(r);if(void 0!==t)return t}}function readInventoryRepairSource(t){const e=isRecord(t?.diagnostic)?t.diagnostic:void 0;return readString(e?.layer)}
@@ -1 +1 @@
1
- import{controlBlockers as e,controlGaps as t,successfulEvidenceOutputs as n,successfulEvidenceToolIds as o}from"./event-evidence.js";const r=/(?<![\w.])(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?[%kKmMbBtTxX]?(?!\w)/gu;export const defaultExecutionEvaluatorRules=[function blockerIssues(t,n){return n.executionReview.stopOnBlocker?e(t.events).map(e=>({code:"control_blocker",message:`Execution produced a control blocker: ${e}`,recoverable:!1})):[]},function controlGapIssues(e,n){if(!n.executionReview.stopOnBlocker||!e.output?.text.trim())return[];const o=t(e.events).filter(t=>!function mentionsGap(e,t){const[n,o]=t.split(":"),r=e.toLowerCase();return r.includes(t.toLowerCase())||Boolean(n&&o&&r.includes(n.toLowerCase())&&r.includes(o.toLowerCase()))}(e.output?.text??"",t));return 0===o.length?[]:[{code:"unresolved_control_gap",message:`Final answer omitted unresolved runtime evidence gap(s): ${o.slice(0,8).join(", ")}`,recoverable:!0}]},function emptyFinalIssues(e,t){return!t.executionReview.rejectEmptyFinal||e.output?.text.trim()?[]:[{code:"empty_final_answer",message:"The final answer is empty.",recoverable:!0}]},function toolEvidenceIssues(e,t){return!t.executionReview.requireToolEvidence||o(e.events).length>0?[]:[{code:"missing_tool_evidence",message:"No successful tool or delegated-task evidence was observed.",recoverable:!0}]},function ungroundedNumberIssues(e,t){if(!t.executionReview.rejectUngroundedNumbers||!e.output?.text.trim())return[];const o=numberSet(n(e.events).join("\n"));if(0===o.size)return[];const r=[...numberSet(e.output.text)].filter(e=>!function isSupportedNumber(e,t){if(t.has(e))return!0;const n=Number.parseFloat(e);if(!Number.isFinite(n))return!1;for(const e of t){const t=Number.parseFloat(e);if(Number.isFinite(t)&&Math.abs(t-n)<=roundingTolerance(n))return!0}return!1}(e,o));return 0===r.length?[]:[{code:"ungrounded_numeric_claim",message:`Final answer contains numeric claims not found in successful tool evidence: ${r.slice(0,12).join(", ")}`,recoverable:!1}]}];export function reviewExecutionEvidence(e,t,n=defaultExecutionEvaluatorRules){if(!t.enabled||!t.executionReview.enabled)return{verdict:"pass",issues:[]};const o=evaluateExecutionRules(e,t,n);return 0===o.length?{verdict:"pass",issues:[]}:{verdict:o.some(e=>!e.recoverable)?"blocked":"continue_react",issues:o}}export function evaluateExecutionRules(e,t,n=defaultExecutionEvaluatorRules){return n.flatMap(n=>n(e,t))}function numberSet(e){const t=new Set;for(const n of e.matchAll(r)){const e=normalizeNumber(n[0]);e&&t.add(e)}return t}function normalizeNumber(e){const t=e.replace(/,/gu,"").replace(/^\+/u,"").replace(/[%kKmMbBtTxX]$/u,"").trim();if(t){if(/^\d+$/u.test(t)){const e=Number.parseInt(t,10);if(e>=1&&e<=20)return;return String(e)}return/^\d+\.\d+$/u.test(t)?t.replace(/0+$/u,"").replace(/\.$/u,""):void 0}}function roundingTolerance(e){return Math.abs(e)>=1e3?1:Math.abs(e)>=100?.1:Math.abs(e)>=10?.05:.005}
1
+ import{controlBlockers as e,controlGaps as t,successfulEvidenceOutputs as n,successfulEvidenceToolIds as o}from"./event-evidence.js";const r=/(?<![\w.])(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?[%kKmMbBtTxX]?(?!\w)/gu;export const defaultExecutionEvaluatorRules=[function blockerIssues(t,n){return n.executionReview.stopOnBlocker?e(t.events).map(e=>({code:"control_blocker",message:`Execution produced a control blocker: ${e}`,recoverable:!1})):[]},function controlGapIssues(e,n){if(!n.executionReview.stopOnBlocker||!e.output?.text.trim())return[];const o=t(e.events).filter(t=>!function mentionsGap(e,t){const[n,o]=t.split(":"),r=e.toLowerCase();return r.includes(t.toLowerCase())||function statusPhrases(e){if(!e)return[];const t=e.toLowerCase().replaceAll("_"," ");return"task_inventory_blocked"===e?[t,"workspace inventory","not in the workspace inventory"]:[t]}(o).some(e=>r.includes(e))||Boolean(n&&o&&r.includes(n.toLowerCase())&&r.includes(o.toLowerCase()))}(e.output?.text??"",t));return 0===o.length?[]:[{code:"unresolved_control_gap",message:`Final answer omitted unresolved runtime evidence gap(s): ${o.slice(0,8).join(", ")}`,recoverable:!0}]},function emptyFinalIssues(e,t){return!t.executionReview.rejectEmptyFinal||e.output?.text.trim()?[]:[{code:"empty_final_answer",message:"The final answer is empty.",recoverable:!0}]},function toolEvidenceIssues(e,t){return!t.executionReview.requireToolEvidence||o(e.events).length>0?[]:[{code:"missing_tool_evidence",message:"No successful tool or delegated-task evidence was observed.",recoverable:!0}]},function ungroundedNumberIssues(e,t){if(!t.executionReview.rejectUngroundedNumbers||!e.output?.text.trim())return[];const o=numberSet(n(e.events).join("\n"));if(0===o.size)return[];const r=[...numberSet(e.output.text)].filter(e=>!function isSupportedNumber(e,t){if(t.has(e))return!0;const n=Number.parseFloat(e);if(!Number.isFinite(n))return!1;for(const e of t){const t=Number.parseFloat(e);if(Number.isFinite(t)&&Math.abs(t-n)<=roundingTolerance(n))return!0}return!1}(e,o));return 0===r.length?[]:[{code:"ungrounded_numeric_claim",message:`Final answer contains numeric claims not found in successful tool evidence: ${r.slice(0,12).join(", ")}`,recoverable:!1}]}];export function reviewExecutionEvidence(e,t,n=defaultExecutionEvaluatorRules){if(!t.enabled||!t.executionReview.enabled)return{verdict:"pass",issues:[]};const o=evaluateExecutionRules(e,t,n);return 0===o.length?{verdict:"pass",issues:[]}:{verdict:o.some(e=>!e.recoverable)?"blocked":"continue_react",issues:o}}export function evaluateExecutionRules(e,t,n=defaultExecutionEvaluatorRules){return n.flatMap(n=>n(e,t))}function numberSet(e){const t=new Set;for(const n of e.matchAll(r)){const e=normalizeNumber(n[0]);e&&t.add(e)}return t}function normalizeNumber(e){const t=e.replace(/,/gu,"").replace(/^\+/u,"").replace(/[%kKmMbBtTxX]$/u,"").trim();if(t){if(/^\d+$/u.test(t)){const e=Number.parseInt(t,10);if(e>=1&&e<=20)return;return String(e)}return/^\d+\.\d+$/u.test(t)?t.replace(/0+$/u,"").replace(/\.$/u,""):void 0}}function roundingTolerance(e){return Math.abs(e)>=1e3?1:Math.abs(e)>=100?.1:Math.abs(e)>=10?.05:.005}
@@ -1 +1 @@
1
- import{omittedControlGaps as t}from"../quality/event-evidence.js";export function completeRun(e){const r=e.store.getRun(e.requestId);if("cancelled"===r?.state)return response(e,"cancelled",r.artifacts);!function assertDeliverableOutput(e,r){if(!e.text.trim())throw new Error("runtime_empty_output: Runtime request produced no user-facing output.");!function assertNoOmittedControlGaps(e,r){const s=t(r,e.text).filter(t=>!function mentionsGap(t,e){const[r,s]=e.split(":"),n=t.toLowerCase(),o=function statusPhrases(t){if(!t)return[];const e=t.toLowerCase().replaceAll("_"," ");return"repeated_tool_call_limit"===t?[e,"repeat limit"]:[e]}(s);return n.includes(e.toLowerCase())||Boolean(s&&n.includes(s.toLowerCase()))||o.some(t=>n.includes(t))||Boolean(r&&s&&n.includes(r.toLowerCase())&&n.includes(s.toLowerCase()))}(e.text,t));if(0!==s.length)throw new Error(`runtime_unresolved_control_gap: Runtime request produced unresolved control gap(s): ${s.slice(0,8).join(", ")}`)}(e,r)}(e.result,r?.events??[]);const s=(e.result.artifacts??[]).map(toPublicArtifact);r&&e.store.updateRun(e.requestId,{state:"completed",output:e.result.text,metadata:{...r.metadata,...e.result.metadata},artifacts:mergeArtifacts(r.artifacts,s),completedAt:(new Date).toISOString()});for(const t of e.result.artifacts??[])e.artifacts?.createArtifact({...t,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id});for(const t of s)e.emit({type:"runtime.artifact.created",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,artifact:t});return e.emit({type:"runtime.request.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,output:e.result.text}),response(e,"completed",e.store.getRun(e.requestId)?.artifacts)}export function failRun(t){const e=t.error instanceof Error?t.error.message:String(t.error);return t.store.getRun(t.requestId)&&t.store.updateRun(t.requestId,{state:"failed",error:e,completedAt:(new Date).toISOString()}),t.emit({type:"runtime.request.failed",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,error:e}),{requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,state:"failed",output:e}}function response(t,e,r){return{requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,state:e,output:t.result.text,metadata:t.result.metadata,artifacts:r??t.result.artifacts}}function mergeArtifacts(t,e){const r=new Map;for(const s of[...t??[],...e??[]])r.set(s.id,s);return[...r.values()]}function toPublicArtifact(t){return{id:t.id,kind:t.kind,...t.uri?{uri:t.uri}:{},...t.metadata?{metadata:t.metadata}:{}}}
1
+ import{omittedControlGaps as t}from"../quality/event-evidence.js";export function completeRun(e){const r=e.store.getRun(e.requestId);if("cancelled"===r?.state)return response(e,"cancelled",r.artifacts);!function assertDeliverableOutput(e,r){if(!e.text.trim())throw new Error("runtime_empty_output: Runtime request produced no user-facing output.");!function assertNoOmittedControlGaps(e,r){const s=t(r,e.text).filter(t=>!function mentionsGap(t,e){const[r,s]=e.split(":"),n=t.toLowerCase(),o=function statusPhrases(t){if(!t)return[];const e=t.toLowerCase().replaceAll("_"," ");return"task_inventory_blocked"===t?[e,"workspace inventory","not in the workspace inventory"]:"repeated_tool_call_limit"===t?[e,"repeat limit"]:[e]}(s);return n.includes(e.toLowerCase())||Boolean(s&&n.includes(s.toLowerCase()))||o.some(t=>n.includes(t))||Boolean(r&&s&&n.includes(r.toLowerCase())&&n.includes(s.toLowerCase()))}(e.text,t));if(0!==s.length)throw new Error(`runtime_unresolved_control_gap: Runtime request produced unresolved control gap(s): ${s.slice(0,8).join(", ")}`)}(e,r)}(e.result,r?.events??[]);const s=(e.result.artifacts??[]).map(toPublicArtifact);r&&e.store.updateRun(e.requestId,{state:"completed",output:e.result.text,metadata:{...r.metadata,...e.result.metadata},artifacts:mergeArtifacts(r.artifacts,s),completedAt:(new Date).toISOString()});for(const t of e.result.artifacts??[])e.artifacts?.createArtifact({...t,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id});for(const t of s)e.emit({type:"runtime.artifact.created",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,artifact:t});return e.emit({type:"runtime.request.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,output:e.result.text}),response(e,"completed",e.store.getRun(e.requestId)?.artifacts)}export function failRun(t){const e=t.error instanceof Error?t.error.message:String(t.error);return t.store.getRun(t.requestId)&&t.store.updateRun(t.requestId,{state:"failed",error:e,completedAt:(new Date).toISOString()}),t.emit({type:"runtime.request.failed",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,error:e}),{requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,state:"failed",output:e}}function response(t,e,r){return{requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,state:e,output:t.result.text,metadata:t.result.metadata,artifacts:r??t.result.artifacts}}function mergeArtifacts(t,e){const r=new Map;for(const s of[...t??[],...e??[]])r.set(s.id,s);return[...r.values()]}function toPublicArtifact(t){return{id:t.id,kind:t.kind,...t.uri?{uri:t.uri}:{},...t.metadata?{metadata:t.metadata}:{}}}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/core",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
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.87",
15
- "@stable-harness/memory": "0.0.87"
14
+ "@stable-harness/governance": "0.0.89",
15
+ "@stable-harness/memory": "0.0.89"
16
16
  }
17
17
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/evaluation",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
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.87"
13
+ "@stable-harness/core": "0.0.89"
14
14
  }
15
15
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/governance",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist/**/*.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/memory",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist/**/*.js",
@@ -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 r,projectRuntimeTraceSpans as n,renderStableHarnessPrometheusMetrics as o,renderWorkflowMermaid as s}from"@stable-harness/core";export function createHttpServer(a){return e((e,d)=>{!async function handleHttpRequest(e,a,d){try{await async function routeHttpRequest(e,a,d){if("GET"===a.method&&"/health"===a.url)return void sendJson(d,200,{ok:!0});if("GET"===a.method&&"/metrics"===a.url)return void function sendText(e,t,r,n="text/plain; charset=utf-8"){e.writeHead(t,{"content-type":n}),e.end(r)}(d,200,o({runtime:e}),"text/plain; version=0.0.4; charset=utf-8");if("GET"===a.method&&"/inspect"===a.url)return void sendJson(d,200,e.inspect());if("GET"===a.method&&"/requests"===a.url)return void sendJson(d,200,e.listRequests());if(await async function handleAdministrationRoutes(e){const{runtime:t,request:r,response:n}=e;if("GET"===r.method&&"/sessions"===r.url)return sendJson(n,200,t.listSessions()),!0;const o=function readSessionDeleteId(e){const t=(e??"").match(/^\/sessions\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(r.url);if("DELETE"===r.method&&o)return sendJson(n,200,t.deleteSession(o)),!0;const s=function readRequestDeleteId(e){const t=(e??"").match(/^\/requests\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(r.url);if("DELETE"===r.method&&s)return sendJson(n,200,t.deleteRequest(s)),!0;if("GET"===r.method&&r.url?.startsWith("/memories"))return sendJson(n,200,await t.listMemories(function readMemoryList(e){const t=new URL(e??"/memories","http://stable-harness.local"),r=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")}:{},...r.length>0?{statuses:r}:{}}}(r.url))),!0;if("POST"===r.method&&"/memories"===r.url){const e=await readJson(r);return sendJson(n,200,await t.memorize(e)),!0}if("POST"===r.method&&"/memories/recall"===r.url){const e=await readJson(r);return sendJson(n,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}(r.url);if("POST"===r.method&&a){const e=await readJson(r);return sendJson(n,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}(r.url);return!("PATCH"!==r.method||!d||(sendJson(n,200,await t.updateMemory({id:d,...await readJson(r)})),0))}({runtime:e,request:a,response:d}))return;const i=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}(a.url);if("GET"===a.method&&i)return void sendJson(d,200,e.listArtifacts(i));const u=function readArtifactContentId(e){const t=(e??"").match(/^\/artifacts\/([^/]+)\/content$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&u){const t=e.getArtifact(u),r=e.readArtifact(u);return void sendJson(d,t&&void 0!==r?200:404,t&&void 0!==r?{artifact:t,content:r}:{error:"artifact_content_not_found"})}const c=function readArtifactId(e){const t=(e??"").match(/^\/artifacts\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&c){const t=e.getArtifact(c);return void sendJson(d,t?200:404,t??{error:"artifact_not_found"})}const f=function readApprovalList(e){if(!e?.startsWith("/approvals"))return;const t=new URL(e,"http://stable-harness.local");if("/approvals"!==t.pathname)return;const r=t.searchParams.get("status");return{status:"pending"===r||"approved"===r||"rejected"===r?r:void 0}}(a.url);if("GET"===a.method&&f)return void sendJson(d,200,await e.listApprovals(f.status));const m=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"}}(a.url);if("POST"===a.method&&m){const t=await e.resolveApproval(m.id,m.status);return void sendJson(d,t?200:404,t??{error:"approval_not_found"})}if("GET"===a.method&&"/workflows"===a.url)return void sendJson(d,200,e.inspect().workflows);const l=function readWorkflowMermaidId(e){const t=(e??"").match(/^\/workflows\/([^/]+)\/mermaid$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&l){const t=e.getWorkflow(l);return void sendJson(d,t?200:404,t?{mermaid:s(t)}:{error:"workflow_not_found"})}const p=function readWorkflowPlanId(e){const t=(e??"").match(/^\/workflows\/([^/]+)\/plan$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&p){const r=e.getWorkflow(p);return void sendJson(d,r?200:404,r?t(r):{error:"workflow_not_found"})}const h=function readRequestInspectionId(e){const t=(e??"").match(/^\/requests\/([^/]+)$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&h){const t=e.inspectRequest(h);return void sendJson(d,t?200:404,t??{error:"request_not_found"})}const v=function readTraceRequestId(e){const t=(e??"").match(/^\/runs\/([^/]+)\/trace$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&v){const t=e.getRun(v);return void sendJson(d,t?200:404,t?r(t):{error:"run_not_found"})}const I=function readSpanRequestId(e){const t=(e??"").match(/^\/runs\/([^/]+)\/spans$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&I){const t=e.getRun(I);return void sendJson(d,t?200:404,t?n(t):{error:"run_not_found"})}const w=function readReplayRequestId(e){const t=(e??"").match(/^\/requests\/([^/]+)\/replay$/u);return t?.[1]?decodeURIComponent(t[1]):void 0}(a.url);if("GET"===a.method&&w){const t=e.exportReplayBundle(w);return void sendJson(d,t?200:404,t??{error:"run_not_found"})}if("POST"===a.method&&"/requests"===a.url){const t=await readJson(a);return void sendJson(d,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),r=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),n=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}:{},...r?{workflow:r}:{},...n?{memory:n}:{},...o?{metadata:o}:{}}}(t)))}sendJson(d,404,{error:"not_found"})}(e,a,d)}catch(e){sendJson(d,500,{error:e instanceof Error?e.message:String(e)})}}(a,e,d)})}function readRecord(e){return"object"!=typeof e||null===e||Array.isArray(e)?void 0:e}function sendJson(e,t,r){e.writeHead(t,{"content-type":"application/json"}),e.end(JSON.stringify(r))}async function readJson(e){const t=[];for await(const r of e)t.push(Buffer.isBuffer(r)?r:Buffer.from(r));return 0===t.length?{}:JSON.parse(Buffer.concat(t).toString("utf8"))}
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.87",
3
+ "version": "0.0.89",
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.87"
13
+ "@stable-harness/core": "0.0.89"
14
14
  }
15
15
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/tool-gateway",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist/**/*.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/workspace-yaml",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
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.87"
14
+ "@stable-harness/core": "0.0.89"
15
15
  }
16
16
  }