stable-harness 0.0.96 → 0.0.98

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/adapter-deepagents",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96",
18
+ "@stable-harness/core": "0.0.98",
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.96",
3
+ "version": "0.0.98",
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.96"
14
+ "@stable-harness/core": "0.0.98"
15
15
  }
16
16
  }
@@ -1,4 +1,4 @@
1
- import type { RuntimeRequest, RuntimeToolGateway, WorkspaceAgent } from "../types.js";
1
+ import type { RuntimeEvent, RuntimeRequest, RuntimeToolGateway, WorkspaceAgent } from "../types.js";
2
2
  import type { CompiledWorkspace } from "../workspace/types.js";
3
3
  export type RawArgsRecoveryInput = {
4
4
  request: RuntimeRequest;
@@ -6,6 +6,7 @@ export type RawArgsRecoveryInput = {
6
6
  agent: WorkspaceAgent;
7
7
  workspace: CompiledWorkspace;
8
8
  toolGateway?: RuntimeToolGateway;
9
+ events?: RuntimeEvent[];
9
10
  policy: unknown;
10
11
  };
11
12
  export declare function buildRawArgsRecoveryRequest(input: RawArgsRecoveryInput): RuntimeRequest | undefined;
@@ -1 +1 @@
1
- export function buildRawArgsRecoveryRequest(e){if(!toolCallRecoveryEnabled(e.policy))return;const t=findUniqueRawArgsTool(e);return t?{...e.request,input:[e.request.input,"","Stable runtime recovery: your previous final answer was a JSON argument object for a declared tool, not the final answer.",`Matched configured tool: ${t.toolId}`,"Continue the same user request by calling that tool through the backend's normal structured tool-calling mechanism with the JSON arguments below.","If the tool call succeeds, synthesize the final user-facing answer from the executed evidence.","Do not print JSON argument objects, raw tool-call markup, plans, or future-intent text as the final answer.","","Previous JSON arguments:",JSON.stringify(t.args)].join("\n"),metadata:{...e.request.metadata,stableHarnessRecovery:"tool_call"}}:void 0}export function hasUniqueRawArgsTool(e){return toolCallRecoveryEnabled(e.policy)&&Boolean(findUniqueRawArgsTool(e))}function findUniqueRawArgsTool(e){const t=function parseStandaloneJsonObject(e){const t=e.trim(),r=t.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/iu)?.[1]?.trim(),o=r??t;if(o.startsWith("{")&&o.endsWith("}")&&!(o.length>6e3))try{const e=JSON.parse(o);return isRecord(e)?e:void 0}catch{return}}(e.output);if(!t)return;const r=e.agent.tools.filter(r=>function schemaMatchesArgs(e,t){if(!isRecord(e)||"object"!==e.type||!isRecord(e.properties))return!1;if(function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}(e.required).some(e=>!(e in t)))return!1;const r=e.properties;return(!1!==e.additionalProperties||!Object.keys(t).some(e=>!(e in r)))&&Object.entries(t).every(([e,t])=>function propertyAcceptsValue(e,t){return!isRecord(e)||"string"!=typeof e.type||("string"===e.type?"string"==typeof t:"number"===e.type?"number"==typeof t:"integer"===e.type?Number.isInteger(t):"boolean"===e.type?"boolean"==typeof t:"array"===e.type?Array.isArray(t):"object"!==e.type||isRecord(t))}(r[e],t))}(e.workspace.tools.get(r)?.schema??e.toolGateway?.get(r)?.schema,t));return 1===r.length?{toolId:r[0],args:t}:void 0}function toolCallRecoveryEnabled(e){return!!(isRecord(e)&&isRecord(e.recovery)&&isRecord(e.recovery.toolCall))&&!0===e.recovery.toolCall.enabled}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
1
+ export function buildRawArgsRecoveryRequest(e){if(!toolCallRecoveryEnabled(e.policy))return;const t=findUniqueRawArgsTool(e);return t?{...e.request,input:[e.request.input,"","Stable runtime recovery: your previous final answer was a JSON argument object for a declared tool, not the final answer.",`Matched configured tool: ${t.toolId}`,"Continue the same user request by calling that tool through the backend's normal structured tool-calling mechanism with the JSON arguments below.","If the tool call succeeds, synthesize the final user-facing answer from the executed evidence.","Do not print JSON argument objects, raw tool-call markup, plans, or future-intent text as the final answer.","","Previous JSON arguments:",JSON.stringify(t.args)].join("\n"),metadata:{...e.request.metadata,stableHarnessRecovery:"tool_call"}}:void 0}export function hasUniqueRawArgsTool(e){return toolCallRecoveryEnabled(e.policy)&&Boolean(findUniqueRawArgsTool(e))}function findUniqueRawArgsTool(e){const t=function parseStandaloneJsonObject(e){const t=e.trim(),r=t.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/iu)?.[1]?.trim(),o=r??t;if(o.startsWith("{")&&o.endsWith("}")&&!(o.length>6e3))try{const e=JSON.parse(o);return!isRecord(e)||function isToolCallEnvelope(e){const t=["tool","tool_name","name","type","subagent_type"].some(t=>"string"==typeof e[t]),r=["args","arguments","parameters","kwargs"].some(t=>t in e);return t&&r}(e)||function isRuntimeControlObject(e){return"string"==typeof e.status||"string"==typeof e.error||"string"==typeof e.controlStatus}(e)?void 0:e}catch{return}}(e.output);if(!t)return;const r=e.agent.tools.filter(r=>function schemaMatchesArgs(e,t){if(!isRecord(e)||"object"!==e.type||!isRecord(e.properties))return!1;if(readStringArray(e.required).some(e=>!(e in t)))return!1;const r=e.properties;return(!1!==e.additionalProperties||!Object.keys(t).some(e=>!(e in r)))&&Object.entries(t).every(([e,t])=>function propertyAcceptsValue(e,t){return!isRecord(e)||"string"!=typeof e.type||("string"===e.type?"string"==typeof t:"number"===e.type?"number"==typeof t:"integer"===e.type?Number.isInteger(t):"boolean"===e.type?"boolean"==typeof t:"array"===e.type?Array.isArray(t):"object"!==e.type||isRecord(t))}(r[e],t))}(e.workspace.tools.get(r)?.schema??e.toolGateway?.get(r)?.schema,t));if(1===r.length)return{toolId:r[0],args:t};const o=function latestSingleToolCandidate(e,t){for(let r=(e?.length??0)-1;r>=0;r-=1){const o=e[r];if(!o||!("diagnostics"in o)||!isRecord(o.diagnostics))continue;const n=readStringArray(o.diagnostics.toolCandidateIds).filter(e=>t.has(e));if(1===n.length)return n[0];if(n.length>1)return}}(e.events,new Set(e.agent.tools));return o?{toolId:o,args:t}:void 0}function toolCallRecoveryEnabled(e){return!!(isRecord(e)&&isRecord(e.recovery)&&isRecord(e.recovery.toolCall))&&!0===e.recovery.toolCall.enabled}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
@@ -1 +1 @@
1
- import{assertNoDeclaredActionOmissionOutput as e}from"../../recovery/control-omission.js";import{buildRawArgsRecoveryRequest as t,hasUniqueRawArgsTool as o}from"../../recovery/raw-args.js";import{assertNoProgressOnlyToolIntentOutput as r,assertNoRawToolCallOutput as a,assertNoRawToolResultOutput as s,assertNoToolExecutionErrorOutput as l,buildEvidenceSynthesisOutput as i,buildResultRecoveryRequest as u,containsRawToolCallOutput as n,rawToolCallFailureMessage as c,rawToolCallOutputPreview as p,toolCallRecoveryEnabled as y}from"../../recovery/tool-call.js";export async function recoverAdapterResultOutput(d){let v=d.result,m=d.request;const g=function resultRecoveryAttempts(e){const t="object"!=typeof e||null===e||Array.isArray(e)?void 0:e.recovery,o="object"!=typeof t||null===t||Array.isArray(t)?void 0:t.toolCall,r="object"!=typeof o||null===o||Array.isArray(o)?void 0:o.maxResultRecoveryAttempts;return"number"==typeof r&&Number.isInteger(r)&&r>0?r:3}(d.recoveryPolicy);let R=!1;for(let e=0;;e+=1){const o=d.store.getRun(d.requestId)?.events??[],r=R?void 0:t({request:m,output:v.text,agent:d.agent,workspace:d.workspace,toolGateway:d.toolGateway,policy:d.recoveryPolicy}),a=e<g?u({request:m,output:v.text,events:o,availableToolIds:d.agent.tools,policy:d.recoveryPolicy}):void 0,s=r??a;if(!s)break;s===r&&(R=!0),m=s,emitRepair(d,"runtime.repair.started","result_output",e+1,"recoverable_result_output",void 0,repairDiagnostics(v.text,d.agent.tools)),v=await d.runAdapter(s),emitRepair(d,"runtime.repair.completed","result_output",e+1,"recoverable_result_output","retried",repairDiagnostics(v.text,d.agent.tools))}return function finalizeRecoveredOutput(t,u){if(!y(t.recoveryPolicy))return u;let d=!1;if(n(u.text,t.recoveryPolicy)&&function rawToolCallFailureReturnsMessage(e){return"message"===("object"!=typeof e?.toolCallRecovery||null===e.toolCallRecovery||Array.isArray(e.toolCallRecovery)?{}:e.toolCallRecovery).onFailure}(t.request.metadata)){const e=u.text;u={...u,text:c(),metadata:{...u.metadata,toolCallRecovery:{failed:!0,reason:"raw_tool_call_output"}}},emitRepair(t,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked",repairDiagnostics(e,t.agent.tools))}const v=i({request:t.request,output:u.text,events:t.store.getRun(t.requestId)?.events??[],policy:t.recoveryPolicy});return v&&(d=!0,u={...u,text:v,metadata:{...u.metadata,toolCallRecovery:{synthesized:!0,reason:"raw_tool_call_output_with_evidence"}}},emitRepair(t,"runtime.repair.completed","evidence_synthesis",void 0,"raw_tool_call_output_with_evidence","synthesized")),d||(n(u.text,t.recoveryPolicy)&&emitRepair(t,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked",repairDiagnostics(u.text,t.agent.tools)),a(u.text,t.recoveryPolicy),function assertNoRawArgsToolOutput(e,t){if(o({output:t,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,policy:e.recoveryPolicy}))throw new Error(`Adapter returned raw tool argument JSON as the final answer after recovery. The backend must execute the matching tool instead. Output preview: ${p(t)}`)}(t,u.text),r(u.text,t.agent.tools,t.recoveryPolicy),s(u.text,t.store.getRun(t.requestId)?.events??[],t.recoveryPolicy),l(u.text,t.recoveryPolicy),e({output:u.text,events:t.store.getRun(t.requestId)?.events??[],availableToolIds:t.agent.tools})),u}(d,v)}function emitRepair(e,t,o,r,a,s,l){const i={requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:o,attempt:r,reason:a,...l?{diagnostics:l}:{}};e.emit("runtime.repair.started"===t?{type:t,...i}:{type:t,...i,outcome:s??"retried"})}function repairDiagnostics(e,t){return{outputPreview:p(e),toolCandidateIds:visibleToolCandidates(e,t)}}function visibleToolCandidates(e,t){const o=new Set;for(const r of t??[])new RegExp(`(?:^|[^A-Za-z0-9_-])${escapeRegexp(r)}(?:$|[^A-Za-z0-9_-])`,"u").test(e)&&o.add(r);return[...o]}function escapeRegexp(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}
1
+ import{assertNoDeclaredActionOmissionOutput as e}from"../../recovery/control-omission.js";import{buildRawArgsRecoveryRequest as t,hasUniqueRawArgsTool as o}from"../../recovery/raw-args.js";import{assertNoProgressOnlyToolIntentOutput as r,assertNoRawToolCallOutput as a,assertNoRawToolResultOutput as s,assertNoToolExecutionErrorOutput as l,buildEvidenceSynthesisOutput as i,buildResultRecoveryRequest as u,containsRawToolCallOutput as n,rawToolCallFailureMessage as c,rawToolCallOutputPreview as p,toolCallRecoveryEnabled as y}from"../../recovery/tool-call.js";export async function recoverAdapterResultOutput(d){let v=d.result,m=d.request;const g=function resultRecoveryAttempts(e){const t="object"!=typeof e||null===e||Array.isArray(e)?void 0:e.recovery,o="object"!=typeof t||null===t||Array.isArray(t)?void 0:t.toolCall,r="object"!=typeof o||null===o||Array.isArray(o)?void 0:o.maxResultRecoveryAttempts;return"number"==typeof r&&Number.isInteger(r)&&r>0?r:3}(d.recoveryPolicy);let R=!1;for(let e=0;;e+=1){const o=d.store.getRun(d.requestId)?.events??[],r=R?void 0:t({request:m,output:v.text,agent:d.agent,workspace:d.workspace,toolGateway:d.toolGateway,events:o,policy:d.recoveryPolicy}),a=e<g?u({request:m,output:v.text,events:o,availableToolIds:d.agent.tools,policy:d.recoveryPolicy}):void 0,s=r??a;if(!s)break;s===r&&(R=!0),m=s,emitRepair(d,"runtime.repair.started","result_output",e+1,"recoverable_result_output",void 0,repairDiagnostics(v.text,d.agent.tools)),v=await d.runAdapter(s),emitRepair(d,"runtime.repair.completed","result_output",e+1,"recoverable_result_output","retried",repairDiagnostics(v.text,d.agent.tools))}return function finalizeRecoveredOutput(t,u){if(!y(t.recoveryPolicy))return u;let d=!1;if(n(u.text,t.recoveryPolicy)&&function rawToolCallFailureReturnsMessage(e){return"message"===("object"!=typeof e?.toolCallRecovery||null===e.toolCallRecovery||Array.isArray(e.toolCallRecovery)?{}:e.toolCallRecovery).onFailure}(t.request.metadata)){const e=u.text;u={...u,text:c(),metadata:{...u.metadata,toolCallRecovery:{failed:!0,reason:"raw_tool_call_output"}}},emitRepair(t,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked",repairDiagnostics(e,t.agent.tools))}const v=i({request:t.request,output:u.text,events:t.store.getRun(t.requestId)?.events??[],policy:t.recoveryPolicy});return v&&(d=!0,u={...u,text:v,metadata:{...u.metadata,toolCallRecovery:{synthesized:!0,reason:"raw_tool_call_output_with_evidence"}}},emitRepair(t,"runtime.repair.completed","evidence_synthesis",void 0,"raw_tool_call_output_with_evidence","synthesized")),d||(n(u.text,t.recoveryPolicy)&&emitRepair(t,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked",repairDiagnostics(u.text,t.agent.tools)),a(u.text,t.recoveryPolicy),function assertNoRawArgsToolOutput(e,t){if(o({output:t,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:e.store.getRun(e.requestId)?.events??[],policy:e.recoveryPolicy}))throw new Error(`Adapter returned raw tool argument JSON as the final answer after recovery. The backend must execute the matching tool instead. Output preview: ${p(t)}`)}(t,u.text),r(u.text,t.agent.tools,t.recoveryPolicy),s(u.text,t.store.getRun(t.requestId)?.events??[],t.recoveryPolicy),l(u.text,t.recoveryPolicy),e({output:u.text,events:t.store.getRun(t.requestId)?.events??[],availableToolIds:t.agent.tools})),u}(d,v)}function emitRepair(e,t,o,r,a,s,l){const i={requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:o,attempt:r,reason:a,...l?{diagnostics:l}:{}};e.emit("runtime.repair.started"===t?{type:t,...i}:{type:t,...i,outcome:s??"retried"})}function repairDiagnostics(e,t){return{outputPreview:p(e),toolCandidateIds:visibleToolCandidates(e,t)}}function visibleToolCandidates(e,t){const o=new Set;for(const r of t??[])new RegExp(`(?:^|[^A-Za-z0-9_-])${escapeRegexp(r)}(?:$|[^A-Za-z0-9_-])`,"u").test(e)&&o.add(r);return[...o]}function escapeRegexp(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/core",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96",
15
- "@stable-harness/memory": "0.0.96"
14
+ "@stable-harness/governance": "0.0.98",
15
+ "@stable-harness/memory": "0.0.98"
16
16
  }
