stable-harness 0.0.132 → 0.0.134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/adapter.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-tool-policy.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/package.json +2 -2
- package/node_modules/@stable-harness/adapter-langgraph/package.json +2 -2
- package/node_modules/@stable-harness/core/dist/quality/event-evidence.js +1 -1
- package/node_modules/@stable-harness/core/dist/recovery/execution-contract.js +1 -1
- package/node_modules/@stable-harness/core/dist/recovery/raw-args.js +1 -1
- package/node_modules/@stable-harness/core/dist/recovery/tool-call.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/recovery/adapter-result.d.ts +4 -2
- package/node_modules/@stable-harness/core/dist/runtime/recovery/adapter-result.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/recovery/execution-contract-runtime.d.ts +18 -0
- package/node_modules/@stable-harness/core/dist/runtime/recovery/execution-contract-runtime.js +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/recovery/focused-text-recovery.d.ts +18 -0
- package/node_modules/@stable-harness/core/dist/runtime/recovery/focused-text-recovery.js +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/recovery/non-focused-recovery.d.ts +13 -0
- package/node_modules/@stable-harness/core/dist/runtime/recovery/non-focused-recovery.js +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/recovery/recovery-policy.d.ts +3 -0
- package/node_modules/@stable-harness/core/dist/runtime/recovery/recovery-policy.js +1 -0
- package/node_modules/@stable-harness/core/dist/runtime.js +1 -1
- package/node_modules/@stable-harness/core/package.json +3 -3
- package/node_modules/@stable-harness/governance/package.json +1 -1
- package/node_modules/@stable-harness/memory/package.json +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/openai-payload.js +1 -1
- package/node_modules/@stable-harness/protocols/package.json +2 -2
- package/node_modules/@stable-harness/tool-gateway/dist/src/argument-guard.js +1 -1
- package/node_modules/@stable-harness/tool-gateway/package.json +1 -1
- package/node_modules/@stable-harness/workspace-yaml/package.json +2 -2
- package/package.json +9 -9
- package/packages/adapter-deepagents/dist/src/adapter.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/builtin-tool-policy.js +1 -1
- package/packages/adapter-deepagents/package.json +2 -2
- package/packages/adapter-langgraph/package.json +2 -2
- package/packages/cli/package.json +8 -8
- package/packages/core/dist/quality/event-evidence.js +1 -1
- package/packages/core/dist/recovery/execution-contract.js +1 -1
- package/packages/core/dist/recovery/raw-args.js +1 -1
- package/packages/core/dist/recovery/tool-call.js +1 -1
- package/packages/core/dist/runtime/recovery/adapter-result.d.ts +4 -2
- package/packages/core/dist/runtime/recovery/adapter-result.js +1 -1
- package/packages/core/dist/runtime/recovery/execution-contract-runtime.d.ts +18 -0
- package/packages/core/dist/runtime/recovery/execution-contract-runtime.js +1 -0
- package/packages/core/dist/runtime/recovery/focused-text-recovery.d.ts +18 -0
- package/packages/core/dist/runtime/recovery/focused-text-recovery.js +1 -0
- package/packages/core/dist/runtime/recovery/non-focused-recovery.d.ts +13 -0
- package/packages/core/dist/runtime/recovery/non-focused-recovery.js +1 -0
- package/packages/core/dist/runtime/recovery/recovery-policy.d.ts +3 -0
- package/packages/core/dist/runtime/recovery/recovery-policy.js +1 -0
- package/packages/core/dist/runtime.js +1 -1
- package/packages/core/package.json +3 -3
- package/packages/evaluation/package.json +2 -2
- package/packages/governance/package.json +1 -1
- package/packages/memory/package.json +1 -1
- package/packages/protocols/dist/src/openai-payload.js +1 -1
- package/packages/protocols/package.json +2 -2
- package/packages/tool-gateway/dist/src/argument-guard.js +1 -1
- package/packages/tool-gateway/package.json +1 -1
- package/packages/workspace-yaml/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{realpathSync as e}from"node:fs";import t from"node:path";import{buildRuntimeSystemPrompt as r}from"@stable-harness/core";import{createBuiltinToolPolicyMiddleware as n,createObserverMiddleware as o}from"./internal/builtin-tool-policy.js";import{resolveFilesystemPermissions as s}from"./internal/builtin/permissions.js";import{createToolRepeatState as a}from"@stable-harness/core";import{buildGatewayTools as i,stringifyDeepAgentResult as l}from"./internal/gateway-tools.js";import{resolveDeepAgentsNativeMemories as d}from"./memory.js";import{buildDeepAgentRequest as c}from"./internal/messages.js";import{createRawToolCallParserMiddleware as p}from"./internal/raw-tool-call-parser.js";import{createBackendModel as u}from"./model-providers.js";import{createDeepAgentsRetryMiddleware as
|
|
1
|
+
import{realpathSync as e}from"node:fs";import t from"node:path";import{buildRuntimeSystemPrompt as r}from"@stable-harness/core";import{createBuiltinToolPolicyMiddleware as n,createObserverMiddleware as o}from"./internal/builtin-tool-policy.js";import{resolveFilesystemPermissions as s}from"./internal/builtin/permissions.js";import{createToolRepeatState as a}from"@stable-harness/core";import{buildGatewayTools as i,stringifyDeepAgentResult as l}from"./internal/gateway-tools.js";import{resolveDeepAgentsNativeMemories as d}from"./memory.js";import{buildDeepAgentRequest as c}from"./internal/messages.js";import{createRawToolCallParserMiddleware as p}from"./internal/raw-tool-call-parser.js";import{createBackendModel as u}from"./model-providers.js";import{createDeepAgentsRetryMiddleware as m}from"./retry-policy.js";import{streamDeepAgentResult as g}from"./internal/stream-events.js";import{cleanupDeepAgentsRuntimeSubstrate as f,resolveDeepAgentsRuntimeSubstrate as y}from"./internal/substrate/runtime.js";import{createDefaultDeepAgentsBackend as v}from"./internal/vfs-backend.js";export function createDeepAgentsAdapter(e={}){return{name:"deepagents",canRun:e=>"deepagents"===e.backend,async run(t){const r=focusedRecoveryToolIds(t),n=recoveryVisibleTools(t,t.agent.tools);if(t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",phase:"agent.handoff",modelRef:t.agent.modelRef,tools:t.agent.tools,gatewayTools:n,...r.length>0?{focusedRecoveryTools:r,recoveryMode:"required_evidence_tools"}:{},skills:t.agent.skills,subagents:t.agent.subagents}}),(r.length>0||n.length!==t.agent.tools.length)&&t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",phase:"agent.gateway.tools",tools:n,declaredTools:t.agent.tools,...r.length>0?{focusedRecoveryTools:r,recoveryMode:"required_evidence_tools"}:{}}}),e.runner)return e.runner(t);const o=e.createDeepAgent?void 0:await async function loadDeepAgentsModule(){try{return await async function importOptionalPackage(e){return import(e)}("deepagents")}catch(e){throw new Error(`DeepAgents package is required for the default adapter path: ${function formatError(e){return e instanceof Error?e.message:String(e)}(e)}`)}}(),a=e.createDeepAgent??function readCreateDeepAgent(e){const t=e?.createDeepAgent;if("function"==typeof t)return t;throw new Error("DeepAgents package does not export createDeepAgent.")}(o),d={...readDeepAgentsConfig(e.config),...readDeepAgentsConfig(t.agent.config.deepagents)},p=y(t,d),u=resolveDeepAgentsSkills(t,t.agent),m=resolveDeepAgentsMemory(t,t.agent),A=void 0===d.backend?await v({workspaceRoot:t.workspace.root,skills:u,memory:m,config:d}):{cleanup:async()=>{}};try{const e=void 0===A.backend&&void 0===d.backend,r=a(function buildDeepAgentParams(e,t,r,n,o={}){const a=o.skills??resolveDeepAgentsSkills(e,e.agent),l=o.memory??resolveDeepAgentsMemory(e,e.agent),d=t.permissions??s(e,e.agent,{enabled:!0===o.autoPathPermissions}),c=requestScopedRepeatState(e,e.agent.id);return pruneUndefined({name:e.agent.id,model:t.model??resolveAgentModel(e,e.agent),systemPrompt:buildSystemPrompt(e,e.agent),backend:t.backend??o.backend??resolveDeepAgentsBackend(e,n,a),checkpointer:r.checkpointer,store:r.store,middleware:mergeMiddleware(e,e.agent,t.middleware,c),responseFormat:t.responseFormat,contextSchema:t.contextSchema,interruptOn:t.interruptOn,generalPurposeAgent:readBoolean(t.generalPurposeAgent),taskDescription:readString(t.taskDescription),permissions:d,tools:i(e,e.agent.id,recoveryVisibleTools(e,e.agent.tools),resolveAgentRepairModel(e,e.agent,t),c),subagents:e.agent.subagents.map(t=>{const r=e.workspace.agents.get(t),n=readDeepAgentsConfig(r?.config.deepagents),a=n.permissions??s(e,r,{enabled:!0===o.autoPathPermissions}),l=scopedInput(e,r),d=requestScopedRepeatState(e,t);return pruneUndefined({name:t,description:r?.description??readString(r?.config.description)??r?.id,systemPrompt:buildSystemPrompt(e,r),model:n.model??(r?resolveAgentModel(e,r):void 0),middleware:mergeMiddleware(l,r,n.middleware,d),interruptOn:n.interruptOn,generalPurposeAgent:readBoolean(n.generalPurposeAgent),taskDescription:readString(n.taskDescription),permissions:a,responseFormat:n.responseFormat,tools:i(e,t,recoveryVisibleTools(e,r?.tools??[]),resolveAgentRepairModel(l,r,n),d),memory:resolveDeepAgentsMemory(e,r),skills:resolveDeepAgentsSkills(e,r)})}),memory:l,skills:a})}(t,d,p,o,{backend:A.backend,skills:u,memory:m,autoPathPermissions:e})),n=c(t),f=function buildDeepAgentInvokeConfig(e,t){return pruneUndefined({recursionLimit:readNumber(readDeepAgentsConfig(e.config.deepagents).recursionLimit)??readNumber(e.config.recursionLimit),configurable:{thread_id:t}})}(t.agent,p.threadId);if(!0===t.request.metadata?.openaiStream&&r.streamEvents){const e=await r.streamEvents(n,{version:"v3",...f});return await g(t,e,l)}const y=await r.invoke(n,f);return l(y)}finally{await A.cleanup(),await f(p)}}}}function recoveryVisibleTools(e,t){const r=focusedRecoveryToolIds(e);return 0===r.length?t:t.filter(e=>r.includes(e))}function focusedRecoveryToolIds(e){return readStringArray(e.request.metadata?.stableHarnessRequiredEvidenceTools)??[]}function buildSystemPrompt(e,t){const n=t?.systemPrompt??readString(t?.config.systemPrompt);return r({workspace:e.workspace,request:e.request,agent:t},n)}function resolveDeepAgentsMemory(e,t){const r=readDeepAgentsStringArray(t?.config,"memory");if(r)return r;const n=[...readAgentMemorySources(e.workspace.root,t),...d(e.workspace).map(e=>`/memories/${e.id}.md`)],o=[...new Set(n)];return o.length>0?o:void 0}function readAgentMemorySources(e,t){return(t?.memory??[]).flatMap(t=>"string"==typeof t&&t.trim()?[backendMemorySourcePath(e,t.trim())]:isRecord(t)&&"string"==typeof t.path&&t.path.trim()?[backendMemorySourcePath(e,t.path.trim())]:[])}function backendMemorySourcePath(e,r){if(r.startsWith("/"))return r;if(t.isAbsolute(r)){const n=t.relative(e,r);return n&&!n.startsWith("..")?`/${n.split(t.sep).join("/")}`:canonicalPath(r)}const n=r.split(t.sep).join("/");return n.startsWith("/")?n:`/${n}`}function resolveDeepAgentsSkills(e,r){const n=readDeepAgentsStringArray(r?.config,"skills");if(n)return n;const o=[...new Set((r?.skills??[]).map(t=>e.workspace.skills.get(t)?.path).filter(e=>"string"==typeof e&&e.trim().length>0).map(r=>function backendSkillSourcePath(e,r){const n=t.dirname(t.dirname(r)),o=t.relative(e,n);return!o||o.startsWith("..")||t.isAbsolute(o)?""===o?"/":canonicalPath(n):`/${o.split(t.sep).join("/")}`}(e.workspace.root,r)))];return o.length>0?o:void 0}function resolveDeepAgentsBackend(e,t,r){if(t?.FilesystemBackend&&r&&0!==r.length)return()=>new t.FilesystemBackend({rootDir:e.workspace.root})}function mergeMiddleware(e,t,r,s=a(e.workspace.runtime.toolGateway)){const i=Array.isArray(r)?r:[],l=scopedInput(e,t),d=new Set,c=readDeepAgentsConfig(t?.config.deepagents);return[o(l,{observedToolIds:d,repeatState:s,repairModel:resolveAgentRepairModel(l,t,c)}),n(l,{repeatState:s}),...m(e.workspace.runtime.retry),...i,p(l)]}function requestScopedRepeatState(e,t){const r=`deepagents.repeat.${t}`,n=e.requestState?.get(r);if(n)return n;const o=a(e.workspace.runtime.toolGateway);return e.requestState&&o&&e.requestState.set(r,o),o}function scopedInput(e,t){return t?{...e,agent:t}:e}function resolveAgentModel(e,t){const r=t.modelRef?e.workspace.models.get(t.modelRef):void 0;return r?u(r):void 0}function resolveAgentRepairModel(e,t,r){const n=r.model;if(isRepairModel(n))return n;if(!t?.modelRef)return;const o=e.workspace.models.get(t.modelRef);if(!o||"openai-compatible"!==o.provider)return;const s=u(o);return isRepairModel(s)?s:void 0}function readDeepAgentsConfig(e){return isRecord(e)?e:{}}function readDeepAgentsStringArray(e,t){const r=isRecord(e)?e:{},n=readDeepAgentsConfig(r.deepagents),o="memory"===t?["memory","memorySources"]:["skills","skillSources"];for(const e of o){const t=readStringArray(n[e]);if(t)return t}return readStringArray(r[t])}function pruneUndefined(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>void 0!==e))}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readNumber(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function readBoolean(e){return"boolean"==typeof e?e:void 0}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e):void 0}function canonicalPath(t){try{return e.native(t)}catch{return t}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function isRepairModel(e){return"object"==typeof e&&null!==e&&"invoke"in e&&"function"==typeof e.invoke}
|
package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-tool-policy.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ToolMessage as t}from"@langchain/core/messages";import{afterToolInvoke as e,beforeToolInvoke as o,createToolRepeatState as r}from"@stable-harness/core";import{filesystemBuiltinToolIds as i,isFilesystemDisabled as n,isFilesystemTool as
|
|
1
|
+
import{ToolMessage as t}from"@langchain/core/messages";import{afterToolInvoke as e,beforeToolInvoke as o,createToolRepeatState as r}from"@stable-harness/core";import{filesystemBuiltinToolIds as i,isFilesystemDisabled as n,isFilesystemTool as s,validateFilesystemBuiltinCall as l}from"./builtin/permissions.js";import{repairTaskCall as a}from"./builtin/task-inventory.js";import{repairBuiltinToolRequest as u}from"./builtin-call-repair.js";import{stringifyDeepAgentResult as c,toolControlProjection as d}from"./gateway-tools.js";import{isSuccessfulEvidenceOutput as p,observedToolEvidence as g,recordObservedToolEvidence as f}from"./gateway/tool-evidence.js";import{filterRepeatLimitedTools as m}from"./tool-repeat-visibility.js";import{traceProjectionForBuiltinTool as v}from"./trace-projection.js";const b=new Set(["write_todos","read_todos","task","execute",...i]),y=new Set(["task","execute"]);export function createBuiltinToolPolicyMiddleware(t,e={}){return{name:"StableHarnessBuiltinToolPolicy",async wrapModelCall(o,r){const i=Array.isArray(o.tools)?m(o.tools.filter(e=>!function hasHiddenBuiltins(t){return n(t)||[...y].some(e=>!isConfiguredModelVisibleBuiltin(t,e))}(t)||isModelVisibleBuiltin(t,e.name)),e.repeatState):o.tools,s=function normalizeToolChoice(t,e,o){if(function focusedEvidenceRecovery(t){const e=t.request.metadata?.stableHarnessRequiredEvidenceTools;return Array.isArray(e)&&e.some(t=>"string"==typeof t&&t.length>0)}(t)){const e=function focusedSingleToolName(t,e){const o=t.request.metadata?.stableHarnessRequiredEvidenceTools,r=Array.isArray(o)?o.filter(t=>"string"==typeof t&&t.length>0):[],i=(e??[]).map(t=>t.name).filter(t=>"string"==typeof t&&t.length>0);return 1===r.length&&i.includes(r[0])?r[0]:void 0}(t,o);return e?{type:"function",function:{name:e}}:o&&o.length>0?"required":"auto"}return"required"===e?o&&o.length>0?e:"auto":function isForcedHiddenTool(t,e){return"string"==typeof e?.function?.name&&!isModelVisibleBuiltin(t,e.function.name)}(t,e)?"auto":e}(t,o.toolChoice,i);return r({...o,tools:i,toolChoice:s})}}}export function createObserverMiddleware(i,n={}){const s=n.repeatState??r(i.workspace.runtime.toolGateway);return{name:"StableHarnessObserver",async wrapToolCall(r,d){const f=r.toolCall?.name;if(!f||!b.has(f))return d(r);const m=await u({toolId:f,request:r,workspaceRoot:i.workspace.root});if(emitToolEvent(i,f,"agent.tool.start",m.toolCall?.args),"task"===f){const t=s?o(f,m.toolCall?.args,s):void 0;if(t)return emitToolEvent(i,f,"agent.tool.result",m.toolCall?.args,{output:t.eventOutput}),builtinToolMessage(r,f,modelOutputForRepeatedBuiltin(f,t.modelOutput))}const v="task"===f?await a(i,m,{repairModel:n.repairModel}):{request:m},h=v.request,T=v.blocked;if(T)return emitToolEvent(i,f,"agent.tool.result",h.toolCall?.args,{output:T.content}),T;const C=function validateModelVisibleBuiltinCall(e,o,r){if(y.has(o)&&!isModelVisibleBuiltin(e,o))return new t({tool_call_id:r.toolCall?.id??`stable-harness-${o}-visibility-policy`,name:o,status:"error",content:JSON.stringify({status:"blocked_builtin_tool",toolId:o,instruction:"This builtin tool is disabled by runtime policy for the current agent. Use the declared workspace tools that remain visible, or finalize from evidence already collected."})})}(i,f,h);if(C)return emitToolEvent(i,f,"agent.tool.result",h.toolCall?.args,{output:C.content}),C;const E=l(i,f,h);if(E)return emitToolEvent(i,f,"agent.tool.result",h.toolCall?.args,{output:E.content}),E;try{const l="task"===f?void 0:s?o(f,h.toolCall?.args,s):void 0;if(l)return emitToolEvent(i,f,"agent.tool.result",h.toolCall?.args,{output:l.eventOutput}),builtinToolMessage(r,f,modelOutputForRepeatedBuiltin(f,l.modelOutput));const a=await d(h),u=function observedToolOutput(t,e,o){return"write_todos"===t?JSON.stringify({status:"recorded",args:e.toolCall?.args}):c(o)}(f,h,a),g=s?e({toolId:f,args:h.toolCall?.args,output:u,successful:!(a instanceof t&&"error"===a.status)&&p(u),state:s}):{};return emitToolEvent(i,f,"agent.tool.result",h.toolCall?.args,{output:g.eventOutput??u}),n.observedToolIds?.add(f),void 0===g.modelOutput?a:builtinToolMessage(r,f,g.modelOutput)}catch(e){const o=function recoverableBuiltinToolError(e,o,r,i){const n=formatError(i);if("task"===o&&/repeat limit reached for tool/iu.test(n)){const o=function formatObservedEvidence(t){const e=g(t);if(0===e.length)return"";const o=e.map(t=>[`Agent: ${t.agentId}`,`Tool: ${t.toolId}`,t.output].join("\n")).join("\n\n---\n\n");return o.length>12e3?`${o.slice(0,12e3)}\n[truncated]`:o}(e);return new t({tool_call_id:r.toolCall?.id??"stable-harness-task-repeat-limit",name:"task",content:JSON.stringify({status:"delegated_task_repeat_limit",finalizationRequired:!0,instruction:"The delegated agent reached a configured tool repeat limit. Stop delegating this evidence need and do not send a synthesis task to another subagent for the same need. Finalize only from observedEvidence and other evidence that is already visible in this run. If the visible evidence is insufficient for a requested claim, report an explicit blocker or evidence gap instead of estimating, inventing, or using generic knowledge.",...o?{observedEvidence:o}:{},error:previewError(n)})})}if(/Received tool input did not match expected schema|Invalid input:/iu.test(n))return new t({tool_call_id:r.toolCall?.id??`stable-harness-${o}-argument-error`,name:o,status:"error",content:JSON.stringify({status:"tool_argument_error",toolId:o,instruction:"The upstream builtin tool rejected these arguments. Fix the tool arguments according to the tool schema, or choose a more appropriate available tool.",error:previewError(n)})})}(i,f,r,e);if(o)return emitToolEvent(i,f,"agent.tool.result",m.toolCall?.args,{output:o.content}),o;throw emitToolEvent(i,f,"agent.tool.result",m.toolCall?.args,{error:formatError(e)}),e}}}}function builtinToolMessage(e,o,r){return new t({tool_call_id:e.toolCall?.id??`stable-harness-${o}-repeat-guard`,name:o,content:r})}function modelOutputForRepeatedBuiltin(t,e){return"task"!==t?e:function readPreviousOutput(t){try{const e=JSON.parse(t);if(!isRecord(e)||"repeated_tool_call_limit"!==e.status||"string"!=typeof e.previousOutput)return;const o=e.previousOutput.trim();return o.length>0?o:void 0}catch{return}}(e)??e}function emitToolEvent(t,e,o,r,i={}){"string"==typeof i.output&&f(t,t.agent.id,e,i.output),t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",eventGroup:"tool_execution",eventType:"agent.tool.start"===o?"deepagents.tool_execution.start":"deepagents.tool_execution.result",phase:o,toolId:e,..."agent.tool.start"===o?{args:r}:{},...i,..."string"==typeof i.output?d(i.output):{},...v(e,o,r)}})}function isConfiguredModelVisibleBuiltin(t,e){const o=function readConfigRecord(t,e){const o=isRecord(t)?t:{};return isRecord(o[e])?o[e]:void 0}(t.agent.config,"builtinTools")?.modelExposed;return!1!==o&&(!Array.isArray(o)||o.includes(e))}function isModelVisibleBuiltin(t,e){return(!n(t)||!s(e))&&("string"!=typeof e||!y.has(e)||isConfiguredModelVisibleBuiltin(t,e))}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function formatError(t){return t instanceof Error?t.message:String(t)}function previewError(t){const e=t.replace(/\s+/gu," ").trim();return e.length>800?`${e.slice(0,797)}...`:e}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/adapter-deepagents",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.134",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"@langchain/node-vfs": "^0.1.4",
|
|
17
17
|
"@langchain/ollama": "^1.2.7",
|
|
18
18
|
"@langchain/openai": "^1.4.5",
|
|
19
|
-
"@stable-harness/core": "0.0.
|
|
19
|
+
"@stable-harness/core": "0.0.134",
|
|
20
20
|
"deepagents": "^1.10.1",
|
|
21
21
|
"langchain": "^1.4.0"
|
|
22
22
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/adapter-langgraph",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.134",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -12,6 +12,6 @@
|
|
|
12
12
|
"types": "dist/src/index.d.ts",
|
|
13
13
|
"peerDependencies": {
|
|
14
14
|
"@langchain/langgraph": "^1.3.0",
|
|
15
|
-
"@stable-harness/core": "0.0.
|
|
15
|
+
"@stable-harness/core": "0.0.134"
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{looksLikeUnexecutedToolIntent as
|
|
1
|
+
import{looksLikeUnexecutedToolIntent as e}from"./evidence/tool-intent.js";export function hasPlanningEvidence(e){return e.some(e=>{const t=readAdapterEvent(e);return!!t&&("plan"===t.traceType||String(t.traceLabel??"").startsWith("plan.")||"write_todos"===t.toolId&&String(t.phase??"").startsWith("agent.tool."))})}export function successfulEvidenceToolIds(e){const t=e.flatMap(e=>{if("runtime.tool.direct.completed"===e.type)return[e.toolId];const t=readAdapterEvent(e),n=readToolSource(t);return isToolResultEvent(t)&&n&&isSuccessfulEvidenceEvent(t)?[n]:[]});return[...new Set(t)]}export function successfulEvidenceOutputs(e){return successfulEvidenceItems(e).map(e=>e.output)}export function successfulEvidenceItems(e){return e.flatMap(e=>{if("runtime.tool.direct.completed"===e.type)return stringifyEvidence(e.output).map(t=>({source:e.toolId,output:t}));const t=readAdapterEvent(e),n=readToolSource(t);return isToolResultEvent(t)&&n?!isSuccessfulEvidenceEvent(t)||isPlanningTool(n)?[]:stringifyEvidence(t.evidenceOutput??t.output).filter(e=>isUsableEvidenceOutput(n,e)).map(e=>({source:n,output:e})):[]})}export function controlBlockers(e){const t=successfulEventIndexesBySource(e);return e.flatMap((n,o)=>{const r=readAdapterEvent(n),s=readControlStatus(r),u=readControlSource(r)??"tool";return s&&isBlockerStatus(s)?isResolvedByLaterCompletion(s)&&completedAfter(t,u,o)||function isResolvedByLaterEvidenceCompletion(e){return"tool_argument_error"===e}(s)&&function successfulEvidenceAfter(e,t){return e.some((e,n)=>n>t&&Boolean(function successfulEvidenceEventSource(e){if("runtime.tool.direct.completed"===e.type)return e.toolId;const t=readAdapterEvent(e),n=readToolSource(t);return isToolResultEvent(t)&&n&&isSuccessfulEvidenceEvent(t)&&!isPlanningTool(n)&&stringifyEvidence(t.evidenceOutput??t.output).some(e=>isUsableEvidenceOutput(n,e))?n:void 0}(e)))}(e,o)||isResolvedByLaterAnyCompletion(s)&&completedAfterAny(t,o)?[]:[`${u}:${s}`]:[]})}export function controlGaps(e){const t=new Set(successfulEvidenceItems(e).map(e=>e.source));return e.flatMap(e=>{const n=readAdapterEvent(e),o=readControlStatus(n),r=readControlSource(n)??"tool";return o&&isGapStatus(o)?t.has(r)&&isResolvedByLaterCompletion(o)?[]:[`${r}:${o}`]:[]})}export function omittedControlGaps(e,t){const n=successfulEventIndexesBySource(e),o=successfulEvidenceItems(e),r=function outputHasUnsupportedEvidenceClaims(e,t,n){const o=function evidenceCorpus(e,t){return[...t.map(e=>e.output),...e.flatMap(e=>"runtime.request.started"===e.type?[e.input??""]:[]),...e.flatMap(e=>"runtime.memory.recall.completed"===e.type?[e.context]:[])].join("\n")}(t,n).toLowerCase();return unsupportedTokens(e,o,/\b[A-Z][A-Z0-9]{1,12}-\d+\b/gu).length>0||unsupportedTokens(e,o,/\b[A-Za-z_$][A-Za-z0-9_$]*[A-Z][A-Za-z0-9_$]*\b/gu).filter(isCodeLikeIdentifier).length>=2}(t,e,o);return e.flatMap((e,s)=>{const u=readAdapterEvent(e),i=readControlStatus(u),c=readControlSource(u)??"tool";return i&&function isOmittedControlStatus(e){return isGapStatus(e)||isBlockerStatus(e)}(i)?isResolvedByLaterCompletion(i)&&completedAfter(n,c,s)||isResolvedByLaterAnyCompletion(i)&&completedAfterAny(n,s)||!r&&outputUsesPriorEvidence(t,c,o)?[]:[`${c}:${i}`]:[]})}function stringifyEvidence(e){return"string"==typeof e?e.trim()?[e]:[]:null==e?[]:[JSON.stringify(e)]}function isPlanningTool(e){return"write_todos"===e||"read_todos"===e}function isUsableEvidenceOutput(t,n){return"task"!==t||!e(n)}function readAdapterEvent(e){if("runtime.adapter.event"===e.type&&isRecord(e.event))return e.event;const t=e;return isRecord(t)&&isToolResultEvent(t)?t:void 0}function isSuccessfulEvidenceEvent(e){const t=readEventStatus(e);return!t||/^(?:completed|success|ok|recorded)$/iu.test(t)}function isBlockerStatus(e){return/^(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input|task_inventory_blocked)$/iu.test(e)}function isGapStatus(e){return/^(?:dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)$/iu.test(e)}function isResolvedByLaterCompletion(e){return isGapStatus(e)||isBlockerStatus(e)}function isResolvedByLaterAnyCompletion(e){return"task_inventory_blocked"===e}function successfulEventIndexesBySource(e){const t=new Map;return e.forEach((e,n)=>{const o=function successfulEventSource(e){if("runtime.tool.direct.completed"===e.type)return e.toolId;const t=readAdapterEvent(e),n=readToolSource(t);return isToolResultEvent(t)&&n&&isSuccessfulEvidenceEvent(t)?n:void 0}(e);o&&t.set(o,[...t.get(o)??[],n])}),t}function isToolResultEvent(e){return"deepagents.tool_execution.result"===e?.eventType||"agent.tool.result"===e?.phase||"agent.tool.result"===e?.type||"deepagents.tool_execution.result"===e?.type}function completedAfter(e,t,n){return(e.get(t)??[]).some(e=>e>n)}function completedAfterAny(e,t){return[...e.values()].some(e=>e.some(e=>e>t))}export function outputUsesPriorEvidence(e,t,n){const o=e.toLowerCase();return n.filter(e=>e.source===t).some(e=>{const t=e.output.trim();return!!t&&(!!o.includes(t.slice(0,500).toLowerCase())||function matchingEvidenceTokens(e,t){const n=new Set(["status","completed","success","recorded"]);return[...new Set(t.toLowerCase().match(/[a-z0-9][a-z0-9_.-]{1,}/gu)??[])].filter(e=>!n.has(e)).filter(t=>e.includes(t)).length}(o,t)>=2)})}function unsupportedTokens(e,t,n){return[...new Set(e.match(n)??[])].filter(e=>!t.includes(e.toLowerCase()))}function isCodeLikeIdentifier(e){return!(e.length<8)&&(/(?:Service|Controller|Repository|Manager|Client|Resolver|Agent|Tool|Async)$/u.test(e)||/[a-z][A-Z]/u.test(e))}function readOutputStatus(e){if(isRecord(e)&&"string"==typeof e.status)return e.status;if("string"==typeof e){const t=parseJsonRecord(e);return"string"==typeof t?.status?t.status:e.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}}function parseJsonRecord(e){try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readEventStatus(e){return readString(e?.controlStatus)??readString(e?.status)??readOutputStatus(e?.output)}function readToolSource(e){return readString(e?.toolId)??readString(e?.toolName)??readString(e?.name)}function readControlStatus(e){const t=function readInventoryRepairControlStatus(e){if("inventory.repair"===e?.phase&&"blocked"===e.status)return"task"===readInventoryRepairSource(e)?"task_inventory_blocked":"blocked"}(e);if(t)return t;const n=readEventStatus(e);return n&&isControlStatus(n)?n:findNestedControlStatus(e)}function readControlSource(e){return readToolSource(e)??readInventoryRepairSource(e)??findNestedToolSource(e)}function isControlStatus(e){return isGapStatus(e)||isBlockerStatus(e)}function findNestedControlStatus(e,t=0){if(t>5||null==e)return;if("string"==typeof e)return function readNestedStringStatus(e,t){const n=parseJsonRecord(e);return n?findNestedControlStatus(n,t+1):findFirstNested(jsonRecordsInText(e),e=>findNestedControlStatus(e,t+1))}(e,t);if(Array.isArray(e))return findFirstNested(e,e=>findNestedControlStatus(e,t+1));if(!isRecord(e))return;const n=readString(e.controlStatus)??readString(e.status);if(n&&isControlStatus(n))return n;const o=readOutputStatus(e.output);return o&&isControlStatus(o)?o:findFirstNested(Object.values(e),e=>findNestedControlStatus(e,t+1))}function findNestedToolSource(e,t=0){if(!(t>5||null==e)){if("string"==typeof e)return function readToolSourceFromText(e){const t=parseJsonRecord(e);return t?findNestedToolSource(t):findFirstNested(jsonRecordsInText(e),e=>findNestedToolSource(e))}(e);if(Array.isArray(e))return findFirstNested(e,e=>findNestedToolSource(e,t+1));if(isRecord(e))return(readString(e.toolId)??readString(e.toolName)??readString(e.name))||findFirstNested(Object.values(e),e=>findNestedToolSource(e,t+1))}}function findFirstNested(e,t){for(const n of e){const e=t(n);if(void 0!==e)return e}}function jsonRecordsInText(e){const t=[];for(let n=0;n<e.length;n+=1){if("{"!==e[n])continue;const o=findJsonObjectEnd(e,n);if(void 0===o)continue;const r=parseJsonRecord(e.slice(n,o+1));r&&(t.push(r),n=o)}return t}function findJsonObjectEnd(e,t){let n=0,o=!1,r=!1;for(let s=t;s<e.length;s+=1){const t=e[s];if(o)r?r=!1:"\\"===t?r=!0:'"'===t&&(o=!1);else if('"'===t)o=!0;else if("{"===t)n+=1;else if("}"===t&&(n-=1,0===n))return s}}function readInventoryRepairSource(e){const t=isRecord(e?.diagnostic)?e.diagnostic:void 0;return readString(t?.layer)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{successfulEvidenceItems as e,successfulEvidenceToolIds as t}from"../quality/event-evidence.js";export function buildExecutionContractRecoveryRequest(e){if(!0!==function readToolCallRecovery(e){if(!isRecord(e))return{};const t=isRecord(e.recovery)?e.recovery:{};return isRecord(t.toolCall)?t.toolCall:{}}(e.policy).enabled)return;const n=function lastExecutionContractFailure(e){for(let t=e.length-1;t>=0;t-=1){const n=e[t];if("runtime.execution.contract.failed"===n?.type)return{reason:n.reason,missing:readStringArray(n.missingEvidenceTools)}}return{missing:[]}}(e.events);if(0===n.missing.length)return;if("missing_required_evidence_usage"===n.reason){const t=recentSuccessfulEvidence(e.events);return recoverRequest(e.request,["Stable runtime recovery: the execution contract was not satisfied.",`The final answer did not use required executed evidence from: ${n.missing.join(", ")}`,"Synthesize from those required source(s), or call them through normal structured tool calling if their evidence is unavailable.","Do not replace required evidence with unrelated intermediate evidence, progress text, or summaries from other tools.",...t.length>0?["","Prior successful tool evidence:",...t]:[]])}const r=recentSuccessfulEvidence(e.events),o=function recoveryToolTargets(e,n,r){const o=function readToolDependencies(e){return isRecord(e)?new Map(Object.entries(e).map(([e,t])=>[e,readStringArray(t)]).filter(e=>e[1].length>0)):new Map}(function readExecutionContract(e){return isRecord(e.config.executionContract)?e.config.executionContract:{}}(e).toolDependencies),
|
|
1
|
+
import{successfulEvidenceItems as e,successfulEvidenceToolIds as t}from"../quality/event-evidence.js";export function buildExecutionContractRecoveryRequest(e){if(!0!==function readToolCallRecovery(e){if(!isRecord(e))return{};const t=isRecord(e.recovery)?e.recovery:{};return isRecord(t.toolCall)?t.toolCall:{}}(e.policy).enabled)return;const n=function lastExecutionContractFailure(e){for(let t=e.length-1;t>=0;t-=1){const n=e[t];if("runtime.execution.contract.failed"===n?.type)return{reason:n.reason,missing:readStringArray(n.missingEvidenceTools)}}return{missing:[]}}(e.events);if(0===n.missing.length)return;if("missing_required_evidence_usage"===n.reason){const t=recentSuccessfulEvidence(e.events);return recoverRequest(e.request,["Stable runtime recovery: the execution contract was not satisfied.",`The final answer did not use required executed evidence from: ${n.missing.join(", ")}`,"Synthesize from those required source(s), or call them through normal structured tool calling if their evidence is unavailable.","Do not replace required evidence with unrelated intermediate evidence, progress text, or summaries from other tools.",...t.length>0?["","Prior successful tool evidence:",...t]:[]])}const r=recentSuccessfulEvidence(e.events),o=function recoveryToolTargets(e,n,r){const o=function readToolDependencies(e){return isRecord(e)?new Map(Object.entries(e).map(([e,t])=>[e,readStringArray(t)]).filter(e=>e[1].length>0)):new Map}(function readExecutionContract(e){return isRecord(e.config.executionContract)?e.config.executionContract:{}}(e).toolDependencies),s=new Set(t(r)),i=new Set;for(const e of n)collectReadyTargets(e,o,s,i,new Set([e]));return[...i].filter(t=>e.tools.includes(t))}(e.agent,n.missing,e.events);return recoverRequest(e.request,["Stable runtime recovery: the execution contract was not satisfied.",`Required evidence tool(s) were missing: ${n.missing.join(", ")}`,`For this recovery turn, the allowed next tool call target(s) are: ${o.join(", ")}`,"Allowed targets include missing required evidence tools and any declared dependency tools that are still needed to build valid arguments.","Reuse exact values from prior successful tool evidence when building the required tool call. Do not invent replacement paths, IDs, handles, URLs, or parameters.","The next assistant action must be the backend's structured tool call for one allowed target, with no prose before it.","Do not call already completed intermediate tools unless they are listed above.","Do not produce a final answer until the required evidence tool call has executed and you have synthesized its result.","Do not print XML, JSON, markdown fences, pseudo tool-call text, plans, or future-intent text in the final answer.",...r.length>0?["","Prior successful tool evidence:",...r]:[]],{stableHarnessRequiredEvidenceTools:o})}function recoverRequest(e,t,n={}){return{...e,input:[e.input,"",...t].join("\n"),metadata:{...e.metadata,stableHarnessRecovery:"tool_call",...n}}}function collectReadyTargets(e,t,n,r,o){if(n.has(e))return;const s=(t.get(e)??[]).filter(e=>!n.has(e));if(0!==s.length)for(const e of s)o.has(e)||(o.add(e),collectReadyTargets(e,t,n,r,o));else r.add(e)}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}function recentSuccessfulEvidence(t){return e(t).slice(-5).map(e=>`- ${e.source}: ${function previewEvidence(e){const t=e.replace(/\s+/gu," ").trim();return t.length>1500?`${t.slice(0,1497)}...`:t}(e.output)}`)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{selectCallCandidateByArgsSchema as e}from"@easynet/better-call";export function buildRawArgsRecoveryRequest(e){if(!toolCallRecoveryEnabled(e.policy))return;const t=matchUniqueRawArgsTool(e);return t?function buildRawArgsRecoveryPrompt(e,t){return{...e,input:[e.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.metadata,stableHarnessRecovery:"tool_call"}}}(e.request,t):void 0}export function buildRawArgsToolEvidenceRecoveryRequest(e){return{...e.request,input:[e.request.input,"","Stable runtime recovery: your previous final answer repeated a JSON argument object for a declared tool after a structured tool-call recovery request.",`Matched configured tool: ${e.match.toolId}`,"Stable runtime executed that matched declared tool through the governed tool gateway.","Continue the same user request from the executed evidence below.","If another declared tool is needed, call it through the backend's normal structured tool-calling mechanism.","Otherwise, 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.","","Executed JSON arguments:",JSON.stringify(e.match.args),"","Executed tool output:",e.toolOutput].join("\n"),metadata:{...e.request.metadata,stableHarnessRecovery:"tool_call"}}}export function hasUniqueRawArgsTool(e){return toolCallRecoveryEnabled(e.policy)&&Boolean(matchUniqueRawArgsTool(e))}export function buildRawArgsToolSequenceEvidenceRecoveryRequest(e){return{...e.request,input:[e.request.input,"","Stable runtime recovery: your previous final answer printed multiple JSON argument objects for declared tools after a recovery request.","Stable runtime matched and executed those declared tools through the governed tool gateway.","Continue the same user request from the executed evidence below.","If another declared tool is needed, call it through the backend's normal structured tool-calling mechanism.","Otherwise, 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.","",...e.evidences.flatMap((e,t)=>[`Executed tool ${t+1}: ${e.match.toolId}`,"Executed JSON arguments:",JSON.stringify(e.match.args),"Executed tool output:",e.toolOutput,""])].join("\n"),metadata:{...e.request.metadata,stableHarnessRecovery:"tool_call"}}}export function matchUniqueRawArgsTool(t){const o=parseStandaloneJsonValues(t.output,{allowArray:!1})[0];if(!o)return;const r=matchToolEnvelope(o,t);if(r)return r;const a=isRawArgsRecord(o)?o:void 0;if(!a)return;const n=e({args:a,candidates:buildCallCandidates(t)});return n.ok?{toolId:n.candidateId,args:n.args}:void 0}export function matchRawArgsToolSequence(t){if(!toolCallRecoveryEnabled(t.policy))return[];const o=parseStandaloneJsonValues(t.output,{allowArray:!0});if(o.length<2)return[];const r=buildCallCandidates(t),a=[];for(const n of o){const o=matchToolEnvelope(n,t);if(o){a.push(o);continue}if(!isRawArgsRecord(n))return[];const s=e({args:n,candidates:r});if(!s.ok)return[];a.push({toolId:s.candidateId,args:s.args})}return a}function buildCallCandidates(e){return candidateToolIds(e).map(t=>({id:t,schema:e.workspace.tools.get(t)?.schema??e.toolGateway?.get(t)?.schema}))}function candidateToolIds(e){const t=new Set(e.agent.tools),o=(e.candidateToolIds??[]).filter(e=>t.has(e));return o.length>0?o:e.agent.tools}function parseStandaloneJsonValues(e,t){const o=e.trim(),r=o.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/iu)?.[1]?.trim(),a=r??o;if(a.length>
|
|
1
|
+
import{selectCallCandidateByArgsSchema as e}from"@easynet/better-call";export function buildRawArgsRecoveryRequest(e){if(!toolCallRecoveryEnabled(e.policy))return;const t=matchUniqueRawArgsTool(e);return t?function buildRawArgsRecoveryPrompt(e,t){return{...e,input:[e.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.metadata,stableHarnessRecovery:"tool_call"}}}(e.request,t):void 0}export function buildRawArgsToolEvidenceRecoveryRequest(e){return{...e.request,input:[e.request.input,"","Stable runtime recovery: your previous final answer repeated a JSON argument object for a declared tool after a structured tool-call recovery request.",`Matched configured tool: ${e.match.toolId}`,"Stable runtime executed that matched declared tool through the governed tool gateway.","Continue the same user request from the executed evidence below.","If another declared tool is needed, call it through the backend's normal structured tool-calling mechanism.","Otherwise, 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.","","Executed JSON arguments:",JSON.stringify(e.match.args),"","Executed tool output:",e.toolOutput].join("\n"),metadata:{...e.request.metadata,stableHarnessRecovery:"tool_call"}}}export function hasUniqueRawArgsTool(e){return toolCallRecoveryEnabled(e.policy)&&Boolean(matchUniqueRawArgsTool(e))}export function buildRawArgsToolSequenceEvidenceRecoveryRequest(e){return{...e.request,input:[e.request.input,"","Stable runtime recovery: your previous final answer printed multiple JSON argument objects for declared tools after a recovery request.","Stable runtime matched and executed those declared tools through the governed tool gateway.","Continue the same user request from the executed evidence below.","If another declared tool is needed, call it through the backend's normal structured tool-calling mechanism.","Otherwise, 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.","",...e.evidences.flatMap((e,t)=>[`Executed tool ${t+1}: ${e.match.toolId}`,"Executed JSON arguments:",JSON.stringify(e.match.args),"Executed tool output:",e.toolOutput,""])].join("\n"),metadata:{...e.request.metadata,stableHarnessRecovery:"tool_call"}}}export function matchUniqueRawArgsTool(t){const o=parseStandaloneJsonValues(t.output,{allowArray:!1})[0];if(!o)return;const r=matchToolEnvelope(o,t);if(r)return r;const a=isRawArgsRecord(o)?o:void 0;if(!a)return;const n=e({args:a,candidates:buildCallCandidates(t)});return n.ok?{toolId:n.candidateId,args:n.args}:void 0}export function matchRawArgsToolSequence(t){if(!toolCallRecoveryEnabled(t.policy))return[];const o=parseStandaloneJsonValues(t.output,{allowArray:!0});if(o.length<2)return[];const r=buildCallCandidates(t),a=[];for(const n of o){const o=matchToolEnvelope(n,t);if(o){a.push(o);continue}if(!isRawArgsRecord(n))return[];const s=e({args:n,candidates:r});if(!s.ok)return[];a.push({toolId:s.candidateId,args:s.args})}return a}function buildCallCandidates(e){return candidateToolIds(e).map(t=>({id:t,schema:e.workspace.tools.get(t)?.schema??e.toolGateway?.get(t)?.schema}))}function candidateToolIds(e){const t=new Set(e.agent.tools),o=(e.candidateToolIds??[]).filter(e=>t.has(e));return o.length>0?o:e.agent.tools}function parseStandaloneJsonValues(e,t){const o=e.trim(),r=o.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/iu)?.[1]?.trim(),a=function extractRawJsonSource(e,t){const o=e.trim();if(o.startsWith("{")||t.allowArray&&o.startsWith("["))return o;if(!/^<tool_code>\s*/iu.test(o))return o;const r=o.indexOf("{"),a=t.allowArray?o.indexOf("["):-1,n=a>=0&&a<r?a:r;if(n<0)return;const s="["===o[n]?o.lastIndexOf("]"):o.lastIndexOf("}");return s<=n?void 0:o.slice(n,s+1).trim()}(r??o,t);if(!a||a.length>3e4)return[];if(!(t.allowArray||a.startsWith("{")&&a.endsWith("}")))return[];if(t.allowArray&&!(a.startsWith("{")&&a.endsWith("}")||a.startsWith("[")&&a.endsWith("]")))return[];try{const e=JSON.parse(a);return Array.isArray(e)&&t.allowArray?e:[e]}catch{return[]}}function matchToolEnvelope(t,o){if(!isRecord(t))return;const r=function readEnvelopeToolId(e){const t=["toolId","toolName","tool","tool_name","name","command"].map(t=>e[t]).filter(e=>"string"==typeof e&&e.length>0);return 1===new Set(t).size?t[0]:void 0}(t),a=function readEnvelopeArgs(e){for(const t of["args","arguments","parameters","params","kwargs"]){const o=e[t];if(isRecord(o))return o}}(t),n=candidateToolIds(o);if(!r||!n.includes(r))return;const s=e({args:a??t,candidates:buildCallCandidates(o).filter(e=>e.id===r)});return s.ok?{toolId:r,args:s.args}:void 0}function isRawArgsRecord(e){return isRecord(e)&&!function isToolCallEnvelope(e){const t=["tool","tool_name","name","type","subagent_type"].some(t=>"string"==typeof e[t]),o=["args","arguments","parameters","kwargs"].some(t=>t in e);return t&&o}(e)&&!function isRuntimeControlObject(e){return"string"==typeof e.status||"string"==typeof e.error||"string"==typeof e.controlStatus}(e)}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 +1 @@
|
|
|
1
|
-
import{controlGaps as e}from"../quality/event-evidence.js";import{omittedControlRecoveryLines as t}from"./control-omission.js";import{containsProgressOnlyToolIntent as o,progressOnlyToolIntentMessage as r}from"./progress-intent.js";import{containsStructurallyIncompleteFinalOutput as n,structurallyIncompleteFinalMessage as a}from"./structural-output.js";import{hasStructuredToolEnvelope as l,hasXmlLikeToolMarkup as i,isFunctionStyleCall as s}from"./tool-call-structure.js";import{containsRawToolResultText as u}from"./tool-result.js";export function toolCallRecoveryEnabled(e){return!0===readToolCallRecovery(e).enabled}export function isRecoverableAdapterError(e,t){const o=readToolCallRecovery(t);if(!0!==o.enabled)return!1;const r=e instanceof Error?e.message:String(e);return readRegexps(o.adapterErrorPatterns,[/XML syntax error|tool.?call.*syntax|malformed.*(?:XML|tool)|Non string tool message content|repeat limit reached for tool/iu]).some(e=>e.test(r))}export function buildAdapterErrorRecoveryPrompt(e,t,o){const r=t instanceof Error?t.message:String(t),n=readToolCallRecovery(o).instruction;return recoverRequest(e,["Stable runtime recovery: the backend failed while parsing a tool call.",`Parser error: ${r}`,"string"==typeof n?n:"Continue the same user request using the backend's normal tool-calling mechanism, then return a final human-readable answer.","Do not print raw tool-call markup, JSON tool-call envelopes, or pseudo tool-call text in the final answer."])}export function buildResultRecoveryRequest(e){const r=readToolCallRecovery(e.policy);if(!0!==r.enabled)return;if(containsRawToolCallText(e.output)){const t=recentToolEvidence(e.events,1e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer printed raw tool-call markup instead of executing the tool.","Continue the same user request by calling the available upstream tool normally when more evidence is required.","If you call a tool, the next assistant action must be the backend's structured tool call itself, with no prose before it.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],"If the conversation context already contains enough evidence to answer, synthesize the final answer from that context instead.","Do not print XML, JSON, markdown fences, pseudo tool-call text, plans, or future-intent text such as saying you will call or wait for a tool.",...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous invalid final answer:",e.output])}if(o(e.output,e.availableToolIds)){const t=recentToolEvidence(e.events,1e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer was progress-only text or a pseudo tool invocation block instead of a user-facing answer.","Continue the same user request by calling the named available tool through the backend's normal structured mechanism.","If the conversation context already contains enough evidence to answer, synthesize the final answer from that context instead.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],"Do not narrate intended future tool calls or print tool invocation blocks as a final answer.",...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous invalid final answer:",e.output])}if(u(e.output,e.events)){const t=recentToolEvidence(e.events,1e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer copied an executed tool result JSON as the user-facing answer.","Continue the same user request from the existing tool evidence.","If more evidence is required, use one remaining declared tool or subagent action through the backend's normal structured mechanism.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],"Otherwise synthesize a human-readable final answer from the executed tool evidence.","Do not return the raw tool result JSON as the final answer.",...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous invalid final answer:",e.output])}if(containsToolExecutionErrorText(e.output,r)){const t=recentToolEvidence(e.events,1e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer exposed a backend tool execution error instead of handling it.","Continue the same user request using the backend's normal structured tool-calling mechanism.","Do not retry the same invalid tool arguments. If the failed tool is not required to answer the user, synthesize the final answer from the available context instead.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],"Do not print tool error stacks, schema validation diagnostics, raw tool-call markup, JSON tool-call envelopes, or pseudo tool-call text in the final answer.",...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous invalid final answer:",e.output])}if(n(e.output)){const t=recentToolEvidence(e.events,6e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer was structurally incomplete or truncated.","Retry synthesis from the existing executed evidence and return a complete user-facing answer.","Do not stop inside an unfinished Markdown fence, inline code span, emphasis marker, sentence, or list item.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous incomplete final answer:",e.output])}const a=t(e);if(a)return recoverRequest(e.request,a);const l="tool_call"===e.request.metadata?.stableHarnessRecovery?void 0:function lastConfiguredEventHint(e,t){const o=function readEventRecoveryHints(e){return(Array.isArray(e)?e:[]).flatMap(e=>isRecord(e)&&"string"==typeof e.instruction?[{..."string"==typeof e.toolId?{toolId:e.toolId}:{},..."string"==typeof e.phase?{phase:e.phase}:{},instruction:e.instruction}]:[])}(t.eventRecoveryHints);if(0!==o.length)return e.flatMap(e=>function readMatchingHints(e,t){const o="runtime.adapter.event"===e.type&&isRecord(e.event)?e.event:void 0;return o?t.filter(e=>function eventMatchesHint(e,t){return!(t.toolId&&e.toolId!==t.toolId||t.phase&&e.phase!==t.phase)}(o,e)).map(e=>({output:"string"==typeof o.output?o.output:"Adapter event matched configured recovery hint.",instruction:e.instruction})):[]}(e,o)).at(-1)}(e.events,r);return l?recoverRequest(e.request,["Stable runtime recovery: a previous adapter event matched a configured recovery hint.",l.output,l.instruction]):void 0}export function assertNoRawToolCallOutput(e,t){if(containsRawToolCallOutput(e,t))throw new Error(`Adapter returned raw tool-call text as the final answer after recovery. The backend must execute tools instead of printing tool-call markup. Output preview: ${previewOutput(e)}`)}export function containsRawToolCallOutput(e,t){return!0===readToolCallRecovery(t).enabled&&containsRawToolCallText(e)}export function containsRecoverableResultOutput(e,t){const o=readToolCallRecovery(t);return!0===o.enabled&&containsRecoverableResultFailureText(e,o)}export function assertNoRawToolResultOutput(e,t,o){if(!0===readToolCallRecovery(o).enabled&&u(e,t))throw new Error(`Adapter returned raw tool result JSON as the final answer after recovery. The backend must synthesize a user-facing answer. Output preview: ${previewOutput(e)}`)}export function assertNoToolExecutionErrorOutput(e,t){const o=readToolCallRecovery(t);if(!0===o.enabled&&containsToolExecutionErrorText(e,o))throw new Error(`Adapter returned a tool execution error as the final answer after recovery. Output preview: ${previewOutput(e)}`)}export function assertNoProgressOnlyToolIntentOutput(e,t,n){if(!0===readToolCallRecovery(n).enabled&&o(e,t))throw new Error(r(e))}export function assertNoStructurallyIncompleteFinalOutput(e,t){if(!0===readToolCallRecovery(t).enabled&&n(e))throw new Error(a(e))}export function rawToolCallFailureMessage(){return["The model attempted to call a tool but returned the tool call as text instead of executing it.","Please retry the request or use a model/backend configuration with reliable tool calling for this workspace."].join(" ")}export function buildEvidenceSynthesisOutput(t){const o=readToolCallRecovery(t.policy);if(!0!==o.enabled||!1===o.synthesizeFromEvidenceOnFailure||!containsRecoverableResultFailureText(t.output,o))return;const r=function latestDelegatedTaskReport(e){return e.flatMap(e=>{const t="runtime.adapter.event"===e.type&&isRecord(e.event)?e.event:void 0;if(!isToolResultEvent(t)||"task"!==t.toolId)return[];const o="string"==typeof t.output?t.output.trim():"";return function looksLikeFinalReport(e){const t=e.trim();return!(t.length<80)&&(/^#{1,3}\s+\S/mu.test(t)||/\n#{1,3}\s+\S/mu.test(t)||/\n-{3,}\n/u.test(t))}(o)?[o]:[]}).at(-1)||void 0}(t.events);if(r)return r;const n=recentToolEvidence(t.events,6e3);if(0===n.length)return;const a=/\p{Script=Han}/u.test(t.request.input)?"zh":"en",l=e(t.events);return"zh"===a?function buildChineseEvidenceSynthesis(e,t,o){return["上游模型在已有工具证据后仍输出了伪工具调用;runtime 已拒绝该 raw 输出,并直接交付已执行工具返回的证据结果。","","已执行的工具证据:",...t,...o.length>0?["","未解决的证据缺口:",...o.map(e=>`- ${e}`)]:[],"",`被拒绝的最终输出预览:${previewRejectedOutput(e)}`].join("\n")}(t.output,n,l):function buildEnglishEvidenceSynthesis(e,t,o){return["The upstream model still returned pseudo tool-call text after tool evidence was available. The runtime rejected that raw output and is returning the executed tool evidence directly.","","Executed tool evidence:",...t,...o.length>0?["","Unresolved evidence gaps:",...o.map(e=>`- ${e}`)]:[],"",`Rejected final output preview: ${previewRejectedOutput(e)}`].join("\n")}(t.output,n,l)}function previewOutput(e){const t=e.replace(/\s+/gu," ").trim();return t.length>300?`${t.slice(0,297)}...`:t}function previewRejectedOutput(e){return previewOutput(e).replace(/[<>]/gu,"")}export function rawToolCallOutputPreview(e){return previewOutput(e)}function recoverRequest(e,t){return{...e,input:[e.input,"",...t].join("\n"),metadata:{...e.metadata,stableHarnessRecovery:"tool_call"}}}function containsRawToolCallText(e,t){return!function looksLikeCompletedMarkdownReport(e){const t=e.trimStart();return e.length>1200&&t.startsWith("#")}(e)&&!!(l(e)||i(e)||s(e))}function containsRecoverableResultFailureText(e,t){return containsRawToolCallText(e)||containsToolExecutionErrorText(e,t)}function containsToolExecutionErrorText(e,t){return readRegexps(t.toolFailureOutputPatterns,[/^Error invoking tool ['"][^'"]+['"] with kwargs /iu,/Received tool input did not match expected schema/iu,/ToolMessage.*status.*error/iu]).some(t=>t.test(e))}function recentToolEvidence(e,t){return e.flatMap(e=>{const o="runtime.adapter.event"===e.type&&isRecord(e.event)?e.event:void 0;return isToolResultEvent(o)&&"string"==typeof o.toolId?function isControlToolOutput(e){if("string"!=typeof e||!e.trim().startsWith("{"))return!1;try{const t=JSON.parse(e),o=isRecord(t)?t.status:void 0;return"duplicate_tool_call"===o||"repeated_tool_call_limit"===o||"tool_argument_error"===o}catch{return!1}}(o.output)?[]:[`- ${o.toolId}: ${formatToolEvidence(o,t)}`]:[]}).slice(-5)}function isToolResultEvent(e){return"deepagents.tool_execution.result"===e?.eventType||"agent.tool.result"===e?.phase}function formatToolEvidence(e,t=1e3){return"string"==typeof e.output&&e.output.trim()?e.output.slice(0,t):"string"==typeof e.error&&e.error.trim()?`error: ${e.error.slice(0,t)}`:isRecord(e.args)?`completed with args: ${previewOutput(JSON.stringify(e.args))}`:"completed"}function readToolCallRecovery(e){if(!isRecord(e))return{};const t=isRecord(e.recovery)?e.recovery:{};return isRecord(t.toolCall)?t.toolCall:{}}function readRegexps(e,t){const o=(Array.isArray(e)?e:[]).filter(e=>"string"==typeof e&&e.length>0).map(e=>new RegExp(e,"iu"));return o.length>0?o:t}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|
|
1
|
+
import{controlGaps as e}from"../quality/event-evidence.js";import{omittedControlRecoveryLines as t}from"./control-omission.js";import{containsProgressOnlyToolIntent as o,progressOnlyToolIntentMessage as r}from"./progress-intent.js";import{containsStructurallyIncompleteFinalOutput as n,structurallyIncompleteFinalMessage as a}from"./structural-output.js";import{hasStructuredToolEnvelope as l,hasXmlLikeToolMarkup as i,isFunctionStyleCall as s}from"./tool-call-structure.js";import{containsRawToolResultText as u}from"./tool-result.js";export function toolCallRecoveryEnabled(e){return!0===readToolCallRecovery(e).enabled}export function isRecoverableAdapterError(e,t){const o=readToolCallRecovery(t);if(!0!==o.enabled)return!1;const r=e instanceof Error?e.message:String(e);return readRegexps(o.adapterErrorPatterns,[/XML syntax error|tool.?call.*syntax|malformed.*(?:XML|tool)|expected element type .* but have|Non string tool message content|repeat limit reached for tool|\bEOF\b/iu]).some(e=>e.test(r))}export function buildAdapterErrorRecoveryPrompt(e,t,o){const r=t instanceof Error?t.message:String(t),n=readToolCallRecovery(o).instruction;return recoverRequest(e,["Stable runtime recovery: the backend failed while parsing a tool call.",`Parser error: ${r}`,"string"==typeof n?n:"Continue the same user request using the backend's normal tool-calling mechanism, then return a final human-readable answer.","Do not print raw tool-call markup, JSON tool-call envelopes, or pseudo tool-call text in the final answer."])}export function buildResultRecoveryRequest(e){const r=readToolCallRecovery(e.policy);if(!0!==r.enabled)return;if(containsRawToolCallText(e.output)){const t=recentToolEvidence(e.events,1e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer printed raw tool-call markup instead of executing the tool.","Continue the same user request by calling the available upstream tool normally when more evidence is required.","If you call a tool, the next assistant action must be the backend's structured tool call itself, with no prose before it.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],"If the conversation context already contains enough evidence to answer, synthesize the final answer from that context instead.","Do not print XML, JSON, markdown fences, pseudo tool-call text, plans, or future-intent text such as saying you will call or wait for a tool.",...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous invalid final answer:",e.output])}if(o(e.output,e.availableToolIds)){const t=recentToolEvidence(e.events,1e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer was progress-only text or a pseudo tool invocation block instead of a user-facing answer.","Continue the same user request by calling the named available tool through the backend's normal structured mechanism.","If the conversation context already contains enough evidence to answer, synthesize the final answer from that context instead.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],"Do not narrate intended future tool calls or print tool invocation blocks as a final answer.",...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous invalid final answer:",e.output])}if(u(e.output,e.events)){const t=recentToolEvidence(e.events,1e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer copied an executed tool result JSON as the user-facing answer.","Continue the same user request from the existing tool evidence.","If more evidence is required, use one remaining declared tool or subagent action through the backend's normal structured mechanism.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],"Otherwise synthesize a human-readable final answer from the executed tool evidence.","Do not return the raw tool result JSON as the final answer.",...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous invalid final answer:",e.output])}if(containsToolExecutionErrorText(e.output,r)){const t=recentToolEvidence(e.events,1e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer exposed a backend tool execution error instead of handling it.","Continue the same user request using the backend's normal structured tool-calling mechanism.","Do not retry the same invalid tool arguments. If the failed tool is not required to answer the user, synthesize the final answer from the available context instead.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],"Do not print tool error stacks, schema validation diagnostics, raw tool-call markup, JSON tool-call envelopes, or pseudo tool-call text in the final answer.",...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous invalid final answer:",e.output])}if(n(e.output)){const t=recentToolEvidence(e.events,6e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer was structurally incomplete or truncated.","Retry synthesis from the existing executed evidence and return a complete user-facing answer.","Do not stop inside an unfinished Markdown fence, inline code span, emphasis marker, sentence, or list item.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous incomplete final answer:",e.output])}const a=t(e);if(a)return recoverRequest(e.request,a);const l="tool_call"===e.request.metadata?.stableHarnessRecovery?void 0:function lastConfiguredEventHint(e,t){const o=function readEventRecoveryHints(e){return(Array.isArray(e)?e:[]).flatMap(e=>isRecord(e)&&"string"==typeof e.instruction?[{..."string"==typeof e.toolId?{toolId:e.toolId}:{},..."string"==typeof e.phase?{phase:e.phase}:{},instruction:e.instruction}]:[])}(t.eventRecoveryHints);if(0!==o.length)return e.flatMap(e=>function readMatchingHints(e,t){const o="runtime.adapter.event"===e.type&&isRecord(e.event)?e.event:void 0;return o?t.filter(e=>function eventMatchesHint(e,t){return!(t.toolId&&e.toolId!==t.toolId||t.phase&&e.phase!==t.phase)}(o,e)).map(e=>({output:"string"==typeof o.output?o.output:"Adapter event matched configured recovery hint.",instruction:e.instruction})):[]}(e,o)).at(-1)}(e.events,r);return l?recoverRequest(e.request,["Stable runtime recovery: a previous adapter event matched a configured recovery hint.",l.output,l.instruction]):void 0}export function assertNoRawToolCallOutput(e,t){if(containsRawToolCallOutput(e,t))throw new Error(`Adapter returned raw tool-call text as the final answer after recovery. The backend must execute tools instead of printing tool-call markup. Output preview: ${previewOutput(e)}`)}export function containsRawToolCallOutput(e,t){return!0===readToolCallRecovery(t).enabled&&containsRawToolCallText(e)}export function containsRecoverableResultOutput(e,t){const o=readToolCallRecovery(t);return!0===o.enabled&&containsRecoverableResultFailureText(e,o)}export function assertNoRawToolResultOutput(e,t,o){if(!0===readToolCallRecovery(o).enabled&&u(e,t))throw new Error(`Adapter returned raw tool result JSON as the final answer after recovery. The backend must synthesize a user-facing answer. Output preview: ${previewOutput(e)}`)}export function assertNoToolExecutionErrorOutput(e,t){const o=readToolCallRecovery(t);if(!0===o.enabled&&containsToolExecutionErrorText(e,o))throw new Error(`Adapter returned a tool execution error as the final answer after recovery. Output preview: ${previewOutput(e)}`)}export function assertNoProgressOnlyToolIntentOutput(e,t,n){if(!0===readToolCallRecovery(n).enabled&&o(e,t))throw new Error(r(e))}export function assertNoStructurallyIncompleteFinalOutput(e,t){if(!0===readToolCallRecovery(t).enabled&&n(e))throw new Error(a(e))}export function rawToolCallFailureMessage(){return["The model attempted to call a tool but returned the tool call as text instead of executing it.","Please retry the request or use a model/backend configuration with reliable tool calling for this workspace."].join(" ")}export function buildEvidenceSynthesisOutput(t){const o=readToolCallRecovery(t.policy);if(!0!==o.enabled||!1===o.synthesizeFromEvidenceOnFailure||!containsRecoverableResultFailureText(t.output,o))return;const r=function latestDelegatedTaskReport(e){return e.flatMap(e=>{const t="runtime.adapter.event"===e.type&&isRecord(e.event)?e.event:void 0;if(!isToolResultEvent(t)||"task"!==t.toolId)return[];const o="string"==typeof t.output?t.output.trim():"";return function looksLikeFinalReport(e){const t=e.trim();return!(t.length<80)&&(/^#{1,3}\s+\S/mu.test(t)||/\n#{1,3}\s+\S/mu.test(t)||/\n-{3,}\n/u.test(t))}(o)?[o]:[]}).at(-1)||void 0}(t.events);if(r)return r;const n=recentToolEvidence(t.events,6e3);if(0===n.length)return;const a=/\p{Script=Han}/u.test(t.request.input)?"zh":"en",l=e(t.events);return"zh"===a?function buildChineseEvidenceSynthesis(e,t,o){return["上游模型在已有工具证据后仍输出了伪工具调用;runtime 已拒绝该 raw 输出,并直接交付已执行工具返回的证据结果。","","已执行的工具证据:",...t,...o.length>0?["","未解决的证据缺口:",...o.map(e=>`- ${e}`)]:[],"",`被拒绝的最终输出预览:${previewRejectedOutput(e)}`].join("\n")}(t.output,n,l):function buildEnglishEvidenceSynthesis(e,t,o){return["The upstream model still returned pseudo tool-call text after tool evidence was available. The runtime rejected that raw output and is returning the executed tool evidence directly.","","Executed tool evidence:",...t,...o.length>0?["","Unresolved evidence gaps:",...o.map(e=>`- ${e}`)]:[],"",`Rejected final output preview: ${previewRejectedOutput(e)}`].join("\n")}(t.output,n,l)}function previewOutput(e){const t=e.replace(/\s+/gu," ").trim();return t.length>300?`${t.slice(0,297)}...`:t}function previewRejectedOutput(e){return previewOutput(e).replace(/[<>]/gu,"")}export function rawToolCallOutputPreview(e){return previewOutput(e)}function recoverRequest(e,t){return{...e,input:[e.input,"",...t].join("\n"),metadata:{...e.metadata,stableHarnessRecovery:"tool_call"}}}function containsRawToolCallText(e,t){return!function looksLikeCompletedMarkdownReport(e){const t=e.trimStart();return e.length>1200&&t.startsWith("#")}(e)&&!!(l(e)||i(e)||s(e))}function containsRecoverableResultFailureText(e,t){return containsRawToolCallText(e)||containsToolExecutionErrorText(e,t)}function containsToolExecutionErrorText(e,t){return readRegexps(t.toolFailureOutputPatterns,[/^Error invoking tool ['"][^'"]+['"] with kwargs /iu,/Received tool input did not match expected schema/iu,/ToolMessage.*status.*error/iu]).some(t=>t.test(e))}function recentToolEvidence(e,t){return e.flatMap(e=>{const o="runtime.adapter.event"===e.type&&isRecord(e.event)?e.event:void 0;return isToolResultEvent(o)&&"string"==typeof o.toolId?function isControlToolOutput(e){if("string"!=typeof e||!e.trim().startsWith("{"))return!1;try{const t=JSON.parse(e),o=isRecord(t)?t.status:void 0;return"duplicate_tool_call"===o||"repeated_tool_call_limit"===o||"tool_argument_error"===o}catch{return!1}}(o.output)?[]:[`- ${o.toolId}: ${formatToolEvidence(o,t)}`]:[]}).slice(-5)}function isToolResultEvent(e){return"deepagents.tool_execution.result"===e?.eventType||"agent.tool.result"===e?.phase}function formatToolEvidence(e,t=1e3){return"string"==typeof e.output&&e.output.trim()?e.output.slice(0,t):"string"==typeof e.error&&e.error.trim()?`error: ${e.error.slice(0,t)}`:isRecord(e.args)?`completed with args: ${previewOutput(JSON.stringify(e.args))}`:"completed"}function readToolCallRecovery(e){if(!isRecord(e))return{};const t=isRecord(e.recovery)?e.recovery:{};return isRecord(t.toolCall)?t.toolCall:{}}function readRegexps(e,t){const o=(Array.isArray(e)?e:[]).filter(e=>"string"==typeof e&&e.length>0).map(e=>new RegExp(e,"iu"));return o.length>0?o:t}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CompiledWorkspace, RuntimeEvent, RuntimeOutput, RuntimeRequest, RuntimeStore, RuntimeToolGateway, WorkspaceAgent } from "../../types.js";
|
|
2
|
-
|
|
2
|
+
type RecoverAdapterResultInput = {
|
|
3
3
|
request: RuntimeRequest;
|
|
4
4
|
result: RuntimeOutput;
|
|
5
5
|
recoveryPolicy: unknown;
|
|
@@ -12,4 +12,6 @@ export declare function recoverAdapterResultOutput(input: {
|
|
|
12
12
|
toolGateway?: RuntimeToolGateway;
|
|
13
13
|
runAdapter: (request: RuntimeRequest) => Promise<RuntimeOutput>;
|
|
14
14
|
runRecoveredToolCall?: (toolId: string, args: Record<string, unknown>) => Promise<RuntimeOutput>;
|
|
15
|
-
}
|
|
15
|
+
};
|
|
16
|
+
export declare function recoverAdapterResultOutput(input: RecoverAdapterResultInput): Promise<RuntimeOutput>;
|
|
17
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{assertNoDeclaredActionOmissionOutput as e}from"../../recovery/control-omission.js";import{containsProgressOnlyToolIntent as t}from"../../recovery/progress-intent.js";import{buildRawArgsRecoveryRequest as o,buildRawArgsToolEvidenceRecoveryRequest as r,buildRawArgsToolSequenceEvidenceRecoveryRequest as a,hasUniqueRawArgsTool as s,matchRawArgsToolSequence as n,matchUniqueRawArgsTool as u}from"../../recovery/raw-args.js";import{assertNoProgressOnlyToolIntentOutput as l,assertNoRawToolCallOutput as c,assertNoRawToolResultOutput as i,assertNoStructurallyIncompleteFinalOutput as d,assertNoToolExecutionErrorOutput as v,buildEvidenceSynthesisOutput as p,buildResultRecoveryRequest as y,containsRawToolCallOutput as g,rawToolCallFailureMessage as f,rawToolCallOutputPreview as m,toolCallRecoveryEnabled as w}from"../../recovery/tool-call.js";import{controlGaps as R,successfulEvidenceItems as h,successfulEvidenceToolIds as T}from"../../quality/event-evidence.js";export async function recoverAdapterResultOutput(t){let r=t.result,a=t.request;const n=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}(t.recoveryPolicy),R=new Set,h=new Set;for(let e=0;;e+=1){const s=t.store.getRun(t.requestId)?.events??[],l=effectiveRecoveryToolIds(a,t.agent.tools),c=buildNonFocusedRecoveryRequest({request:a,output:r.text,events:s,policy:t.recoveryPolicy,declaredToolIds:t.agent.tools,visibleToolIds:l});if(c){e>=n&&assertNoNonFocusedRecoveryIntent(r.text,t.recoveryPolicy,t.agent.tools,l,s),a=c,emitRepair(t,"runtime.repair.started","result_output",e+1,"non_focused_recovery_intent",void 0,repairDiagnostics(r.text,l)),r=await t.runAdapter(c),emitRepair(t,"runtime.repair.completed","result_output",e+1,"non_focused_recovery_intent","retried",repairDiagnostics(r.text,l));continue}assertNoNonFocusedRecoveryIntent(r.text,t.recoveryPolicy,t.agent.tools,l,s);const i=await recoverRawArgsSequenceByToolGateway(t,a,r,h,e+1,l);if(i){a=i.request,r=i.result;continue}const d=u({output:r.text,agent:t.agent,workspace:t.workspace,toolGateway:t.toolGateway,events:s,candidateToolIds:l,policy:t.recoveryPolicy}),v=d?rawArgsToolKey(d):void 0;if(d&&v&&h.size>0&&!h.has(v)){const o=await recoverRawArgsByToolGateway(t,a,r,d,h,e+1);if(o){a=o.request,r=o.result;continue}}const p=v&&!R.has(v)?o({request:a,output:r.text,agent:t.agent,workspace:t.workspace,toolGateway:t.toolGateway,events:s,candidateToolIds:l,policy:t.recoveryPolicy}):void 0,g=e<n?y({request:a,output:r.text,events:s,availableToolIds:l,policy:t.recoveryPolicy}):void 0,f=p??g;if(!f)break;if(f===p&&R.add(v),a=f,emitRepair(t,"runtime.repair.started","result_output",e+1,"recoverable_result_output",void 0,repairDiagnostics(r.text,l)),r=await t.runAdapter(f),emitRepair(t,"runtime.repair.completed","result_output",e+1,"recoverable_result_output","retried",repairDiagnostics(r.text,l)),f===p){const o=await recoverRepeatedRawArgsByToolGateway(t,a,r,R,h,e+1);o&&(a=o.request,r=o.result)}}return function finalizeRecoveredOutput(t,o){if(!w(t.recoveryPolicy))return o;let r=!1;if(g(o.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=o.text;o={...o,text:f(),metadata:{...o.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 a=p({request:t.request,output:o.text,events:t.store.getRun(t.requestId)?.events??[],policy:t.recoveryPolicy});return a&&(r=!0,o={...o,text:a,metadata:{...o.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")),r||(g(o.text,t.recoveryPolicy)&&emitRepair(t,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked",repairDiagnostics(o.text,t.agent.tools)),c(o.text,t.recoveryPolicy),function assertNoRawArgsToolOutput(e,t){if(s({output:t,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:e.store.getRun(e.requestId)?.events??[],candidateToolIds:effectiveRecoveryToolIds(e.request,e.agent.tools),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: ${m(t)}`)}(t,o.text),l(o.text,t.agent.tools,t.recoveryPolicy),i(o.text,t.store.getRun(t.requestId)?.events??[],t.recoveryPolicy),v(o.text,t.recoveryPolicy),d(o.text,t.recoveryPolicy),e({output:o.text,events:t.store.getRun(t.requestId)?.events??[],availableToolIds:t.agent.tools})),o}(t,r)}async function recoverRawArgsSequenceByToolGateway(e,t,o,r,s,u){if(!e.runRecoveredToolCall)return;const l=n({output:o.text,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:e.store.getRun(e.requestId)?.events??[],candidateToolIds:u,policy:e.recoveryPolicy});if(l.length<2||l.some(e=>r.has(rawArgsToolKey(e))))return;emitRepair(e,"runtime.repair.started","result_output",s,"raw_args_tool_sequence_gateway_recovery",void 0,repairDiagnostics(o.text,u));const c=[];for(const t of l){r.add(rawArgsToolKey(t));const o=await e.runRecoveredToolCall(t.toolId,t.args);c.push({match:t,toolOutput:visibleRecoveredToolOutput(o)})}const i=a({request:t,evidences:c}),d=await e.runAdapter(i),v=d.text.trim()?d:{...d,text:buildEmptyRecoveredToolSequenceBlocker({evidences:c,events:e.store.getRun(e.requestId)?.events??[]}),metadata:{...d.metadata,toolCallRecovery:{blocked:!0,reason:"empty_output_after_recovered_tool_sequence"}}};return emitRepair(e,"runtime.repair.completed","result_output",s,"raw_args_tool_sequence_gateway_recovery","retried",repairDiagnostics(v.text,u)),{request:i,result:v}}async function recoverRepeatedRawArgsByToolGateway(e,t,o,r,a,s){const n=u({output:o.text,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:e.store.getRun(e.requestId)?.events??[],candidateToolIds:effectiveRecoveryToolIds(t,e.agent.tools),policy:e.recoveryPolicy});if(!n||!e.runRecoveredToolCall)return;const l=rawArgsToolKey(n);return r.has(l)&&!a.has(l)?recoverRawArgsByToolGateway(e,t,o,n,a,s):void 0}async function recoverRawArgsByToolGateway(e,t,o,a,s,n){if(!e.runRecoveredToolCall)return;const u=rawArgsToolKey(a);if(s.has(u))return;s.add(u),emitRepair(e,"runtime.repair.started","result_output",n,"raw_args_tool_gateway_recovery",void 0,repairDiagnostics(o.text,e.agent.tools));const l=visibleRecoveredToolOutput(await e.runRecoveredToolCall(a.toolId,a.args)),c=r({request:t,match:a,toolOutput:l}),i=await e.runAdapter(c),d=i.text.trim()?i:{...i,text:buildEmptyRecoveredToolBlocker({match:a,toolOutput:l,events:e.store.getRun(e.requestId)?.events??[]}),metadata:{...i.metadata,toolCallRecovery:{blocked:!0,reason:"empty_output_after_recovered_tool"}}};return emitRepair(e,"runtime.repair.completed","result_output",n,"raw_args_tool_gateway_recovery","retried",repairDiagnostics(d.text,e.agent.tools)),{request:c,result:d}}function assertNoNonFocusedRecoveryIntent(e,t,o,r,a){const s=nonFocusedRecoveryIntent(e,t,o,r);if(!s)return;const n=new Set(T(a)),u=s.nonFocused.filter(e=>!n.has(e)),l=u.length>0?u:s.nonFocused;throw new Error(`Focused recovery output referenced non-focused tool(s): ${l.join(", ")}. The backend must call one of the focused gateway tools: ${r.join(", ")}.`)}function buildNonFocusedRecoveryRequest(e){const t=nonFocusedRecoveryIntent(e.output,e.policy,e.declaredToolIds,e.visibleToolIds);if(!t)return;const o=h(e.events),r=new Set(T(e.events));if(t.nonFocused.some(e=>!r.has(e)))return;const a=o.slice(-5).map(e=>`- ${e.source}: ${function previewRecoveredEvidence(e){const t=e.replace(/\s+/gu," ").trim();return t.length>1e3?`${t.slice(0,997)}...`:t}(e.output)}`);return{...e.request,input:[e.request.input,"","Stable runtime recovery: the previous recovery output referenced tool(s) that already have successful evidence but are not allowed targets for this focused turn.",`Already completed non-focused tool(s): ${t.nonFocused.join(", ")}`,`Allowed focused tool target(s): ${e.visibleToolIds.join(", ")}`,"Reuse the prior successful evidence below to build one allowed focused tool call. Do not call already completed non-focused tools again.","The next assistant action must be the backend's structured tool call for one allowed focused target, with no prose before it.","","Prior successful tool evidence:",...a,"","Previous invalid recovery output:",e.output].join("\n"),metadata:{...e.request.metadata,stableHarnessRecovery:"tool_call"}}}function nonFocusedRecoveryIntent(e,o,r,a){if(0===a.length||a.length===r.length)return;const s=new Set(a),n=visibleToolCandidates(e,r).filter(e=>!s.has(e)),u=g(e,o)||t(e,r)||function containsJsonToolEnvelope(e){const t=e.trim(),o=t.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/iu)?.[1]?.trim(),r=o??t;if(!r.startsWith("{")||!r.endsWith("}")||r.length>6e3)return!1;try{const e=JSON.parse(r);if(!function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}(e))return!1;const t=["tool","tool_name","name","type","subagent_type"].some(t=>"string"==typeof e[t]),o=["args","arguments","parameters","params","kwargs"].some(t=>t in e);return t&&o}catch{return!1}}(e);return n.length>0&&u?{nonFocused:n}:void 0}function emitRepair(e,t,o,r,a,s,n){const u={requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:o,attempt:r,reason:a,...n?{diagnostics:n}:{}};e.emit("runtime.repair.started"===t?{type:t,...u}:{type:t,...u,outcome:s??"retried"})}function repairDiagnostics(e,t){return{outputPreview:m(e),toolCandidateIds:visibleToolCandidates(e,t)}}function visibleToolCandidates(e,t){const o=new Set;for(const r of t??[])containsDelimitedToken(e,r)&&o.add(r);return[...o]}function containsDelimitedToken(e,t){if(!t)return!1;let o=e.indexOf(t);for(;o>=0;){const r=0===o?"":e[o-1],a=e[o+t.length]??"";if(!isTokenChar(r)&&!isTokenChar(a))return!0;o=e.indexOf(t,o+t.length)}return!1}function isTokenChar(e){return"_"===e||"-"===e||e>="A"&&e<="Z"||e>="a"&&e<="z"||e>="0"&&e<="9"}function effectiveRecoveryToolIds(e,t){const o=function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}(e.metadata?.stableHarnessRequiredEvidenceTools).filter(e=>t.includes(e));return o.length>0?o:t}function rawArgsToolKey(e){return`${e.toolId}:${JSON.stringify(e.args)}`}function visibleRecoveredToolOutput(e){return("string"==typeof e.text?e.text.trim():"")||"The recovered tool completed successfully but returned no user-visible output."}function buildEmptyRecoveredToolBlocker(e){const t=R(e.events);return["Stable runtime recovery executed the matched declared tool, but the backend returned no user-facing output after receiving the executed evidence.","",`Executed tool: ${e.match.toolId}`,"","Executed JSON arguments:",JSON.stringify(e.match.args),"","Executed tool evidence:",e.toolOutput,...t.length>0?["","Unresolved control gaps:",...t.map(e=>`- ${e}`)]:[]].join("\n")}function buildEmptyRecoveredToolSequenceBlocker(e){const t=R(e.events);return["Stable runtime recovery executed matched declared tools, but the backend returned no user-facing output after receiving the executed evidence.","",...e.evidences.flatMap((e,t)=>[`Executed tool ${t+1}: ${e.match.toolId}`,"Executed JSON arguments:",JSON.stringify(e.match.args),"Executed tool evidence:",e.toolOutput,""]),...t.length>0?["Unresolved control gaps:",...t.map(e=>`- ${e}`)]:[]].join("\n")}
|
|
1
|
+
import{assertNoDeclaredActionOmissionOutput as e}from"../../recovery/control-omission.js";import{buildRawArgsRecoveryRequest as t,buildRawArgsToolEvidenceRecoveryRequest as o,buildRawArgsToolSequenceEvidenceRecoveryRequest as r,hasUniqueRawArgsTool as a,matchRawArgsToolSequence as s,matchUniqueRawArgsTool as l}from"../../recovery/raw-args.js";import{assertNoProgressOnlyToolIntentOutput as n,assertNoRawToolCallOutput as u,assertNoRawToolResultOutput as c,assertNoStructurallyIncompleteFinalOutput as i,assertNoToolExecutionErrorOutput as d,buildAdapterErrorRecoveryPrompt as y,buildEvidenceSynthesisOutput as v,buildResultRecoveryRequest as p,containsRawToolCallOutput as g,isRecoverableAdapterError as R,rawToolCallFailureMessage as m,rawToolCallOutputPreview as w,toolCallRecoveryEnabled as f}from"../../recovery/tool-call.js";import{controlGaps as _,successfulEvidenceToolIds as T}from"../../quality/event-evidence.js";import{buildFocusedTextToolEvidenceRecoveryRequest as x,focusedTextArgumentName as h}from"./focused-text-recovery.js";import{assertNoNonFocusedRecoveryIntent as q,buildNonFocusedRecoveryRequest as A,visibleToolCandidates as I}from"./non-focused-recovery.js";import{maxNonFocusedRecoveryRedirects as b,resultRecoveryAttempts as O}from"./recovery-policy.js";export async function recoverAdapterResultOutput(o){let r=o.result,s=o.request;const y=O(o.recoveryPolicy),R=new Set,_=new Set;let T=0;for(let e=0;;e+=1){const a=e+1,n=o.store.getRun(o.requestId)?.events??[],u=effectiveRecoveryToolIds(s,o.agent.tools),c=await recoverNonFocusedRawArgsByToolGateway(o,s,r,_,a,u,n);if(c){s=c.request,r=c.result;continue}const i=A({request:s,output:r.text,events:n,policy:o.recoveryPolicy,declaredToolIds:o.agent.tools,visibleToolIds:u});if(i){s=i,emitRepair(o,"runtime.repair.started","result_output",a,"non_focused_recovery_intent",void 0,repairDiagnostics(r.text,u)),r=await runResultRecoveryAdapter(o,i,a),emitRepair(o,"runtime.repair.completed","result_output",a,"non_focused_recovery_intent","retried",repairDiagnostics(r.text,u));continue}q(r.text,o.recoveryPolicy,o.agent.tools,u,n);const d=await recoverFocusedTextByToolGateway(o,s,r,_,a,u);if(d){s=d.request,r=d.result;continue}const v=await recoverRawArgsSequenceByToolGateway(o,s,r,_,a,u);if(v){s=v.request,r=v.result;continue}const g=l({output:r.text,agent:o.agent,workspace:o.workspace,toolGateway:o.toolGateway,events:n,candidateToolIds:u,policy:o.recoveryPolicy}),m=g?rawArgsToolKey(g):void 0;if(g&&m&&_.size>0&&!_.has(m)){const e=await recoverRawArgsByToolGateway(o,s,r,g,_,a);if(e){s=e.request,r=e.result;continue}}const w=m&&!R.has(m)?t({request:s,output:r.text,agent:o.agent,workspace:o.workspace,toolGateway:o.toolGateway,events:n,candidateToolIds:u,policy:o.recoveryPolicy}):void 0,f=T<y?p({request:s,output:r.text,events:n,availableToolIds:u,policy:o.recoveryPolicy}):void 0,x=w??f;if(!x)break;if(x===w&&R.add(m),s=x,x===f&&(T+=1),emitRepair(o,"runtime.repair.started","result_output",a,"recoverable_result_output",void 0,repairDiagnostics(r.text,u)),r=await runResultRecoveryAdapter(o,x,a),emitRepair(o,"runtime.repair.completed","result_output",a,"recoverable_result_output","retried",repairDiagnostics(r.text,u)),x===w){const e=await recoverRepeatedRawArgsByToolGateway(o,s,r,R,_,a);e&&(s=e.request,r=e.result)}}return function finalizeRecoveredOutput(t,o){if(!f(t.recoveryPolicy))return o;let r=!1;if(g(o.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=o.text;o={...o,text:m(),metadata:{...o.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 s=v({request:t.request,output:o.text,events:t.store.getRun(t.requestId)?.events??[],policy:t.recoveryPolicy});return s&&(r=!0,o={...o,text:s,metadata:{...o.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")),r||(g(o.text,t.recoveryPolicy)&&emitRepair(t,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked",repairDiagnostics(o.text,t.agent.tools)),u(o.text,t.recoveryPolicy),function assertNoRawArgsToolOutput(e,t){if(a({output:t,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:e.store.getRun(e.requestId)?.events??[],candidateToolIds:effectiveRecoveryToolIds(e.request,e.agent.tools),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: ${w(t)}`)}(t,o.text),n(o.text,t.agent.tools,t.recoveryPolicy),c(o.text,t.store.getRun(t.requestId)?.events??[],t.recoveryPolicy),d(o.text,t.recoveryPolicy),i(o.text,t.recoveryPolicy),e({output:o.text,events:t.store.getRun(t.requestId)?.events??[],availableToolIds:t.agent.tools})),o}(o,r)}async function recoverFocusedTextByToolGateway(e,t,o,r,a,s){if(!e.runRecoveredToolCall||1!==s.length||1!==readStringArray(t.metadata?.stableHarnessRequiredEvidenceTools).length)return;const l=s[0],n=h(e,l),u=o.text.trim();if(!n||0===u.length||T(e.store.getRun(e.requestId)?.events??[]).includes(l))return;const c={toolId:l,args:{[n]:u}},i=rawArgsToolKey(c);if(r.has(i))return;r.add(i),emitRepair(e,"runtime.repair.started","result_output",a,"focused_text_tool_gateway_recovery",void 0,repairDiagnostics(o.text,s));const d=visibleRecoveredToolOutput(await runRecoveredToolCallAsEvidence(e,c)),y=x({request:t,match:c,toolOutput:d}),v=await runResultRecoveryAdapter(e,y,a);return emitRepair(e,"runtime.repair.completed","result_output",a,"focused_text_tool_gateway_recovery","retried",repairDiagnostics(v.text,s)),{request:y,result:v}}async function recoverNonFocusedRawArgsByToolGateway(e,t,o,r,a,s,n){if(!e.runRecoveredToolCall||s.length===e.agent.tools.length||0===b(e.recoveryPolicy))return;const u=l({output:o.text,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:n,candidateToolIds:e.agent.tools,policy:e.recoveryPolicy});return!u||s.includes(u.toolId)||T(n).includes(u.toolId)?void 0:recoverRawArgsByToolGateway(e,t,o,u,r,a)}async function recoverRawArgsSequenceByToolGateway(e,t,o,a,l,n){if(!e.runRecoveredToolCall)return;const u=s({output:o.text,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:e.store.getRun(e.requestId)?.events??[],candidateToolIds:n,policy:e.recoveryPolicy});if(u.length<2||u.some(e=>a.has(rawArgsToolKey(e))))return;emitRepair(e,"runtime.repair.started","result_output",l,"raw_args_tool_sequence_gateway_recovery",void 0,repairDiagnostics(o.text,n));const c=[];for(const t of u){a.add(rawArgsToolKey(t));const o=await e.runRecoveredToolCall(t.toolId,t.args);c.push({match:t,toolOutput:visibleRecoveredToolOutput(o)})}const i=r({request:t,evidences:c}),d=await runResultRecoveryAdapter(e,i,l),y=d.text.trim()?d:{...d,text:buildEmptyRecoveredToolSequenceBlocker({evidences:c,events:e.store.getRun(e.requestId)?.events??[]}),metadata:{...d.metadata,toolCallRecovery:{blocked:!0,reason:"empty_output_after_recovered_tool_sequence"}}};return emitRepair(e,"runtime.repair.completed","result_output",l,"raw_args_tool_sequence_gateway_recovery","retried",repairDiagnostics(y.text,n)),{request:i,result:y}}async function recoverRepeatedRawArgsByToolGateway(e,t,o,r,a,s){const n=l({output:o.text,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:e.store.getRun(e.requestId)?.events??[],candidateToolIds:effectiveRecoveryToolIds(t,e.agent.tools),policy:e.recoveryPolicy});if(!n||!e.runRecoveredToolCall)return;const u=rawArgsToolKey(n);return r.has(u)&&!a.has(u)?recoverRawArgsByToolGateway(e,t,o,n,a,s):void 0}async function recoverRawArgsByToolGateway(e,t,r,a,s,l){if(!e.runRecoveredToolCall)return;const n=rawArgsToolKey(a);if(s.has(n))return;s.add(n),emitRepair(e,"runtime.repair.started","result_output",l,"raw_args_tool_gateway_recovery",void 0,repairDiagnostics(r.text,e.agent.tools));const u=visibleRecoveredToolOutput(await runRecoveredToolCallAsEvidence(e,a)),c=o({request:t,match:a,toolOutput:u}),i=await runResultRecoveryAdapter(e,c,l),d=i.text.trim()?i:{...i,text:buildEmptyRecoveredToolBlocker({match:a,toolOutput:u,events:e.store.getRun(e.requestId)?.events??[]}),metadata:{...i.metadata,toolCallRecovery:{blocked:!0,reason:"empty_output_after_recovered_tool"}}};return emitRepair(e,"runtime.repair.completed","result_output",l,"raw_args_tool_gateway_recovery","retried",repairDiagnostics(d.text,e.agent.tools)),{request:c,result:d}}async function runRecoveredToolCallAsEvidence(e,t){try{return await e.runRecoveredToolCall(t.toolId,t.args)}catch(e){return{text:[JSON.stringify({status:"recovered_tool_call_failed",toolId:t.toolId,args:t.args,message:errorMessage(e),instruction:"The recovered raw tool arguments failed validation or execution. Correct the arguments or choose the next required tool through structured tool calling."},null,2)].join("\n"),metadata:{toolCallRecovery:{failed:!0,reason:"recovered_tool_call_failed"}}}}}async function runResultRecoveryAdapter(e,t,o){try{return await e.runAdapter(t)}catch(r){if(!R(r,e.recoveryPolicy))throw r;emitRepair(e,"runtime.repair.started","adapter_error",o,errorMessage(r));const a=y(t,r,e.recoveryPolicy),s=await e.runAdapter(a);return emitRepair(e,"runtime.repair.completed","adapter_error",o,errorMessage(r),"retried"),s}}function emitRepair(e,t,o,r,a,s,l){const n={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,...n}:{type:t,...n,outcome:s??"retried"})}function errorMessage(e){return e instanceof Error?e.message:String(e)}function repairDiagnostics(e,t){return{outputPreview:w(e),toolCandidateIds:I(e,t)}}function effectiveRecoveryToolIds(e,t){const o=readStringArray(e.metadata?.stableHarnessRequiredEvidenceTools).filter(e=>t.includes(e));return o.length>0?o:t}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}function rawArgsToolKey(e){return`${e.toolId}:${JSON.stringify(e.args)}`}function visibleRecoveredToolOutput(e){return("string"==typeof e.text?e.text.trim():"")||"The recovered tool completed successfully but returned no user-visible output."}function buildEmptyRecoveredToolBlocker(e){const t=_(e.events);return["Stable runtime recovery executed the matched declared tool, but the backend returned no user-facing output after receiving the executed evidence.","",`Executed tool: ${e.match.toolId}`,"","Executed JSON arguments:",JSON.stringify(e.match.args),"","Executed tool evidence:",e.toolOutput,...t.length>0?["","Unresolved control gaps:",...t.map(e=>`- ${e}`)]:[]].join("\n")}function buildEmptyRecoveredToolSequenceBlocker(e){const t=_(e.events);return["Stable runtime recovery executed matched declared tools, but the backend returned no user-facing output after receiving the executed evidence.","",...e.evidences.flatMap((e,t)=>[`Executed tool ${t+1}: ${e.match.toolId}`,"Executed JSON arguments:",JSON.stringify(e.match.args),"Executed tool evidence:",e.toolOutput,""]),...t.length>0?["Unresolved control gaps:",...t.map(e=>`- ${e}`)]:[]].join("\n")}
|
package/node_modules/@stable-harness/core/dist/runtime/recovery/execution-contract-runtime.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CompiledWorkspace, RuntimeEmit, RuntimeEvent, RuntimeOutput, RuntimeRequest, RuntimeToolGateway, WorkspaceAgent, WorkspaceRuntimePolicy } from "../../types.js";
|
|
2
|
+
export declare function recoverExecutionContract(input: {
|
|
3
|
+
request: RuntimeRequest;
|
|
4
|
+
events: () => RuntimeEvent[];
|
|
5
|
+
agent: WorkspaceAgent;
|
|
6
|
+
emit: RuntimeEmit;
|
|
7
|
+
requestId: string;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
result: RuntimeOutput;
|
|
10
|
+
policy: WorkspaceRuntimePolicy;
|
|
11
|
+
workspace: CompiledWorkspace;
|
|
12
|
+
toolGateway?: RuntimeToolGateway;
|
|
13
|
+
assertContract: (result: RuntimeOutput) => void;
|
|
14
|
+
runAdapter: (request: RuntimeRequest) => Promise<RuntimeOutput>;
|
|
15
|
+
runRecoveredToolCall?: (toolId: string, args: Record<string, unknown>) => Promise<RuntimeOutput>;
|
|
16
|
+
recoverResultOutput: (request: RuntimeRequest, result: RuntimeOutput) => Promise<RuntimeOutput>;
|
|
17
|
+
recoverQuality: (request: RuntimeRequest, result: RuntimeOutput) => Promise<RuntimeOutput>;
|
|
18
|
+
}): Promise<RuntimeOutput>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{buildExecutionContractRecoveryRequest as e}from"../../recovery/execution-contract.js";import{buildAdapterErrorRecoveryPrompt as r,isRecoverableAdapterError as t}from"../../recovery/tool-call.js";import{successfulEvidenceItems as o}from"../../quality/event-evidence.js";import{focusedTextArgumentName as a}from"./focused-text-recovery.js";export async function recoverExecutionContract(r){let t=r.result;const o=function executionContractRecoveryAttempts(e,r){const t=readToolCallNumber(e,"maxExecutionContractRecoveryAttempts");if(void 0!==t&&t>0)return t;const o=isRecord(r.config.executionContract)?r.config.executionContract:{},a=readStringArray(o.requiredEvidenceTools),n=function readToolDependencyIds(e){return isRecord(e)?Object.values(e).flatMap(readStringArray):[]}(o.toolDependencies),i=new Set([...a,...n]).size+2;return Math.max(3,i)}(r.policy,r.agent);for(let a=1;;a+=1)try{return r.assertContract(t),t}catch(n){if(a>o)throw n;const i=e({request:r.request,events:r.events(),agent:r.agent,policy:r.policy});if(!i)throw n;emitRepair(r,"runtime.repair.started","execution_contract",a,errorMessage(n)),t=await recoverFocusedTextToolAfterAdapterError(r,i,a)??await runContractRecoveryAdapter(r,i,a),t=await r.recoverResultOutput(i,t),t=await r.recoverQuality(i,t),emitRepair(r,"runtime.repair.completed","execution_contract",a,errorMessage(n))}}async function runContractRecoveryAdapter(o,a,n){try{return await o.runAdapter(a)}catch(i){if(!t(i,o.policy))throw i;emitRepair(o,"runtime.repair.started","adapter_error",n,errorMessage(i));const c=r(a,i,o.policy),s=e({request:c,events:o.events(),agent:o.agent,policy:o.policy})??c;let u=i;for(let e=1;e<=adapterErrorRecoveryAttempts(o.policy);e+=1)try{const e=await o.runAdapter(s);return emitRepair(o,"runtime.repair.completed","adapter_error",n,errorMessage(u)),e}catch(r){if(!t(r,o.policy)||e>=adapterErrorRecoveryAttempts(o.policy)){const e=await recoverFocusedTextToolAfterAdapterError(o,s,n);if(e)return emitRepair(o,"runtime.repair.completed","adapter_error",n,errorMessage(r)),e;throw r}u=r,emitRepair(o,"runtime.repair.completed","adapter_error",n,errorMessage(r)),emitRepair(o,"runtime.repair.started","adapter_error",n,errorMessage(r))}throw u}}async function recoverFocusedTextToolAfterAdapterError(e,r,t){if(!e.runRecoveredToolCall)return;const n=readStringArray(r.metadata?.stableHarnessRequiredEvidenceTools).filter(r=>e.agent.tools.includes(r));if(1!==n.length)return;const i=n[0],c=a(e,i);if(!c||!function isFocusedEvidenceTextArgument(e){return/^(?:text|content|reviewText|analysisText|evidenceText|inputText|body)$/u.test(e)}(c))return;const s=o(e.events()).filter(e=>e.source!==i).at(-1),u=String(s?.output??"").trim();return u?(emitRepair(e,"runtime.repair.started","adapter_error",t,"focused_text_tool_gateway_recovery"),e.runRecoveredToolCall(i,{[c]:u})):void 0}function emitRepair(e,r,t,o,a){const n={requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:t,attempt:o,reason:a};e.emit("runtime.repair.started"===r?{type:r,...n}:{type:r,...n,outcome:"retried"})}function errorMessage(e){return e instanceof Error?e.message:String(e)}function adapterErrorRecoveryAttempts(e){const r=readToolCallNumber(e,"maxAdapterErrorRecoveryAttempts");return void 0!==r&&r>0?r:3}function readToolCallNumber(e,r){const t=isRecord(e)?e.recovery:void 0,o=isRecord(t)?t.toolCall:void 0,a=isRecord(o)?o[r]:void 0;return"number"==typeof a&&Number.isInteger(a)?a:void 0}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)}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RawArgsToolMatch } from "../../recovery/raw-args.js";
|
|
2
|
+
import type { RuntimeRequest, RuntimeToolGateway, WorkspaceAgent } from "../../types.js";
|
|
3
|
+
type FocusedTextArgumentInput = {
|
|
4
|
+
agent: WorkspaceAgent;
|
|
5
|
+
workspace: {
|
|
6
|
+
tools: Map<string, {
|
|
7
|
+
schema?: unknown;
|
|
8
|
+
}>;
|
|
9
|
+
};
|
|
10
|
+
toolGateway?: RuntimeToolGateway;
|
|
11
|
+
};
|
|
12
|
+
export declare function buildFocusedTextToolEvidenceRecoveryRequest(input: {
|
|
13
|
+
request: RuntimeRequest;
|
|
14
|
+
match: RawArgsToolMatch;
|
|
15
|
+
toolOutput: string;
|
|
16
|
+
}): RuntimeRequest;
|
|
17
|
+
export declare function focusedTextArgumentName(input: FocusedTextArgumentInput, toolId: string): string | undefined;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function buildFocusedTextToolEvidenceRecoveryRequest(e){return{...e.request,input:[e.request.input,"","Stable runtime recovery: the focused recovery turn produced text instead of the required structured tool call.",`Focused tool executed through the governed gateway: ${e.match.toolId}`,"Continue from the executed evidence below.","If another declared tool is needed, call it through the backend's normal structured tool-calling mechanism.","Do not repeat the same focused tool call unless new required input is materially different.","","Executed focused tool arguments:",JSON.stringify(e.match.args),"","Executed focused tool output:",e.toolOutput].join("\n"),metadata:{...e.request.metadata,stableHarnessRecovery:"tool_call"}}}export function focusedTextArgumentName(e,t){const r=e.workspace.tools.get(t)?.schema??e.toolGateway?.get(t)?.schema,o=function readExplicitFocusedTextArgument(e){const t=isRecord(e)?e:{},r=t.stableHarnessFocusedTextArgument??t.focusedTextArgument;return"string"==typeof r&&r.trim()?r.trim():void 0}(r);if(o)return o;const n=function readZodObjectShape(e){const t=isRecord(e)?e.def:void 0,r=isRecord(t)?t.shape:void 0;return isRecord(r)?r:void 0}(r);if(n){const e=Object.entries(n).filter(([,e])=>"string"===readSchemaType(e));return 1===e.length?e[0][0]:void 0}const i=isRecord(r)?r:{},c=function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}(i.required),s=isRecord(i.properties)?i.properties:{},d=Object.entries(s).filter(([e,t])=>(0===c.length||c.includes(e))&&"string"===readSchemaType(t)).map(([e])=>e);return 1===d.length?d[0]:void 0}function readSchemaType(e){const t=isRecord(e)?e:{},r=isRecord(t.def)?t.def:void 0;return"string"==typeof t.type?t.type:"string"==typeof r?.type?r.type:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { rawToolCallOutputPreview } from "../../recovery/tool-call.js";
|
|
2
|
+
import type { RuntimeEvent, RuntimeRequest } from "../../types.js";
|
|
3
|
+
export declare function assertNoNonFocusedRecoveryIntent(output: string, policy: unknown, declaredToolIds: string[], visibleToolIds: string[], events: RuntimeEvent[]): void;
|
|
4
|
+
export declare function buildNonFocusedRecoveryRequest(input: {
|
|
5
|
+
request: RuntimeRequest;
|
|
6
|
+
output: string;
|
|
7
|
+
events: RuntimeEvent[];
|
|
8
|
+
policy: unknown;
|
|
9
|
+
declaredToolIds: string[];
|
|
10
|
+
visibleToolIds: string[];
|
|
11
|
+
}): RuntimeRequest | undefined;
|
|
12
|
+
export declare function visibleToolCandidates(output: string, toolIds: string[] | undefined): string[];
|
|
13
|
+
export { rawToolCallOutputPreview };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{successfulEvidenceItems as e,successfulEvidenceToolIds as o}from"../../quality/event-evidence.js";import{containsProgressOnlyToolIntent as t}from"../../recovery/progress-intent.js";import{containsRawToolCallOutput as n,rawToolCallOutputPreview as r}from"../../recovery/tool-call.js";import{maxNonFocusedRecoveryRedirects as s,nonFocusedRecoveryRedirectCount as l}from"./recovery-policy.js";export function assertNoNonFocusedRecoveryIntent(e,t,n,r,s){const l=nonFocusedRecoveryIntent(e,t,n,r);if(!l)return;const c=new Set(o(s)),i=l.nonFocused.filter(e=>!c.has(e));if(0===i.length)return;const a=i.length>0?i:l.nonFocused;throw new Error(`Focused recovery output referenced non-focused tool(s): ${a.join(", ")}. The backend must call one of the focused gateway tools: ${r.join(", ")}.`)}export function buildNonFocusedRecoveryRequest(t){const n=nonFocusedRecoveryIntent(t.output,t.policy,t.declaredToolIds,t.visibleToolIds);if(!n)return;const r=e(t.events),c=new Set(o(t.events)),i=n.nonFocused.filter(e=>!c.has(e)),a=r.slice(-5).map(e=>`- ${e.source}: ${function previewRecoveredEvidence(e){const o=e.replace(/\s+/gu," ").trim();return o.length>1e3?`${o.slice(0,997)}...`:o}(e.output)}`),u=l(t.request.metadata);if(u>=s(t.policy))return;const d=i.length>0?[...new Set([...t.visibleToolIds,...i])]:t.visibleToolIds;return{...t.request,input:[t.request.input,"",i.length>0?"Stable runtime recovery: the previous recovery output referenced declared tool(s) that were not allowed targets for this focused turn.":"Stable runtime recovery: the previous recovery output referenced tool(s) that already have successful evidence but are not allowed targets for this focused turn.",i.length>0?`Unresolved non-focused declared tool(s): ${i.join(", ")}`:`Already completed non-focused tool(s): ${n.nonFocused.join(", ")}`,i.length>0?`Additional declared tool target(s) allowed for this recovery turn: ${i.join(", ")}`:"",`Allowed focused tool target(s): ${d.join(", ")}`,i.length>0?"Call one allowed focused target. Use the added declared tool only if it is needed to build the required evidence call.":"Reuse the prior successful evidence below to build one allowed focused tool call. Do not call already completed non-focused tools again.","The next assistant action must be the backend's structured tool call for one allowed focused target, with no prose before it.","","Prior successful tool evidence:",...a,"","Previous invalid recovery output:",t.output].filter(Boolean).join("\n"),metadata:{...t.request.metadata,stableHarnessRecovery:"tool_call",stableHarnessRequiredEvidenceTools:d,stableHarnessNonFocusedRecoveryRedirects:u+1}}}export function visibleToolCandidates(e,o){const t=new Set;for(const n of o??[])containsDelimitedToken(e,n)&&t.add(n);return[...t]}function nonFocusedRecoveryIntent(e,o,r,s){if(0===s.length||s.length===r.length)return;const l=new Set(s),c=visibleToolCandidates(e,r).filter(e=>!l.has(e)),i=n(e,o)||t(e,r)||function containsJsonToolEnvelope(e){const o=e.trim(),t=o.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/iu)?.[1]?.trim(),n=t??o;if(!n.startsWith("{")||!n.endsWith("}")||n.length>6e3)return!1;try{const e=JSON.parse(n);if(!function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}(e))return!1;const o=["tool","tool_name","name","type","subagent_type"].some(o=>"string"==typeof e[o]),t=["args","arguments","parameters","params","kwargs"].some(o=>o in e);return o&&t}catch{return!1}}(e);return c.length>0&&i?{nonFocused:c}:void 0}function containsDelimitedToken(e,o){if(!o)return!1;let t=e.indexOf(o);for(;t>=0;){const n=0===t?"":e[t-1],r=e[t+o.length]??"";if(!isTokenChar(n)&&!isTokenChar(r))return!0;t=e.indexOf(o,t+o.length)}return!1}function isTokenChar(e){return"_"===e||"-"===e||e>="A"&&e<="Z"||e>="a"&&e<="z"||e>="0"&&e<="9"}export{r as rawToolCallOutputPreview};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function resultRecoveryAttempts(e){const o=readToolCallNumber(e,"maxResultRecoveryAttempts");return void 0!==o&&o>0?o:3}export function maxNonFocusedRecoveryRedirects(e){const o=readToolCallNumber(e,"maxNonFocusedRecoveryRedirects");return void 0!==o&&o>=0?o:3}export function nonFocusedRecoveryRedirectCount(e){const o=e?.stableHarnessNonFocusedRecoveryRedirects;return"number"==typeof o&&Number.isInteger(o)&&o>=0?o:0}function readToolCallNumber(e,o){const r=isRecord(e)?e.recovery:void 0,t=isRecord(r)?r.toolCall:void 0,n=isRecord(t)?t[o]:void 0;return"number"==typeof n&&Number.isInteger(n)?n:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID as e}from"node:crypto";import{assertExecutionContract as t}from"./execution-contract.js";import{
|
|
1
|
+
import{randomUUID as e}from"node:crypto";import{assertExecutionContract as t}from"./execution-contract.js";import{buildAdapterErrorRecoveryPrompt as r,isRecoverableAdapterError as a}from"./recovery/tool-call.js";import{recoverQualityReview as o,resolveQualityPolicy as n}from"./quality/index.js";import{recoverAdapterResultOutput as s}from"./runtime/recovery/adapter-result.js";import{completeRun as i,failRun as u}from"./runtime/completion.js";import{createRuntimeAdministrationMethods as c}from"./runtime/admin/administration.js";import{runDirectToolCall as p}from"./runtime/direct-tool-call.js";import{createApprovalGatedToolGateway as d}from"./runtime/governance/approval-gate.js";import{createSandboxedToolGateway as m}from"./runtime/governance/sandbox.js";import{createRuntimeImprovementAdministration as l}from"./runtime/improvement/admin.js";import{createRuntimeEvidenceAdministration as w}from"./runtime/improvement/evidence-admin.js";import{createInMemoryRuntimeImprovementStore as I}from"./runtime/improvement/store.js";import{createRuntimeInspectionMethods as y}from"./runtime/inspection/methods.js";import{createRuntimeCapabilityRegistry as g,normalizeAdapterResult as f}from"./runtime/capabilities.js";import{createMemoryRuntimeCapability as q}from"./runtime/memory.js";import{resolveToolCallRecoveryPolicy as v}from"./runtime/recovery/tool-call-policy.js";import{createRuntimeMemoryAdministration as R}from"./runtime/admin/memory.js";import{createInMemoryRuntimeStore as k}from"./runtime/persistence/stores.js";import{createProgressNarrationCapability as A}from"./runtime/progress-narration.js";import{repairRuntimeSelection as b}from"./runtime/selection-repair.js";import{createLangSmithTracingCapability as C}from"./runtime/tracing/langsmith.js";import{createToolFailureTracker as j}from"./runtime/tool-failure.js";import{recoverExecutionContract as G}from"./runtime/recovery/execution-contract-runtime.js";import{runWorkflowRequest as T}from"./workflows/runtime.js";export function createStableHarnessRuntime(f){const x=new Set,E=f.store??k(),S=f.improvements??I(),h=g([q(f),A({options:f.progressNarration,policy:f.workspace.runtime}),C({policy:f.workspace.runtime,store:E,options:f.langSmithTracing}),...f.capabilities??[]]),emitBase=t=>{const r=function enrichRuntimeEvent(t){return{...t,eventId:t.eventId??e(),emittedAt:t.emittedAt??(new Date).toISOString()}}(t);E.appendEvent(r);for(const e of x)e(r)},emit=e=>{emitBase(e),h.emitSideEffects(e,emitBase)},M=m({gateway:d({gateway:f.toolGateway,approvals:f.approvals,workspace:f.workspace,emit:emit}),workspace:f.workspace,sandbox:f.sandbox,emit:emit}),O={...f,toolGateway:M},F=j(function readToolFailurePolicy(e){if("object"!=typeof e||null===e||Array.isArray(e))return;const t=e.failurePolicy;return"object"!=typeof t||null===t||Array.isArray(t)?void 0:t}(f.workspace.runtime.toolGateway));return{request:async c=>async function runRuntimeRequest(c){const d=c.request.requestId??e(),m=c.request.sessionId??e(),l=[],{agent:w,adapter:I}=await async function resolveExecution(e,t,r){const a=t.agentId?await async function resolveRequestedAgentId(e,t,r){if(e.agents.has(t))return t;const a=await b({id:t,candidates:[...e.agents.values()].map(e=>({id:e.id,description:e.description})),trace:{...r,agentId:t,layer:"agent",owner:"stable_runtime_policy"}});return a.ok?a.id:t}(e.workspace,t.agentId,r):e.workspace.runtime.defaultAgentId,o=e.workspace.agents.get(a);if(!o)throw new Error(`Agent ${a} is not defined in the workspace`);if(t.toolCall||t.workflow)return{agent:o,adapter:void 0};const n=e.adapters.find(e=>e.canRun(o));if(!n)throw new Error(`No runtime adapter can run backend ${o.backend} for agent ${o.id}`);return{agent:o,adapter:n}}(c.input,c.request,{requestId:d,sessionId:m,emit:e=>l.push(e)});c.store.createRun(function createRunRecord(e,t,r,a){return{requestId:t,sessionId:r,agentId:a.id,input:e.input,state:"running",parentRunId:e.parentRunId,metadata:e.metadata,artifacts:[],startedAt:(new Date).toISOString(),events:[]}}(c.request,d,m,w)),l.forEach(c.emit),c.emit({type:"runtime.request.started",requestId:d,sessionId:m,agentId:w.id,input:c.request.input});try{if(c.request.workflow){const e=await T({workspace:c.input.workspace,adapters:c.input.workflowAdapters??[],toolGateway:c.input.toolGateway,request:{input:c.request.input,...c.request.workflow},requestId:d,sessionId:m,agentId:w.id,emit:c.emit});return i({store:c.store,emit:c.emit,requestId:d,sessionId:m,agent:w,result:e,artifacts:c.input.artifacts})}if(c.request.toolCall){const e=await p({gateway:c.input.toolGateway,workspace:c.input.workspace,emit:c.emit,request:c.request,requestId:d,sessionId:m,agent:w,toolFailureTracker:c.toolFailureTracker,toolGuardrails:c.input.toolGuardrails,events:c.store.getRun(d)?.events??[]});return i({store:c.store,emit:c.emit,requestId:d,sessionId:m,agent:w,result:e,artifacts:c.input.artifacts})}return await async function runAdapterRequest(e){if(!e.adapter)throw new Error(`No runtime adapter can run backend ${e.agent.backend} for agent ${e.agent.id}`);const u=e.adapter,c=await e.capabilities.beforeAdapterRun(createCapabilityContext(e)),p=c.memory,d=c.pluginMemories??[],m=v({workspace:e.input.workspace,agent:e.agent}),l=n(e.input.workspace.runtime,e.agent),w=new Map;let I;try{I=await runAdapterOnce(e,u,e.request,p,d,w,m)}catch(t){if(!a(t,m))throw t;e.emit(function repairStarted(e,t,r,a){return{type:"runtime.repair.started",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:t,attempt:r,reason:a}}(e,"adapter_error",1,errorMessage(t))),I=await runAdapterOnce(e,u,r(e.request,t,m),p,d,w,m),e.emit(function repairCompleted(e,t,r,a,o){return{type:"runtime.repair.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:t,outcome:r,attempt:a,reason:o}}(e,"adapter_error","retried",1,errorMessage(t)))}I=await s({...e,request:e.request,result:I,recoveryPolicy:m,workspace:e.input.workspace,toolGateway:e.input.toolGateway,runAdapter:t=>runAdapterOnce(e,u,t,p,d,w,m),runRecoveredToolCall:(t,r)=>runRecoveredToolCall(e,t,r)}),I=await o(createQualityRuntimeInput(e,p,d,w,m),e.request,I,l),await e.capabilities.beforeAdapterResultContract({...createCapabilityContext(e),result:I}),I=await G({request:e.request,events:()=>e.store.getRun(e.requestId)?.events??[],agent:e.agent,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,result:I,policy:m,workspace:e.input.workspace,toolGateway:e.input.toolGateway,assertContract:r=>function assertRequestExecutionContract(e,r){t({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,output:r.text,metadata:e.request.metadata})}(e,r),runAdapter:t=>runAdapterOnce(e,u,t,p,d,w,m),runRecoveredToolCall:(t,r)=>runRecoveredToolCall(e,t,r),recoverResultOutput:(t,r)=>s({...e,request:t,result:r,recoveryPolicy:m,workspace:e.input.workspace,toolGateway:e.input.toolGateway,runAdapter:t=>runAdapterOnce(e,u,t,p,d,w,m),runRecoveredToolCall:(t,r)=>runRecoveredToolCall(e,t,r)}),recoverQuality:(t,r)=>o(createQualityRuntimeInput(e,p,d,w,m),t,r,l)});const y=i({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,result:I,artifacts:e.input.artifacts});return await e.capabilities.afterAdapterResponse({...createCapabilityContext(e),result:I,response:y}),y}({...c,adapter:I,requestId:d,sessionId:m,agent:w})}catch(e){return u({store:c.store,emit:c.emit,requestId:d,sessionId:m,agent:w,error:e})}}({input:O,capabilities:h,store:E,emit:emit,request:c,toolFailureTracker:F}),subscribe:e=>(x.add(e),()=>x.delete(e)),...y({workspace:f.workspace,store:E,artifacts:f.artifacts,approvals:f.approvals,emit:emit}),...c({store:E,emit:emit}),...l({runtimeStore:E,store:S,emit:emit}),...w({runtimeStore:E,emit:emit}),...R({memory:f.memory}),cancel(e,t){const r=E.getRun(e);r&&"running"===r.state&&(E.updateRun(e,{state:"cancelled",completedAt:(new Date).toISOString()}),emit({type:"runtime.request.cancelled",requestId:e,sessionId:r.sessionId,agentId:r.agentId,reason:t}))},async stop(){await h.stop(),x.clear()}}}function runRecoveredToolCall(e,t,r){return p({gateway:e.input.toolGateway,workspace:e.input.workspace,emit:e.emit,request:{...e.request,toolCall:{toolId:t,args:r}},requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,toolFailureTracker:e.input.toolFailureTracker,toolGuardrails:e.input.toolGuardrails,events:e.store.getRun(e.requestId)?.events??[]})}function createCapabilityContext(e){return{workspace:e.input.workspace,store:e.store,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent}}function createQualityRuntimeInput(e,t,r,a,o){return{workspace:e.input.workspace,agent:e.agent,request:e.request,requestId:e.requestId,sessionId:e.sessionId,events:e.store.getRun(e.requestId)?.events??[],emit:e.emit,getEvents:()=>e.store.getRun(e.requestId)?.events??[],runAdapter:n=>runAdapterOnce(e,e.adapter,n,t,r,a,o),reviewModel:e.input.qualityReviewModel,executionEvaluatorRules:e.input.executionEvaluatorRules,memory:t,pluginMemories:r}}async function runAdapterOnce(e,t,r,a,o,n,s){return f(await t.run({workspace:{...e.input.workspace,runtime:s},agent:e.agent,request:r,requestId:e.requestId,sessionId:e.sessionId,memory:a,pluginMemories:o,toolGateway:e.input.toolGateway,toolFailureTracker:e.input.toolFailureTracker,toolGuardrails:e.input.toolGuardrails,executionEvaluatorRules:e.input.executionEvaluatorRules,requestState:n,getEvents:()=>e.store.getRun(e.requestId)?.events??[],emit:e.emit}))}function errorMessage(e){return e instanceof Error?e.message:String(e)}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.134",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
".": "./dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"@stable-harness/governance": "0.0.
|
|
16
|
-
"@stable-harness/memory": "0.0.
|
|
15
|
+
"@stable-harness/governance": "0.0.134",
|
|
16
|
+
"@stable-harness/memory": "0.0.134"
|
|
17
17
|
}
|
|
18
18
|
}
|