17
17
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/governance",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96",
3
+ "version": "0.0.98",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist/**/*.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/protocols",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96"
13
+ "@stable-harness/core": "0.0.98"
14
14
  }
15
15
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/tool-gateway",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96",
3
+ "version": "0.0.98",
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.96"
14
+ "@stable-harness/core": "0.0.98"
15
15
  }
16
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stable-harness",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
4
4
  "type": "module",
5
5
  "description": "Stable application runtime and operator control plane for agent workspaces.",
6
6
  "license": "Apache-2.0",
@@ -82,14 +82,14 @@
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.96",
86
- "@stable-harness/adapter-langgraph": "0.0.96",
87
- "@stable-harness/core": "0.0.96",
88
- "@stable-harness/governance": "0.0.96",
89
- "@stable-harness/memory": "0.0.96",
90
- "@stable-harness/protocols": "0.0.96",
91
- "@stable-harness/tool-gateway": "0.0.96",
92
- "@stable-harness/workspace-yaml": "0.0.96",
85
+ "@stable-harness/adapter-deepagents": "0.0.98",
86
+ "@stable-harness/adapter-langgraph": "0.0.98",
87
+ "@stable-harness/core": "0.0.98",
88
+ "@stable-harness/governance": "0.0.98",
89
+ "@stable-harness/memory": "0.0.98",
90
+ "@stable-harness/protocols": "0.0.98",
91
+ "@stable-harness/tool-gateway": "0.0.98",
92
+ "@stable-harness/workspace-yaml": "0.0.98",
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.96",
3
+ "version": "0.0.98",
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.96",
18
+ "@stable-harness/core": "0.0.98",
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.96",
3
+ "version": "0.0.98",
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.96"
14
+ "@stable-harness/core": "0.0.98"
15
15
  }
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/cli",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96",
18
- "@stable-harness/adapter-langgraph": "0.0.96",
19
- "@stable-harness/core": "0.0.96",
20
- "@stable-harness/memory": "0.0.96",
21
- "@stable-harness/protocols": "0.0.96",
22
- "@stable-harness/tool-gateway": "0.0.96",
23
- "@stable-harness/workspace-yaml": "0.0.96"
17
+ "@stable-harness/adapter-deepagents": "0.0.98",
18
+ "@stable-harness/adapter-langgraph": "0.0.98",
19
+ "@stable-harness/core": "0.0.98",
20
+ "@stable-harness/memory": "0.0.98",
21
+ "@stable-harness/protocols": "0.0.98",
22
+ "@stable-harness/tool-gateway": "0.0.98",
23
+ "@stable-harness/workspace-yaml": "0.0.98"
24
24
  }
25
25
  }
@@ -1,4 +1,4 @@
1
- import type { RuntimeRequest, RuntimeToolGateway, WorkspaceAgent } from "../types.js";
1
+ import type { RuntimeEvent, RuntimeRequest, RuntimeToolGateway, WorkspaceAgent } from "../types.js";
2
2
  import type { CompiledWorkspace } from "../workspace/types.js";
3
3
  export type RawArgsRecoveryInput = {
4
4
  request: RuntimeRequest;
@@ -6,6 +6,7 @@ export type RawArgsRecoveryInput = {
6
6
  agent: WorkspaceAgent;
7
7
  workspace: CompiledWorkspace;
8
8
  toolGateway?: RuntimeToolGateway;
9
+ events?: RuntimeEvent[];
9
10
  policy: unknown;
10
11
  };
11
12
  export declare function buildRawArgsRecoveryRequest(input: RawArgsRecoveryInput): RuntimeRequest | undefined;
@@ -1 +1 @@
1
- export function buildRawArgsRecoveryRequest(e){if(!toolCallRecoveryEnabled(e.policy))return;const t=findUniqueRawArgsTool(e);return t?{...e.request,input:[e.request.input,"","Stable runtime recovery: your previous final answer was a JSON argument object for a declared tool, not the final answer.",`Matched configured tool: ${t.toolId}`,"Continue the same user request by calling that tool through the backend's normal structured tool-calling mechanism with the JSON arguments below.","If the tool call succeeds, synthesize the final user-facing answer from the executed evidence.","Do not print JSON argument objects, raw tool-call markup, plans, or future-intent text as the final answer.","","Previous JSON arguments:",JSON.stringify(t.args)].join("\n"),metadata:{...e.request.metadata,stableHarnessRecovery:"tool_call"}}:void 0}export function hasUniqueRawArgsTool(e){return toolCallRecoveryEnabled(e.policy)&&Boolean(findUniqueRawArgsTool(e))}function findUniqueRawArgsTool(e){const t=function parseStandaloneJsonObject(e){const t=e.trim(),r=t.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/iu)?.[1]?.trim(),o=r??t;if(o.startsWith("{")&&o.endsWith("}")&&!(o.length>6e3))try{const e=JSON.parse(o);return isRecord(e)?e:void 0}catch{return}}(e.output);if(!t)return;const r=e.agent.tools.filter(r=>function schemaMatchesArgs(e,t){if(!isRecord(e)||"object"!==e.type||!isRecord(e.properties))return!1;if(function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}(e.required).some(e=>!(e in t)))return!1;const r=e.properties;return(!1!==e.additionalProperties||!Object.keys(t).some(e=>!(e in r)))&&Object.entries(t).every(([e,t])=>function propertyAcceptsValue(e,t){return!isRecord(e)||"string"!=typeof e.type||("string"===e.type?"string"==typeof t:"number"===e.type?"number"==typeof t:"integer"===e.type?Number.isInteger(t):"boolean"===e.type?"boolean"==typeof t:"array"===e.type?Array.isArray(t):"object"!==e.type||isRecord(t))}(r[e],t))}(e.workspace.tools.get(r)?.schema??e.toolGateway?.get(r)?.schema,t));return 1===r.length?{toolId:r[0],args:t}:void 0}function toolCallRecoveryEnabled(e){return!!(isRecord(e)&&isRecord(e.recovery)&&isRecord(e.recovery.toolCall))&&!0===e.recovery.toolCall.enabled}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
1
+ export function buildRawArgsRecoveryRequest(e){if(!toolCallRecoveryEnabled(e.policy))return;const t=findUniqueRawArgsTool(e);return t?{...e.request,input:[e.request.input,"","Stable runtime recovery: your previous final answer was a JSON argument object for a declared tool, not the final answer.",`Matched configured tool: ${t.toolId}`,"Continue the same user request by calling that tool through the backend's normal structured tool-calling mechanism with the JSON arguments below.","If the tool call succeeds, synthesize the final user-facing answer from the executed evidence.","Do not print JSON argument objects, raw tool-call markup, plans, or future-intent text as the final answer.","","Previous JSON arguments:",JSON.stringify(t.args)].join("\n"),metadata:{...e.request.metadata,stableHarnessRecovery:"tool_call"}}:void 0}export function hasUniqueRawArgsTool(e){return toolCallRecoveryEnabled(e.policy)&&Boolean(findUniqueRawArgsTool(e))}function findUniqueRawArgsTool(e){const t=function parseStandaloneJsonObject(e){const t=e.trim(),r=t.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/iu)?.[1]?.trim(),o=r??t;if(o.startsWith("{")&&o.endsWith("}")&&!(o.length>6e3))try{const e=JSON.parse(o);return!isRecord(e)||function isToolCallEnvelope(e){const t=["tool","tool_name","name","type","subagent_type"].some(t=>"string"==typeof e[t]),r=["args","arguments","parameters","kwargs"].some(t=>t in e);return t&&r}(e)||function isRuntimeControlObject(e){return"string"==typeof e.status||"string"==typeof e.error||"string"==typeof e.controlStatus}(e)?void 0:e}catch{return}}(e.output);if(!t)return;const r=e.agent.tools.filter(r=>function schemaMatchesArgs(e,t){if(!isRecord(e)||"object"!==e.type||!isRecord(e.properties))return!1;if(readStringArray(e.required).some(e=>!(e in t)))return!1;const r=e.properties;return(!1!==e.additionalProperties||!Object.keys(t).some(e=>!(e in r)))&&Object.entries(t).every(([e,t])=>function propertyAcceptsValue(e,t){return!isRecord(e)||"string"!=typeof e.type||("string"===e.type?"string"==typeof t:"number"===e.type?"number"==typeof t:"integer"===e.type?Number.isInteger(t):"boolean"===e.type?"boolean"==typeof t:"array"===e.type?Array.isArray(t):"object"!==e.type||isRecord(t))}(r[e],t))}(e.workspace.tools.get(r)?.schema??e.toolGateway?.get(r)?.schema,t));if(1===r.length)return{toolId:r[0],args:t};const o=function latestSingleToolCandidate(e,t){for(let r=(e?.length??0)-1;r>=0;r-=1){const o=e[r];if(!o||!("diagnostics"in o)||!isRecord(o.diagnostics))continue;const n=readStringArray(o.diagnostics.toolCandidateIds).filter(e=>t.has(e));if(1===n.length)return n[0];if(n.length>1)return}}(e.events,new Set(e.agent.tools));return o?{toolId:o,args:t}:void 0}function toolCallRecoveryEnabled(e){return!!(isRecord(e)&&isRecord(e.recovery)&&isRecord(e.recovery.toolCall))&&!0===e.recovery.toolCall.enabled}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
@@ -1 +1 @@
1
- import{assertNoDeclaredActionOmissionOutput as e}from"../../recovery/control-omission.js";import{buildRawArgsRecoveryRequest as t,hasUniqueRawArgsTool as o}from"../../recovery/raw-args.js";import{assertNoProgressOnlyToolIntentOutput as r,assertNoRawToolCallOutput as a,assertNoRawToolResultOutput as s,assertNoToolExecutionErrorOutput as l,buildEvidenceSynthesisOutput as i,buildResultRecoveryRequest as u,containsRawToolCallOutput as n,rawToolCallFailureMessage as c,rawToolCallOutputPreview as p,toolCallRecoveryEnabled as y}from"../../recovery/tool-call.js";export async function recoverAdapterResultOutput(d){let v=d.result,m=d.request;const g=function resultRecoveryAttempts(e){const t="object"!=typeof e||null===e||Array.isArray(e)?void 0:e.recovery,o="object"!=typeof t||null===t||Array.isArray(t)?void 0:t.toolCall,r="object"!=typeof o||null===o||Array.isArray(o)?void 0:o.maxResultRecoveryAttempts;return"number"==typeof r&&Number.isInteger(r)&&r>0?r:3}(d.recoveryPolicy);let R=!1;for(let e=0;;e+=1){const o=d.store.getRun(d.requestId)?.events??[],r=R?void 0:t({request:m,output:v.text,agent:d.agent,workspace:d.workspace,toolGateway:d.toolGateway,policy:d.recoveryPolicy}),a=e<g?u({request:m,output:v.text,events:o,availableToolIds:d.agent.tools,policy:d.recoveryPolicy}):void 0,s=r??a;if(!s)break;s===r&&(R=!0),m=s,emitRepair(d,"runtime.repair.started","result_output",e+1,"recoverable_result_output",void 0,repairDiagnostics(v.text,d.agent.tools)),v=await d.runAdapter(s),emitRepair(d,"runtime.repair.completed","result_output",e+1,"recoverable_result_output","retried",repairDiagnostics(v.text,d.agent.tools))}return function finalizeRecoveredOutput(t,u){if(!y(t.recoveryPolicy))return u;let d=!1;if(n(u.text,t.recoveryPolicy)&&function rawToolCallFailureReturnsMessage(e){return"message"===("object"!=typeof e?.toolCallRecovery||null===e.toolCallRecovery||Array.isArray(e.toolCallRecovery)?{}:e.toolCallRecovery).onFailure}(t.request.metadata)){const e=u.text;u={...u,text:c(),metadata:{...u.metadata,toolCallRecovery:{failed:!0,reason:"raw_tool_call_output"}}},emitRepair(t,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked",repairDiagnostics(e,t.agent.tools))}const v=i({request:t.request,output:u.text,events:t.store.getRun(t.requestId)?.events??[],policy:t.recoveryPolicy});return v&&(d=!0,u={...u,text:v,metadata:{...u.metadata,toolCallRecovery:{synthesized:!0,reason:"raw_tool_call_output_with_evidence"}}},emitRepair(t,"runtime.repair.completed","evidence_synthesis",void 0,"raw_tool_call_output_with_evidence","synthesized")),d||(n(u.text,t.recoveryPolicy)&&emitRepair(t,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked",repairDiagnostics(u.text,t.agent.tools)),a(u.text,t.recoveryPolicy),function assertNoRawArgsToolOutput(e,t){if(o({output:t,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,policy:e.recoveryPolicy}))throw new Error(`Adapter returned raw tool argument JSON as the final answer after recovery. The backend must execute the matching tool instead. Output preview: ${p(t)}`)}(t,u.text),r(u.text,t.agent.tools,t.recoveryPolicy),s(u.text,t.store.getRun(t.requestId)?.events??[],t.recoveryPolicy),l(u.text,t.recoveryPolicy),e({output:u.text,events:t.store.getRun(t.requestId)?.events??[],availableToolIds:t.agent.tools})),u}(d,v)}function emitRepair(e,t,o,r,a,s,l){const i={requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:o,attempt:r,reason:a,...l?{diagnostics:l}:{}};e.emit("runtime.repair.started"===t?{type:t,...i}:{type:t,...i,outcome:s??"retried"})}function repairDiagnostics(e,t){return{outputPreview:p(e),toolCandidateIds:visibleToolCandidates(e,t)}}function visibleToolCandidates(e,t){const o=new Set;for(const r of t??[])new RegExp(`(?:^|[^A-Za-z0-9_-])${escapeRegexp(r)}(?:$|[^A-Za-z0-9_-])`,"u").test(e)&&o.add(r);return[...o]}function escapeRegexp(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}
1
+ import{assertNoDeclaredActionOmissionOutput as e}from"../../recovery/control-omission.js";import{buildRawArgsRecoveryRequest as t,hasUniqueRawArgsTool as o}from"../../recovery/raw-args.js";import{assertNoProgressOnlyToolIntentOutput as r,assertNoRawToolCallOutput as a,assertNoRawToolResultOutput as s,assertNoToolExecutionErrorOutput as l,buildEvidenceSynthesisOutput as i,buildResultRecoveryRequest as u,containsRawToolCallOutput as n,rawToolCallFailureMessage as c,rawToolCallOutputPreview as p,toolCallRecoveryEnabled as y}from"../../recovery/tool-call.js";export async function recoverAdapterResultOutput(d){let v=d.result,m=d.request;const g=function resultRecoveryAttempts(e){const t="object"!=typeof e||null===e||Array.isArray(e)?void 0:e.recovery,o="object"!=typeof t||null===t||Array.isArray(t)?void 0:t.toolCall,r="object"!=typeof o||null===o||Array.isArray(o)?void 0:o.maxResultRecoveryAttempts;return"number"==typeof r&&Number.isInteger(r)&&r>0?r:3}(d.recoveryPolicy);let R=!1;for(let e=0;;e+=1){const o=d.store.getRun(d.requestId)?.events??[],r=R?void 0:t({request:m,output:v.text,agent:d.agent,workspace:d.workspace,toolGateway:d.toolGateway,events:o,policy:d.recoveryPolicy}),a=e<g?u({request:m,output:v.text,events:o,availableToolIds:d.agent.tools,policy:d.recoveryPolicy}):void 0,s=r??a;if(!s)break;s===r&&(R=!0),m=s,emitRepair(d,"runtime.repair.started","result_output",e+1,"recoverable_result_output",void 0,repairDiagnostics(v.text,d.agent.tools)),v=await d.runAdapter(s),emitRepair(d,"runtime.repair.completed","result_output",e+1,"recoverable_result_output","retried",repairDiagnostics(v.text,d.agent.tools))}return function finalizeRecoveredOutput(t,u){if(!y(t.recoveryPolicy))return u;let d=!1;if(n(u.text,t.recoveryPolicy)&&function rawToolCallFailureReturnsMessage(e){return"message"===("object"!=typeof e?.toolCallRecovery||null===e.toolCallRecovery||Array.isArray(e.toolCallRecovery)?{}:e.toolCallRecovery).onFailure}(t.request.metadata)){const e=u.text;u={...u,text:c(),metadata:{...u.metadata,toolCallRecovery:{failed:!0,reason:"raw_tool_call_output"}}},emitRepair(t,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked",repairDiagnostics(e,t.agent.tools))}const v=i({request:t.request,output:u.text,events:t.store.getRun(t.requestId)?.events??[],policy:t.recoveryPolicy});return v&&(d=!0,u={...u,text:v,metadata:{...u.metadata,toolCallRecovery:{synthesized:!0,reason:"raw_tool_call_output_with_evidence"}}},emitRepair(t,"runtime.repair.completed","evidence_synthesis",void 0,"raw_tool_call_output_with_evidence","synthesized")),d||(n(u.text,t.recoveryPolicy)&&emitRepair(t,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked",repairDiagnostics(u.text,t.agent.tools)),a(u.text,t.recoveryPolicy),function assertNoRawArgsToolOutput(e,t){if(o({output:t,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:e.store.getRun(e.requestId)?.events??[],policy:e.recoveryPolicy}))throw new Error(`Adapter returned raw tool argument JSON as the final answer after recovery. The backend must execute the matching tool instead. Output preview: ${p(t)}`)}(t,u.text),r(u.text,t.agent.tools,t.recoveryPolicy),s(u.text,t.store.getRun(t.requestId)?.events??[],t.recoveryPolicy),l(u.text,t.recoveryPolicy),e({output:u.text,events:t.store.getRun(t.requestId)?.events??[],availableToolIds:t.agent.tools})),u}(d,v)}function emitRepair(e,t,o,r,a,s,l){const i={requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:o,attempt:r,reason:a,...l?{diagnostics:l}:{}};e.emit("runtime.repair.started"===t?{type:t,...i}:{type:t,...i,outcome:s??"retried"})}function repairDiagnostics(e,t){return{outputPreview:p(e),toolCandidateIds:visibleToolCandidates(e,t)}}function visibleToolCandidates(e,t){const o=new Set;for(const r of t??[])new RegExp(`(?:^|[^A-Za-z0-9_-])${escapeRegexp(r)}(?:$|[^A-Za-z0-9_-])`,"u").test(e)&&o.add(r);return[...o]}function escapeRegexp(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/core",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96",
15
- "@stable-harness/memory": "0.0.96"
14
+ "@stable-harness/governance": "0.0.98",
15
+ "@stable-harness/memory": "0.0.98"
16
16
  }
17
17
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/evaluation",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96"
13
+ "@stable-harness/core": "0.0.98"
14
14
  }
15
15
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/governance",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96",
3
+ "version": "0.0.98",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist/**/*.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/protocols",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96"
13
+ "@stable-harness/core": "0.0.98"
14
14
  }
15
15
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable-harness/tool-gateway",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
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.96",
3
+ "version": "0.0.98",
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.96"
14
+ "@stable-harness/core": "0.0.98"
15
15
  }
16
16
  }