stable-harness 0.0.35 → 0.0.36

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stable-harness",
3
- "version": "0.0.35",
3
+ "version": "0.0.36",
4
4
  "type": "module",
5
5
  "description": "Stable application runtime and operator control plane for agent workspaces.",
6
6
  "license": "Apache-2.0",
@@ -1 +1 @@
1
- import{ToolMessage as e}from"@langchain/core/messages";import{tool as t}from"@langchain/core/tools";import{isSuccessfulEvidenceOutput as o,observedToolEvidence as r,recordObservedToolEvidence as n}from"./gateway/tool-evidence.js";import{emitStructuredToolFailure as s}from"./gateway/tool-failure-events.js";export function buildGatewayTools(o,n,a,i,l=createToolRepeatState(o.workspace.runtime.toolGateway)){return o.toolGateway?a.flatMap(a=>{const u=o.toolGateway?.get(a);if(!u)return[];const c=o.workspace.tools.get(a),d=c?.schema??u.schema;return[t(async t=>async function invokeGuardedGatewayTool(t){emitToolResult(t.input,t.agentId,t.toolId,void 0);const o=function missingRequiredPlanContent(e,t){const o=readRecord(e.agent.config.executionContract);if(!0!==o?.requiresPlan)return"";const n=readStringArray(o.planEvidenceTools);if(0===n.length||n.includes(t))return"";const s=new Set(r(e).map(e=>e.toolId));return n.some(e=>s.has(e))?"":["Status: plan_required",`Evidence tool: ${t}`,`Blocker: execution contract requires a planning checkpoint from one of: ${n.join(", ")} before evidence tools run.`,"Instruction: call the planning tool first, then retry this atomic evidence tool with repaired arguments."].join("\n")}(t.input,t.toolId);if(o)return emitToolResult(t.input,t.agentId,t.toolId,o),o;const n=function missingToolDependencyContent(e,t){const o=readRecord(e.agent.config.executionContract),n=readStringArray(readRecord(o.toolDependencies)[t]);if(0===n.length)return"";const s=new Set(r(e).map(e=>e.toolId)),a=n.filter(e=>!s.has(e));return 0===a.length?"":["Status: dependency_required",`Evidence tool: ${t}`,`Blocker: this atomic evidence tool requires completed dependency evidence from: ${a.join(", ")}.`,"Instruction: complete the dependency tool first, evaluate it, then retry this atomic evidence tool."].join("\n")}(t.input,t.toolId);if(n)return emitToolResult(t.input,t.agentId,t.toolId,n),n;const a=t.repeatState?beforeToolInvoke(t.toolId,t.args,t.repeatState):void 0;if(a)return emitToolResult(t.input,t.agentId,t.toolId,a.eventOutput),a.modelOutput;const i=await async function invokeGatewayTool(t,o,r,n,a){try{if(t.toolFailureTracker?.isCircuitOpen(r))throw new Error(`Tool circuit is open: ${r}`);const e=await t.toolGateway.invoke({toolId:r,args:n,repairModel:a,context:{workspaceRoot:t.workspace.root,requestId:t.requestId,sessionId:t.sessionId,agentId:o,requestInput:t.request.input,observedEvidence:formatObservedEvidenceForToolContext(t),approvalIds:readApprovalIds(t.request.metadata)}});return t.toolFailureTracker?.recordSuccess(r),e}catch(n){if(s(t,o,r,n),function isToolArgumentValidationError(e){return e instanceof Error&&"ToolArgumentValidationError"===e.name&&"string"==typeof e.toolId&&Array.isArray(e.issues)}(n))return new e({tool_call_id:`stable-harness-${r}-argument-guard`,name:r,status:"error",content:formatToolArgumentError(n)});if(t.workspace.runtime.retry?.tools?.enabled)throw n;return new e({tool_call_id:`stable-harness-${r}-execution-error`,name:r,status:"error",content:JSON.stringify({error:"tool_execution_failed",toolId:r,message:formatError(n),retry:"Use the error as evidence, adjust the tool arguments if possible, or return a final answer with the blocker."})})}}(t.input,t.agentId,t.toolId,t.args,t.repairModel),l=i instanceof e?String(i.content):stringifyDeepAgentResult(i.output),u=t.repeatState?afterToolInvoke(t.toolId,t.args,l,i,t.repeatState):{};return emitToolResult(t.input,t.agentId,t.toolId,u.eventOutput??l),void 0!==u.modelOutput?u.modelOutput:i instanceof e?i:l}({input:o,agentId:n,toolId:a,args:t,repairModel:i,repeatState:l}),{name:a,description:buildToolDescription(c?.description??u.description??a,d,o.workspace.runtime.toolGateway,a),schema:{type:"object",additionalProperties:!0}})]}):[]}export function createToolRepeatState(e){if(function repeatGuardEnabled(e){return!0===repeatGuardConfig(e).enabled}(e))return{successfulCalls:new Map,duplicateCallCounts:new Map,latestSuccessfulOutputByTool:new Map,successfulToolCounts:new Map,toolCallCounts:new Map,maxDuplicateCallsPerTool:readPositiveInteger(repeatGuardConfig(e).maxDuplicateCallsPerTool)??3,maxCallsPerTool:readPositiveInteger(repeatGuardConfig(e).maxCallsPerTool),maxSuccessfulCallsPerTool:readPositiveInteger(repeatGuardConfig(e).maxSuccessfulCallsPerTool),maxCallsByTool:readPositiveIntegerMap(repeatGuardConfig(e).maxCallsByTool),maxSuccessfulCallsByTool:readPositiveIntegerMap(repeatGuardConfig(e).maxSuccessfulCallsByTool),returnPreviousOutputOnRepeatLimit:!0===repeatGuardConfig(e).returnPreviousOutputOnRepeatLimit}}function repeatGuardConfig(e){return isRecord(e)&&isRecord(e.repeatGuard)?e.repeatGuard:{}}function readPositiveInteger(e){return"number"==typeof e&&Number.isInteger(e)&&e>0?e:void 0}function readPositiveIntegerMap(e){return isRecord(e)?new Map(Object.entries(e).map(([e,t])=>[e,readPositiveInteger(t)]).filter(e=>void 0!==e[1])):new Map}export function beforeToolInvoke(e,t,o){const r=o.toolCallCounts.get(e)??0;o.toolCallCounts.set(e,r+1);const n=o.maxCallsByTool.get(e)??o.maxCallsPerTool;if(void 0!==n&&r>=n){const t=o.latestSuccessfulOutputByTool.get(e),r=repeatedToolCallLimitContent(e,t);return{eventOutput:r,modelOutput:repeatLimitModelOutput(r,t,o)}}const s=o.maxSuccessfulCallsByTool.get(e)??o.maxSuccessfulCallsPerTool;if(void 0!==s&&(o.successfulToolCounts.get(e)??0)>=s){const t=o.latestSuccessfulOutputByTool.get(e),r=repeatedToolCallLimitContent(e,t);return{eventOutput:r,modelOutput:repeatLimitModelOutput(r,t,o)}}const a=stableToolCallKey(e,t),i=o.successfulCalls.get(a);if(void 0!==i){const t=o.duplicateCallCounts.get(a)??0;if(o.duplicateCallCounts.set(a,t+1),void 0!==o.maxDuplicateCallsPerTool&&t>=o.maxDuplicateCallsPerTool){const t=repeatedToolCallLimitContent(e);return{eventOutput:t,modelOutput:t}}const r=function duplicateToolCallContent(e,t){return JSON.stringify({status:"duplicate_tool_call",toolId:e,instruction:"This agent already completed an equivalent tool call. Use the prior evidence instead of calling the tool again.",previousOutput:t})}(e,i);return{eventOutput:r,modelOutput:i}}}function repeatLimitModelOutput(e,t,o){return o.returnPreviousOutputOnRepeatLimit&&void 0!==t&&0!==t.trim().length?t:e}export function isToolRepeatLimitReached(e,t){if(!t)return!1;const o=t.maxCallsByTool.get(e)??t.maxCallsPerTool;if(void 0!==o&&(t.toolCallCounts.get(e)??0)>=o)return!0;const r=t.maxSuccessfulCallsByTool.get(e)??t.maxSuccessfulCallsPerTool;return void 0!==r&&(t.successfulToolCounts.get(e)??0)>=r}export function afterToolInvoke(t,r,n,s,a){return s instanceof e&&"error"===s.status?{}:o(n)?(a.successfulCalls.set(stableToolCallKey(t,r),n),a.latestSuccessfulOutputByTool.set(t,n),a.successfulToolCounts.set(t,(a.successfulToolCounts.get(t)??0)+1),{}):{}}function emitToolResult(e,t,o,r){void 0!==r&&n(e,t,o,r),e.emit({type:"runtime.adapter.event",requestId:e.requestId,sessionId:e.sessionId,agentId:t,event:void 0===r?{adapter:"deepagents",phase:"agent.tool.start",toolId:o}:{adapter:"deepagents",phase:"agent.tool.result",toolId:o,output:previewToolOutput(r),...toolControlProjection(r)}})}function repeatedToolCallLimitContent(e,t){return JSON.stringify({status:"repeated_tool_call_limit",toolId:e,instruction:"This tool reached the configured repeat limit for this request. Do not call this tool or a substitute tool for the same evidence need again. Use previousOutput and the collected evidence to produce the final answer now, or report the remaining gap explicitly.",...void 0!==t?{previousOutput:t}:{}})}export function stringifyDeepAgentResult(t){if(t instanceof e)return function stringifyToolMessageContent(e){return"string"==typeof e?e:JSON.stringify(e)}(t.content);if("string"==typeof t)return t;if(isRecord(t)){const e=t.structuredResponse??t.structured_response;if(void 0!==e)return"string"==typeof e?e:JSON.stringify(e);const o=(Array.isArray(t.messages)?t.messages:[]).at(-1);if(isRecord(o)&&"string"==typeof o.content)return o.content;const r=(isRecord(t.update)&&Array.isArray(t.update.messages)?t.update.messages:[]).at(-1);if(isRecord(r)&&isRecord(r.kwargs)&&"string"==typeof r.kwargs.content)return r.kwargs.content;if(isRecord(r)&&"string"==typeof r.content)return r.content}return JSON.stringify(t)}function buildToolDescription(e,t,o,r){const n=function toolRepeatPolicyDescription(e,t){const o=repeatGuardConfig(e),r=readPositiveIntegerMap(o.maxSuccessfulCallsByTool).get(t)??readPositiveInteger(o.maxSuccessfulCallsPerTool);return void 0===r?"":`Stable runtime repeat policy: call this tool at most ${r} successful time(s) for this request. If more detail is needed, include the dimensions in the first call and synthesize after the result returns.`}(o,r),s=n?`${e}\n\n${n}`:e;return t?`${s}\n\nStable tool input schema:\n${previewToolOutput(JSON.stringify(t))}`:s}function previewToolOutput(e){const t=e.replace(/\s+/gu," ").trim();return t.length>500?`${t.slice(0,497)}...`:t}export function toolControlProjection(e){const t=function parseJsonRecord(e){try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e);if("string"==typeof t?.status)return{controlStatus:t.status};const o=function readTextStatus(e){return String(e).match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}(e);return o?{controlStatus:o}:"string"==typeof t?.error?{controlStatus:t.error}:e.startsWith("Task delegation target is not in the workspace inventory")?{controlStatus:"task_inventory_blocked"}:{}}function stableToolCallKey(e,t){return`${e}:${stableJson(t)}`}function stableJson(e){return Array.isArray(e)?`[${e.map(stableJson).join(",")}]`:isRecord(e)?`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${stableJson(e[t])}`).join(",")}}`:JSON.stringify(e)}function readApprovalIds(e){const t=e?.approvalIds??e?.approvalId;return"string"==typeof t&&t.trim()?[t.trim()]:Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.trim().length>0):void 0}function formatObservedEvidenceForToolContext(e){const t=r(e).map(e=>`Tool: ${e.toolId}\n${e.output}`).join("\n\n---\n\n");return t.length>12e3?`${t.slice(0,12e3)}\n[truncated]`:t}function formatToolArgumentError(e){return JSON.stringify({error:"tool_argument_validation_failed",toolId:e.toolId,issues:e.issues,retry:"Call the same tool again with arguments that satisfy the reported schema and semantic issues."})}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readRecord(e){return isRecord(e)?e:{}}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}function formatError(e){return e instanceof Error?e.message:String(e)}
1
+ import{ToolMessage as e}from"@langchain/core/messages";import{tool as t}from"@langchain/core/tools";import{isSuccessfulEvidenceOutput as o,observedToolEvidence as r,recordObservedToolEvidence as n}from"./gateway/tool-evidence.js";import{emitStructuredToolFailure as s}from"./gateway/tool-failure-events.js";export function buildGatewayTools(o,n,a,i,l=createToolRepeatState(o.workspace.runtime.toolGateway)){return o.toolGateway?a.flatMap(a=>{const u=o.toolGateway?.get(a);if(!u)return[];const c=o.workspace.tools.get(a),d=c?.schema??u.schema;return[t(async t=>async function invokeGuardedGatewayTool(t){emitToolResult(t.input,t.agentId,t.toolId,void 0);const o=function missingRequiredPlanContent(e,t){const o=readRecord(e.agent.config.executionContract);if(!0!==o?.requiresPlan)return"";const n=readStringArray(o.planEvidenceTools);if(0===n.length||n.includes(t))return"";const s=new Set(r(e).map(e=>e.toolId));return n.some(e=>s.has(e))?"":["Status: plan_required",`Evidence tool: ${t}`,`Blocker: execution contract requires a planning checkpoint from one of: ${n.join(", ")} before evidence tools run.`,"Instruction: call the planning tool first, then retry this atomic evidence tool with repaired arguments."].join("\n")}(t.input,t.toolId);if(o)return emitToolResult(t.input,t.agentId,t.toolId,o),o;const n=function missingToolDependencyContent(e,t){const o=readRecord(e.agent.config.executionContract),n=readStringArray(readRecord(o.toolDependencies)[t]);if(0===n.length)return"";const s=new Set(r(e).map(e=>e.toolId)),a=n.filter(e=>!s.has(e));return 0===a.length?"":["Status: dependency_required",`Evidence tool: ${t}`,`Blocker: this atomic evidence tool requires completed dependency evidence from: ${a.join(", ")}.`,"Instruction: complete the dependency tool first, evaluate it, then retry this atomic evidence tool."].join("\n")}(t.input,t.toolId);if(n)return emitToolResult(t.input,t.agentId,t.toolId,n),n;const a=t.repeatState?beforeToolInvoke(t.toolId,t.args,t.repeatState):void 0;if(a)return emitToolResult(t.input,t.agentId,t.toolId,a.eventOutput),a.modelOutput;const i=await async function invokeGatewayTool(t,o,r,n,a){try{if(t.toolFailureTracker?.isCircuitOpen(r))throw new Error(`Tool circuit is open: ${r}`);const e=await t.toolGateway.invoke({toolId:r,args:n,repairModel:a,context:{workspaceRoot:t.workspace.root,requestId:t.requestId,sessionId:t.sessionId,agentId:o,requestInput:t.request.input,observedEvidence:formatObservedEvidenceForToolContext(t),approvalIds:readApprovalIds(t.request.metadata)}});return t.toolFailureTracker?.recordSuccess(r),e}catch(n){if(s(t,o,r,n),function isToolArgumentValidationError(e){return e instanceof Error&&"ToolArgumentValidationError"===e.name&&"string"==typeof e.toolId&&Array.isArray(e.issues)}(n))return new e({tool_call_id:`stable-harness-${r}-argument-guard`,name:r,status:"error",content:formatToolArgumentError(n)});if(t.workspace.runtime.retry?.tools?.enabled)throw n;return new e({tool_call_id:`stable-harness-${r}-execution-error`,name:r,status:"error",content:JSON.stringify({error:"tool_execution_failed",toolId:r,message:formatError(n),retry:"Use the error as evidence, adjust the tool arguments if possible, or return a final answer with the blocker."})})}}(t.input,t.agentId,t.toolId,t.args,t.repairModel),l=i instanceof e?String(i.content):stringifyDeepAgentResult(i.output),u=t.repeatState?afterToolInvoke(t.toolId,t.args,l,i,t.repeatState):{};return emitToolResult(t.input,t.agentId,t.toolId,u.eventOutput??l),void 0!==u.modelOutput?u.modelOutput:i instanceof e?i:l}({input:o,agentId:n,toolId:a,args:t,repairModel:i,repeatState:l}),{name:a,description:buildToolDescription(c?.description??u.description??a,d,o.workspace.runtime.toolGateway,a),schema:{type:"object",additionalProperties:!0}})]}):[]}export function createToolRepeatState(e){if(function repeatGuardEnabled(e){return!0===repeatGuardConfig(e).enabled}(e))return{successfulCalls:new Map,duplicateCallCounts:new Map,latestSuccessfulOutputByTool:new Map,successfulToolCounts:new Map,toolCallCounts:new Map,maxDuplicateCallsPerTool:readPositiveInteger(repeatGuardConfig(e).maxDuplicateCallsPerTool)??3,maxCallsPerTool:readPositiveInteger(repeatGuardConfig(e).maxCallsPerTool),maxSuccessfulCallsPerTool:readPositiveInteger(repeatGuardConfig(e).maxSuccessfulCallsPerTool),maxCallsByTool:readPositiveIntegerMap(repeatGuardConfig(e).maxCallsByTool),maxSuccessfulCallsByTool:readPositiveIntegerMap(repeatGuardConfig(e).maxSuccessfulCallsByTool),returnPreviousOutputOnRepeatLimit:!0===repeatGuardConfig(e).returnPreviousOutputOnRepeatLimit}}function repeatGuardConfig(e){return isRecord(e)&&isRecord(e.repeatGuard)?e.repeatGuard:{}}function readPositiveInteger(e){return"number"==typeof e&&Number.isInteger(e)&&e>0?e:void 0}function readPositiveIntegerMap(e){return isRecord(e)?new Map(Object.entries(e).map(([e,t])=>[e,readPositiveInteger(t)]).filter(e=>void 0!==e[1])):new Map}export function beforeToolInvoke(e,t,o){const r=o.toolCallCounts.get(e)??0;o.toolCallCounts.set(e,r+1);const n=o.maxCallsByTool.get(e)??o.maxCallsPerTool;if(void 0!==n&&r>=n){const t=o.latestSuccessfulOutputByTool.get(e),r=repeatedToolCallLimitContent(e,t);return{eventOutput:r,modelOutput:repeatLimitModelOutput(r,t,o)}}const s=o.maxSuccessfulCallsByTool.get(e)??o.maxSuccessfulCallsPerTool;if(void 0!==s&&(o.successfulToolCounts.get(e)??0)>=s){const t=o.latestSuccessfulOutputByTool.get(e),r=repeatedToolCallLimitContent(e,t);return{eventOutput:r,modelOutput:repeatLimitModelOutput(r,t,o)}}const a=stableToolCallKey(e,t),i=o.successfulCalls.get(a);if(void 0!==i){const t=o.duplicateCallCounts.get(a)??0;if(o.duplicateCallCounts.set(a,t+1),void 0!==o.maxDuplicateCallsPerTool&&t>=o.maxDuplicateCallsPerTool){const t=repeatedToolCallLimitContent(e);return{eventOutput:t,modelOutput:t}}const r=function duplicateToolCallContent(e,t){return JSON.stringify({status:"duplicate_tool_call",toolId:e,instruction:"This agent already completed an equivalent tool call. Use the prior evidence instead of calling the tool again.",previousOutput:t})}(e,i);return{eventOutput:r,modelOutput:i}}}function repeatLimitModelOutput(e,t,o){return o.returnPreviousOutputOnRepeatLimit&&void 0!==t&&0!==t.trim().length?t:e}export function isToolRepeatLimitReached(e,t){if(!t)return!1;const o=t.maxCallsByTool.get(e)??t.maxCallsPerTool;if(void 0!==o&&(t.toolCallCounts.get(e)??0)>=o)return!0;const r=t.maxSuccessfulCallsByTool.get(e)??t.maxSuccessfulCallsPerTool;return void 0!==r&&(t.successfulToolCounts.get(e)??0)>=r}export function afterToolInvoke(t,r,n,s,a){return s instanceof e&&"error"===s.status?{}:o(n)?(a.successfulCalls.set(stableToolCallKey(t,r),n),a.latestSuccessfulOutputByTool.set(t,n),a.successfulToolCounts.set(t,(a.successfulToolCounts.get(t)??0)+1),{}):{}}function emitToolResult(e,t,o,r){void 0!==r&&n(e,t,o,r),e.emit({type:"runtime.adapter.event",requestId:e.requestId,sessionId:e.sessionId,agentId:t,event:void 0===r?{adapter:"deepagents",phase:"agent.tool.start",toolId:o}:{adapter:"deepagents",phase:"agent.tool.result",toolId:o,output:previewToolOutput(r),evidenceOutput:r,...toolControlProjection(r)}})}function repeatedToolCallLimitContent(e,t){return JSON.stringify({status:"repeated_tool_call_limit",toolId:e,instruction:"This tool reached the configured repeat limit for this request. Do not call this tool or a substitute tool for the same evidence need again. Use previousOutput and the collected evidence to produce the final answer now, or report the remaining gap explicitly.",...void 0!==t?{previousOutput:t}:{}})}export function stringifyDeepAgentResult(t){if(t instanceof e)return function stringifyToolMessageContent(e){return"string"==typeof e?e:JSON.stringify(e)}(t.content);if("string"==typeof t)return t;if(isRecord(t)){const e=t.structuredResponse??t.structured_response;if(void 0!==e)return"string"==typeof e?e:JSON.stringify(e);const o=(Array.isArray(t.messages)?t.messages:[]).at(-1);if(isRecord(o)&&"string"==typeof o.content)return o.content;const r=(isRecord(t.update)&&Array.isArray(t.update.messages)?t.update.messages:[]).at(-1);if(isRecord(r)&&isRecord(r.kwargs)&&"string"==typeof r.kwargs.content)return r.kwargs.content;if(isRecord(r)&&"string"==typeof r.content)return r.content}return JSON.stringify(t)}function buildToolDescription(e,t,o,r){const n=function toolRepeatPolicyDescription(e,t){const o=repeatGuardConfig(e),r=readPositiveIntegerMap(o.maxSuccessfulCallsByTool).get(t)??readPositiveInteger(o.maxSuccessfulCallsPerTool);return void 0===r?"":`Stable runtime repeat policy: call this tool at most ${r} successful time(s) for this request. If more detail is needed, include the dimensions in the first call and synthesize after the result returns.`}(o,r),s=n?`${e}\n\n${n}`:e;return t?`${s}\n\nStable tool input schema:\n${previewToolOutput(JSON.stringify(t))}`:s}function previewToolOutput(e){const t=e.replace(/\s+/gu," ").trim();return t.length>500?`${t.slice(0,497)}...`:t}export function toolControlProjection(e){const t=function parseJsonRecord(e){try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e);if("string"==typeof t?.status)return{controlStatus:t.status};const o=function readTextStatus(e){return String(e).match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}(e);return o?{controlStatus:o}:"string"==typeof t?.error?{controlStatus:t.error}:e.startsWith("Task delegation target is not in the workspace inventory")?{controlStatus:"task_inventory_blocked"}:{}}function stableToolCallKey(e,t){return`${e}:${stableJson(t)}`}function stableJson(e){return Array.isArray(e)?`[${e.map(stableJson).join(",")}]`:isRecord(e)?`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${stableJson(e[t])}`).join(",")}}`:JSON.stringify(e)}function readApprovalIds(e){const t=e?.approvalIds??e?.approvalId;return"string"==typeof t&&t.trim()?[t.trim()]:Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.trim().length>0):void 0}function formatObservedEvidenceForToolContext(e){const t=r(e).map(e=>`Tool: ${e.toolId}\n${e.output}`).join("\n\n---\n\n");return t.length>12e3?`${t.slice(0,12e3)}\n[truncated]`:t}function formatToolArgumentError(e){return JSON.stringify({error:"tool_argument_validation_failed",toolId:e.toolId,issues:e.issues,retry:"Call the same tool again with arguments that satisfy the reported schema and semantic issues."})}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readRecord(e){return isRecord(e)?e:{}}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}function formatError(e){return e instanceof Error?e.message:String(e)}
@@ -4,6 +4,7 @@ export * from "./boundary-scan.js";
4
4
  export * from "./execution-contract.js";
5
5
  export * from "./recovery/tool-call.js";
6
6
  export * from "./runtime/persistence/inspection.js";
7
+ export { createWorkspaceSandboxPolicy } from "./runtime/governance/sandbox.js";
7
8
  export * from "./memory-plugins.js";
8
9
  export * from "./runtime/persistence/queue.js";
9
10
  export * from "./runtime.js";
@@ -1 +1 @@
1
- export*from"./runtime/persistence/artifacts.js";export*from"./boundary-scan.js";export*from"./execution-contract.js";export*from"./recovery/tool-call.js";export*from"./runtime/persistence/inspection.js";export*from"./memory-plugins.js";export*from"./runtime/persistence/queue.js";export*from"./runtime.js";export*from"./runtime/selection-repair.js";export*from"./runtime/tool-failure.js";export*from"./runtime/persistence/stores.js";export*from"./trace.js";export*from"./types.js";export*from"./workspace/tool-quality.js";export*from"./evaluations/index.js";export*from"./quality/index.js";export*from"./spec-driven/index.js";export*from"./workflows/index.js";
1
+ export*from"./runtime/persistence/artifacts.js";export*from"./boundary-scan.js";export*from"./execution-contract.js";export*from"./recovery/tool-call.js";export*from"./runtime/persistence/inspection.js";export{createWorkspaceSandboxPolicy}from"./runtime/governance/sandbox.js";export*from"./memory-plugins.js";export*from"./runtime/persistence/queue.js";export*from"./runtime.js";export*from"./runtime/selection-repair.js";export*from"./runtime/tool-failure.js";export*from"./runtime/persistence/stores.js";export*from"./trace.js";export*from"./types.js";export*from"./workspace/tool-quality.js";export*from"./evaluations/index.js";export*from"./quality/index.js";export*from"./spec-driven/index.js";export*from"./workflows/index.js";
@@ -1 +1 @@
1
- export function hasPlanningEvidence(t){return t.some(t=>{const e=readAdapterEvent(t);return!!e&&("plan"===e.traceType||String(e.traceLabel??"").startsWith("plan.")||"write_todos"===e.toolId&&String(e.phase??"").startsWith("agent.tool."))})}export function successfulEvidenceToolIds(t){const e=t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return[t.toolId];const e=readAdapterEvent(t);return e&&"agent.tool.result"===e.phase&&"string"==typeof e.toolId&&isSuccessfulEvidenceEvent(e)?[e.toolId]:[]});return[...new Set(e)]}export function successfulEvidenceOutputs(t){return successfulEvidenceItems(t).map(t=>t.output)}export function successfulEvidenceItems(t){return t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return stringifyEvidence(t.output).map(e=>({source:t.toolId,output:e}));const e=readAdapterEvent(t);return e&&"agent.tool.result"===e.phase&&"string"==typeof e.toolId?!isSuccessfulEvidenceEvent(e)||function isPlanningTool(t){return/^(?:write_todos|read_todos)$/u.test(t)}(e.toolId)?[]:stringifyEvidence(e.output).filter(t=>function isUsableEvidenceOutput(t,e){return"task"!==t||!function looksLikeUnexecutedToolIntent(t){const e=t.trim();return!(e.length>4e3)&&[/\b(?:I need to|I will|I'll|I am going to|I'm going to|Let me)\s+(?:call|use|run|invoke|get|fetch|check)\b[\s\S]{0,1200}\b(?:tool|function|system_time|web_search|url_text_fetch|task)\b/iu,/(?:我需要|我要|我会|我将|让我|我来|接下来我(?:会|将)?)\s*(?:先)?(?:调用|使用|运行|执行|检查|获取|查看)\b[\s\S]{0,1200}\b(?:工具|函数|system_time|web_search|url_text_fetch|task)\b/iu,/```(?:json)?\s*(?:system_time|web_search|url_text_fetch|task)\s*```/iu].some(t=>t.test(e))}(e)&&!function looksLikeDelegatedCommentary(t){const e=t.trim();return!(e.length>8e3)&&[/(?:这篇文章|this article)[\s\S]{0,1200}(?:我认为|我认同|打动我|值得深入探讨|特别认同|what I find|I think|I agree)/iu,/(?:你还有什么|还想深入探讨|would you like|do you want).{0,120}[??]\s*$/iu].some(t=>t.test(e))}(e)}(e.toolId,t)).map(t=>({source:e.toolId,output:t})):[]})}export function controlBlockers(t){const e=function successfulEventIndexesBySource(t){const e=new Map;return t.forEach((t,n)=>{const o=function successfulEventSource(t){if("runtime.tool.direct.completed"===t.type)return t.toolId;const e=readAdapterEvent(t);return e&&"agent.tool.result"===e.phase&&"string"==typeof e.toolId&&isSuccessfulEvidenceEvent(e)?e.toolId:void 0}(t);o&&e.set(o,[...e.get(o)??[],n])}),e}(t);return t.flatMap((t,n)=>{const o=readAdapterEvent(t),r=readString(o?.controlStatus)??readOutputStatus(o?.output),s=readString(o?.toolId)??"tool";return r&&isBlockerStatus(r)?isResolvedByLaterCompletion(r)&&function completedAfter(t,e,n){return(t.get(e)??[]).some(t=>t>n)}(e,s,n)?[]:[`${s}:${r}`]:[]})}export function controlGaps(t){const e=new Set(successfulEvidenceItems(t).map(t=>t.source));return t.flatMap(t=>{const n=readAdapterEvent(t),o=readString(n?.controlStatus)??readOutputStatus(n?.output),r=readString(n?.toolId)??"tool";return o&&isGapStatus(o)?e.has(r)&&isResolvedByLaterCompletion(o)?[]:[`${r}:${o}`]:[]})}function stringifyEvidence(t){return"string"==typeof t?t.trim()?[t]:[]:null==t?[]:[JSON.stringify(t)]}function readAdapterEvent(t){return"runtime.adapter.event"===t.type&&isRecord(t.event)?t.event:void 0}function isSuccessfulEvidenceEvent(t){const e=readString(t.controlStatus)??readOutputStatus(t.output);return!e||/^(?:completed|success|ok|recorded)$/iu.test(e)}function isBlockerStatus(t){return/^(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input)$/iu.test(t)}function isGapStatus(t){return/^(?:dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)$/iu.test(t)}function isResolvedByLaterCompletion(t){return isGapStatus(t)||isBlockerStatus(t)}function readOutputStatus(t){if("string"!=typeof t)return;const e=function parseJsonRecord(t){try{const e=JSON.parse(t);return isRecord(e)?e:void 0}catch{return}}(t);return"string"==typeof e?.status?e.status:t.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function readString(t){return"string"==typeof t&&t.trim()?t:void 0}
1
+ export function hasPlanningEvidence(t){return t.some(t=>{const e=readAdapterEvent(t);return!!e&&("plan"===e.traceType||String(e.traceLabel??"").startsWith("plan.")||"write_todos"===e.toolId&&String(e.phase??"").startsWith("agent.tool."))})}export function successfulEvidenceToolIds(t){const e=t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return[t.toolId];const e=readAdapterEvent(t);return e&&"agent.tool.result"===e.phase&&"string"==typeof e.toolId&&isSuccessfulEvidenceEvent(e)?[e.toolId]:[]});return[...new Set(e)]}export function successfulEvidenceOutputs(t){return successfulEvidenceItems(t).map(t=>t.output)}export function successfulEvidenceItems(t){return t.flatMap(t=>{if("runtime.tool.direct.completed"===t.type)return stringifyEvidence(t.output).map(e=>({source:t.toolId,output:e}));const e=readAdapterEvent(t);return e&&"agent.tool.result"===e.phase&&"string"==typeof e.toolId?!isSuccessfulEvidenceEvent(e)||function isPlanningTool(t){return/^(?:write_todos|read_todos)$/u.test(t)}(e.toolId)?[]:stringifyEvidence(e.evidenceOutput??e.output).filter(t=>function isUsableEvidenceOutput(t,e){return"task"!==t||!function looksLikeUnexecutedToolIntent(t){const e=t.trim();return!(e.length>4e3)&&[/\b(?:I need to|I will|I'll|I am going to|I'm going to|Let me)\s+(?:call|use|run|invoke|get|fetch|check)\b[\s\S]{0,1200}\b(?:tool|function|system_time|web_search|url_text_fetch|task)\b/iu,/(?:我需要|我要|我会|我将|让我|我来|接下来我(?:会|将)?)\s*(?:先)?(?:调用|使用|运行|执行|检查|获取|查看)\b[\s\S]{0,1200}\b(?:工具|函数|system_time|web_search|url_text_fetch|task)\b/iu,/```(?:json)?\s*(?:system_time|web_search|url_text_fetch|task)\s*```/iu].some(t=>t.test(e))}(e)&&!function looksLikeDelegatedCommentary(t){const e=t.trim();return!(e.length>8e3)&&[/(?:这篇文章|this article)[\s\S]{0,1200}(?:我认为|我认同|打动我|值得深入探讨|特别认同|what I find|I think|I agree)/iu,/(?:你还有什么|还想深入探讨|would you like|do you want).{0,120}[??]\s*$/iu].some(t=>t.test(e))}(e)}(e.toolId,t)).map(t=>({source:e.toolId,output:t})):[]})}export function controlBlockers(t){const e=function successfulEventIndexesBySource(t){const e=new Map;return t.forEach((t,n)=>{const o=function successfulEventSource(t){if("runtime.tool.direct.completed"===t.type)return t.toolId;const e=readAdapterEvent(t);return e&&"agent.tool.result"===e.phase&&"string"==typeof e.toolId&&isSuccessfulEvidenceEvent(e)?e.toolId:void 0}(t);o&&e.set(o,[...e.get(o)??[],n])}),e}(t);return t.flatMap((t,n)=>{const o=readAdapterEvent(t),r=readString(o?.controlStatus)??readOutputStatus(o?.output),s=readString(o?.toolId)??"tool";return r&&isBlockerStatus(r)?isResolvedByLaterCompletion(r)&&function completedAfter(t,e,n){return(t.get(e)??[]).some(t=>t>n)}(e,s,n)?[]:[`${s}:${r}`]:[]})}export function controlGaps(t){const e=new Set(successfulEvidenceItems(t).map(t=>t.source));return t.flatMap(t=>{const n=readAdapterEvent(t),o=readString(n?.controlStatus)??readOutputStatus(n?.output),r=readString(n?.toolId)??"tool";return o&&isGapStatus(o)?e.has(r)&&isResolvedByLaterCompletion(o)?[]:[`${r}:${o}`]:[]})}function stringifyEvidence(t){return"string"==typeof t?t.trim()?[t]:[]:null==t?[]:[JSON.stringify(t)]}function readAdapterEvent(t){return"runtime.adapter.event"===t.type&&isRecord(t.event)?t.event:void 0}function isSuccessfulEvidenceEvent(t){const e=readString(t.controlStatus)??readOutputStatus(t.output);return!e||/^(?:completed|success|ok|recorded)$/iu.test(e)}function isBlockerStatus(t){return/^(?:blocked|approval_required|schema_repair_failed|tool_argument_error|invalid_input)$/iu.test(t)}function isGapStatus(t){return/^(?:dependency_required|plan_required|repeated_tool_call_limit|duplicate_tool_call)$/iu.test(t)}function isResolvedByLaterCompletion(t){return isGapStatus(t)||isBlockerStatus(t)}function readOutputStatus(t){if("string"!=typeof t)return;const e=function parseJsonRecord(t){try{const e=JSON.parse(t);return isRecord(e)?e:void 0}catch{return}}(t);return"string"==typeof e?.status?e.status:t.match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function readString(t){return"string"==typeof t&&t.trim()?t:void 0}
@@ -1 +1 @@
1
- export function evidenceFields(e){const t=new Set,l=[];for(const a of e)for(const e of parseEvidenceFields(a)){const a=`${normalizeFieldLabel(e.label)}\0${e.value.toLowerCase()}`;t.has(a)||(t.add(a),l.push(e))}return l}export function selectSectionFields(e,t,l){return function withSourceCoverage(e,t){const l=[...e].sort((e,t)=>scoreField(t)-scoreField(e)),a=new Map;for(const e of[...new Set(l.map(e=>e.source))]){const t=l.find(t=>t.source===e);t&&a.set(fieldKey(t),t)}for(const e of l)if(a.set(fieldKey(e),e),a.size>=t)break;return[...a.values()].slice(0,t)}(e.filter(e=>e.kind===t),l).sort((e,t)=>scoreField(t)-scoreField(e)||e.label.localeCompare(t.label))}export function fieldTableLines(e,t){return 0===e.length?[]:[..."zh"===t?["| 项目 | 数值 | 来源 |","|---|---:|---|"]:["| Field | Value | Source |","|---|---:|---|"],...e.map(e=>`| ${escapeTableCell(e.label)} | ${escapeTableCell(e.value)} | ${escapeTableCell(function humanSourceLabel(e){const t=e.replace(/([a-z])([A-Z])/gu,"$1 $2").split(/[_:.\-\s]+/u).map(e=>e.trim()).filter(Boolean);return 0===t.length?e:t.map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}(e.source))} |`)]}export function hasExtractableFields(e){return extractKeyValueFields(e).some(e=>!isBoilerplateField(e.label)&&e.value.length>0)}export function classifyFact(e){return/(?:gap|blocked|missing|unavailable|unsupported|缺口|阻塞|缺失|不支持|无法|未提供)/iu.test(e)?"limit":/(?:news|headline|recent|latest|filing|event|公告|新闻|近期|最新|披露|\b20\d{2}[-/年])/iu.test(e)?"timeBound":/(?:[$€£¥%]|\b\d[\d,]*(?:\.\d+)?\b)/u.test(e)?"data":/(?:name|company|symbol|resolved|overview|query|名称|公司|代码|概览|识别)/iu.test(e)?"context":"other"}function parseEvidenceFields(e){return extractKeyValueFields(e.text).filter(e=>e.value.length>0&&!isBoilerplateField(e.label)).filter(e=>!function isLowValueField(e,t){return!!/(?:snapshot for|source type|loaded sources)/iu.test(e)||!!/^\d{1,2}\s+(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b/iu.test(e)||scoreField({source:"",label:e,value:t,kind:"other"})<0}(e.label,e.value)).map(t=>{const l=classifyFact(`${t.label}: ${t.value}`);return{source:e.source,label:titleCaseLabel(t.label),value:formatEvidence(t.value),kind:"other"===l?e.kind:l}})}function scoreField(e){const t=normalizeFieldLabel(e.label);let l=e.value.length>0?10:0;return/(?:price|value|amount|total|ratio|rate|range|target|estimate|revenue|income|earnings|margin|volume|date|rating|status|count|metric|价格|收入|利润|目标|评级|数量|日期|范围|比率)/iu.test(t)&&(l+=8),/(?:name|company|symbol|title|headline|summary|名称|公司|代码|标题|摘要)/iu.test(t)&&(l+=6),/(?:unix|epoch|timestamp|raw|html|url|href|source|id|identifier|internal|debug)/iu.test(t)&&(l-=20),(/^https?:\/\//iu.test(e.value)||"/"===e.value)&&(l-=12),e.value.length>240&&(l-=5),l}function extractKeyValueFields(e){const t=[...e.matchAll(/(^|[\s;|])([\p{L}\p{N}][\p{L}\p{N} _./()%&+\-]{0,48})[::](?!\/\/)\s*/gu)].filter(e=>void 0!==e.index).map((e,t,l)=>{l[t-1];const a=function cleanFieldLabel(e){const t=e.replace(/^(?:[-*]\s*)+/u,"").replace(/\s+/gu," ").trim(),l=t.match(/^.+\b(PE Ratio TTM)$/iu);if(l?.[1]&&l[1]!==t&&/(?:beta|\b20\d{2}|\b(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b)/iu.test(t))return l[1];const a=t.split(" ").filter(Boolean);return a.length>1&&/^\d{4}$/u.test(a[0]??"")||a.length>1&&/^\d+(?:\.\d+)?$/u.test(a[0]??"")&&/^(?:\d+|beta|pe|p\/b)$/iu.test(a[1]??"")||a.length>1&&/^[A-Z]$/u.test(a[0]??"")||a.length>1&&/^(?:inc\.?|llc\.?|ltd\.?|corp\.?|corporation|co\.?)$/iu.test(a[0]??"")||a.length>1&&/^(?:usd|eur|gbp|jpy|cny|cad|aud)$/iu.test(a[0]??"")||a.length>1&&/^(?:gmt|utc)$/iu.test(a[0]??"")?a.slice(1).join(" "):function trailingKnownLabel(e){if(/\bPE Ratio TTM$/iu.test(e)&&!/^PE Ratio TTM$/iu.test(e))return"PE Ratio TTM";const t=e.match(/\b(?:Revenue|Net Income|Operating Income|Diluted EPS|EPS|Market Cap|Book Value|Target Estimate|Target Mean Price|Target Median Price|Target High Price|Target Low Price|PE Ratio TTM|P\/B|Beta(?: 5Y Monthly)?|Published|Updated|Date|Time|Summary|Title|Headline)$/iu);return t&&/(?:filed|\b20\d{2}|10-k|10-q|\bfy\b|\b(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b|\s{3,}|[a-z].{8,}\s)/iu.test(e.slice(0,t.index))?t?.[0]??e:e}(t)}(e[2]??""),r=function droppedLabelPrefix(e,t){const l=e.trim();if(l===t)return"";const a=l.toLowerCase().lastIndexOf(t.toLowerCase());return a>0?l.slice(0,a):""}(e[2]??"",a);return{index:(e.index??0)+String(e[1]??"").length+r.length,start:(e.index??0)+e[0].length,label:a}}).filter(e=>!function isBoundaryNoiseLabel(e){return/^\d{1,2}\s+(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b/iu.test(e)}(e.label));return t.map((l,a)=>{const r=t[a+1]?.index??e.length;return{label:l.label,value:cleanFieldValue(e.slice(l.start,r),l.label)}}).filter(e=>e.label.length>0)}function cleanFieldValue(e,t){const l=e.replace(/^[\s,;|.-]+/u,"").replace(/[\s,;|.-]+$/u,"").replace(/\s+/gu," ").trim(),a=normalizeFieldLabel(t);if(/\brange\b/iu.test(a))return l.replace(/\s+Beta\b.*$/iu,"").trim();if(/^(?:ticker|symbol|resolved symbol|resolved ticker|股票 resolved ticker|代码)$/iu.test(a)){const e=l.match(/^([A-Z0-9._-]{1,24})(?:\s+\d+[.)]\s+|$)/u);if(e?.[1])return e[1]}return l}function isBoilerplateField(e){return/^(?:status|control status|evidence tool|tool|source|来源)$/iu.test(e.trim())}export function normalizeFieldLabel(e){return e.toLowerCase().replace(/[^a-z0-9\p{L}\p{N}]+/giu," ").trim()}function titleCaseLabel(e){if(/\p{Script=Han}/u.test(e))return e;const t=e.split(/[^A-Za-z0-9]+/u).filter(Boolean);return normalizeFieldLabel(e).split(" ").filter(Boolean).map((e,l)=>{const a=t[l]??e;return/^[A-Z0-9]{2,}$/u.test(a)?a:e.charAt(0).toUpperCase()+e.slice(1)}).join(" ")}function formatEvidence(e){const t=e.replace(/\s+/gu," ").trim();return t.length>1200?`${t.slice(0,1197)}...`:t}function escapeTableCell(e){return e.replace(/\|/gu,"\\|").replace(/\r?\n/gu," ")}function fieldKey(e){return`${e.source}\0${normalizeFieldLabel(e.label)}\0${e.value.toLowerCase()}`}
1
+ export function evidenceFields(e){const t=new Set,l=[];for(const a of e)for(const e of parseEvidenceFields(a)){const a=`${normalizeFieldLabel(e.label)}\0${e.value.toLowerCase()}`;t.has(a)||(t.add(a),l.push(e))}return l}export function selectSectionFields(e,t,l){return function withSourceCoverage(e,t){const l=[...e].sort((e,t)=>scoreField(t)-scoreField(e)),a=new Map;for(const e of[...new Set(l.map(e=>e.source))]){const t=l.find(t=>t.source===e);t&&a.set(fieldKey(t),t)}for(const e of l)if(a.set(fieldKey(e),e),a.size>=t)break;return[...a.values()].slice(0,t)}(e.filter(e=>e.kind===t),l).sort((e,t)=>scoreField(t)-scoreField(e)||e.label.localeCompare(t.label))}export function fieldTableLines(e,t){return 0===e.length?[]:[..."zh"===t?["| 项目 | 数值 | 来源 |","|---|---:|---|"]:["| Field | Value | Source |","|---|---:|---|"],...e.map(e=>`| ${escapeTableCell(e.label)} | ${escapeTableCell(e.value)} | ${escapeTableCell(function humanSourceLabel(e){const t=e.replace(/([a-z])([A-Z])/gu,"$1 $2").split(/[_:.\-\s]+/u).map(e=>e.trim()).filter(Boolean);return 0===t.length?e:t.map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}(e.source))} |`)]}export function hasExtractableFields(e){return extractKeyValueFields(e).some(e=>!isBoilerplateField(e.label)&&e.value.length>0)}export function classifyFact(e){return/(?:gap|blocked|missing|unavailable|unsupported|缺口|阻塞|缺失|不支持|无法|未提供)/iu.test(e)?"limit":/(?:news|headline|recent|latest|filing|event|公告|新闻|近期|最新|披露|\b20\d{2}[-/年])/iu.test(e)?"timeBound":/(?:[$€£¥%]|\b\d[\d,]*(?:\.\d+)?\b)/u.test(e)?"data":/(?:name|company|symbol|resolved|overview|query|名称|公司|代码|概览|识别)/iu.test(e)?"context":"other"}function parseEvidenceFields(e){return extractKeyValueFields(e.text).filter(e=>e.value.length>0&&!isBoilerplateField(e.label)).filter(e=>!function isLowValueField(e,t){return!!/(?:snapshot for|source type|loaded sources)/iu.test(e)||!!/^\d{1,2}\s+(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b/iu.test(e)||scoreField({source:"",label:e,value:t,kind:"other"})<0}(e.label,e.value)).map(t=>{const l=classifyFact(`${t.label}: ${t.value}`);return{source:e.source,label:titleCaseLabel(t.label),value:formatEvidence(t.value),kind:"other"===l?e.kind:l}})}function scoreField(e){const t=normalizeFieldLabel(e.label);let l=e.value.length>0?10:0;return/(?:price|value|amount|total|ratio|rate|range|target|estimate|revenue|income|earnings|margin|volume|date|rating|status|count|metric|价格|收入|利润|目标|评级|数量|日期|范围|比率)/iu.test(t)&&(l+=8),/(?:name|company|symbol|title|headline|summary|名称|公司|代码|标题|摘要)/iu.test(t)&&(l+=6),/(?:unix|epoch|timestamp|raw|html|url|href|source|id|identifier|internal|debug)/iu.test(t)&&(l-=20),(/^https?:\/\//iu.test(e.value)||"/"===e.value)&&(l-=12),e.value.length>240&&(l-=5),l}function extractKeyValueFields(e){const t=[...e.matchAll(/(^|[\s;|])([\p{L}\p{N}][\p{L}\p{N} _./()%&+\-]{0,48})[::](?!\/\/)\s*/gu)].filter(e=>void 0!==e.index).map((e,t,l)=>{l[t-1];const a=function cleanFieldLabel(e){const t=e.replace(/^(?:[-*]\s*)+/u,"").replace(/\s+/gu," ").trim(),l=t.match(/^.+\b(PE Ratio TTM)$/iu);if(l?.[1]&&l[1]!==t&&/(?:beta|\b20\d{2}|\b(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b)/iu.test(t))return l[1];const a=t.split(" ").filter(Boolean);return a.length>1&&/^\d{4}$/u.test(a[0]??"")||a.length>1&&/^\d+(?:\.\d+)?$/u.test(a[0]??"")&&/^(?:\d+|beta|pe|p\/b)$/iu.test(a[1]??"")||a.length>1&&/^[A-Z]$/u.test(a[0]??"")||a.length>1&&/^(?:inc\.?|llc\.?|ltd\.?|corp\.?|corporation|co\.?)$/iu.test(a[0]??"")||a.length>1&&/^(?:usd|eur|gbp|jpy|cny|cad|aud)$/iu.test(a[0]??"")||a.length>1&&/^(?:gmt|utc)$/iu.test(a[0]??"")?a.slice(1).join(" "):function trailingKnownLabel(e){if(/\bPE Ratio TTM$/iu.test(e)&&!/^PE Ratio TTM$/iu.test(e))return"PE Ratio TTM";const t=e.match(/\b(?:Revenue|Net Income|Operating Income|Diluted EPS|EPS|Market Cap|Book Value|Target Estimate|Target Mean Price|Target Median Price|Target High Price|Target Low Price|PE Ratio TTM|P\/B|Beta(?: 5Y Monthly)?|Published|Updated|Date|Time|Summary|Title|Headline)$/iu);return t&&/(?:filed|\b20\d{2}|10-k|10-q|\bfy\b|\b(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b|\s{3,}|[a-z].{8,}\s)/iu.test(e.slice(0,t.index))?t?.[0]??e:e}(t)}(e[2]??""),r=function droppedLabelPrefix(e,t){const l=e.trim();if(l===t)return"";const a=l.toLowerCase().lastIndexOf(t.toLowerCase());return a>0?l.slice(0,a):""}(e[2]??"",a);return{index:(e.index??0)+String(e[1]??"").length+r.length,start:(e.index??0)+e[0].length,label:a,rawLabel:e[2]??""}}).filter(e=>!isBoundaryNoiseLabel(e.label)&&!isBoundaryNoiseLabel(e.rawLabel));return t.map((l,a)=>{const r=t[a+1]?.index??e.length;return{label:l.label,value:cleanFieldValue(e.slice(l.start,r),l.label)}}).filter(e=>e.label.length>0)}function cleanFieldValue(e,t){const l=e.replace(/^[\s,;|.-]+/u,"").replace(/[\s,;|.-]+$/u,"").replace(/\s+/gu," ").trim(),a=normalizeFieldLabel(t);if(/\brange\b/iu.test(a))return l.replace(/\s+Beta\b.*$/iu,"").trim();if(/^(?:ticker|symbol|resolved symbol|resolved ticker|股票 resolved ticker|代码)$/iu.test(a)){const e=l.match(/^([A-Z0-9._-]{1,24})(?:\s+\d+[.)]\s+|$)/u);if(e?.[1])return e[1]}return l}function isBoilerplateField(e){return/^(?:status|control status|evidence tool|tool|source|来源)$/iu.test(e.trim())}function isBoundaryNoiseLabel(e){return/^\d{1,2}\s+(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b/iu.test(e)||/^(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s+\d{1,4}(?:\s+\d{1,2})?$/iu.test(e)||/^\d{4}\s+\d{1,2}$/u.test(e)}export function normalizeFieldLabel(e){return e.toLowerCase().replace(/[^a-z0-9\p{L}\p{N}]+/giu," ").trim()}function titleCaseLabel(e){if(/\p{Script=Han}/u.test(e))return e;const t=e.split(/[^A-Za-z0-9]+/u).filter(Boolean);return normalizeFieldLabel(e).split(" ").filter(Boolean).map((e,l)=>{const a=t[l]??e;return/^[A-Z0-9]{2,}$/u.test(a)?a:e.charAt(0).toUpperCase()+e.slice(1)}).join(" ")}function formatEvidence(e){const t=e.replace(/\s+/gu," ").trim();return t.length>1200?`${t.slice(0,1197)}...`:t}function escapeTableCell(e){return e.replace(/\|/gu,"\\|").replace(/\r?\n/gu," ")}function fieldKey(e){return`${e.source}\0${normalizeFieldLabel(e.label)}\0${e.value.toLowerCase()}`}
@@ -1,6 +1,7 @@
1
1
  import type { MemoryCandidate, MemoryDecision, MemoryRecord } from "@stable-harness/memory";
2
2
  import type { ApprovalRequest } from "@stable-harness/governance";
3
3
  import type { RuntimeArtifact } from "../types.js";
4
+ import type { RuntimeSandboxDecision } from "./tool-gateway.js";
4
5
  import type { RuntimeToolFailureClassification, RuntimeToolFailureReason } from "./tool-failure.js";
5
6
  export type RuntimeInventoryRepairLayer = "agent" | "workflow_route" | "workflow" | "tool" | "task" | "skill";
6
7
  export type RuntimeInventoryRepairStatus = "repaired" | "blocked";
@@ -71,6 +72,13 @@ export type RuntimeEvent = {
71
72
  agentId: string;
72
73
  toolId: string;
73
74
  output: unknown;
75
+ } | {
76
+ type: "runtime.sandbox.decision";
77
+ requestId: string;
78
+ sessionId: string;
79
+ agentId: string;
80
+ toolId: string;
81
+ decision: RuntimeSandboxDecision;
74
82
  } | {
75
83
  type: "runtime.approval.requested";
76
84
  requestId: string;
@@ -0,0 +1,9 @@
1
+ import type { CompiledWorkspace, RuntimeEvent, RuntimeToolGateway } from "../../types.js";
2
+ import type { RuntimeSandboxPolicy } from "../tool-gateway.js";
3
+ export declare function createSandboxedToolGateway(input: {
4
+ gateway?: RuntimeToolGateway;
5
+ workspace: CompiledWorkspace;
6
+ sandbox?: RuntimeSandboxPolicy | false;
7
+ emit: (event: RuntimeEvent) => void;
8
+ }): RuntimeToolGateway | undefined;
9
+ export declare function createWorkspaceSandboxPolicy(config: unknown): RuntimeSandboxPolicy | undefined;
@@ -0,0 +1 @@
1
+ export function createSandboxedToolGateway(e){const o=!1===e.sandbox?void 0:e.sandbox??createWorkspaceSandboxPolicy(e.workspace.runtime.sandbox);return e.gateway&&o?{get:o=>e.gateway.get(o),repairToolCall:e.gateway.repairToolCall?o=>e.gateway.repairToolCall(o):void 0,async invoke(t){const n=await o.decide({toolId:t.toolId,args:t.args,context:t.context});return function emitDecision(e,o,t){e({type:"runtime.sandbox.decision",requestId:o.context.requestId,sessionId:o.context.sessionId,agentId:o.context.agentId,toolId:o.toolId,decision:t})}(e.emit,t,n),"deny"===n.action?{toolId:t.toolId,output:sandboxDeniedOutput(t.toolId,n)}:e.gateway.invoke({...t,context:{...t.context,sandbox:n}})}}:e.gateway}export function createWorkspaceSandboxPolicy(e){const o=readRecord(e);if(!o||!1===o.enabled)return;const t=function readRuleMap(e){const o=readRecord(e);return o?new Map(Object.entries(o).map(([e,o])=>[e,readRule(o)])):new Map}(o.byToolId??o.sandboxByToolId??o.profilesByToolId),n=new Set(function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.trim().length>0):[]}(o.denyToolIds)),a=function fallbackDecision(e){const o=readAction(e.defaultAction)??"allow",t=readString(e.defaultProfile)??readString(e.profile);return{action:o,...t?{profile:t}:{},reason:"allow"===o?"No sandbox rule matched; default allow applied.":"No sandbox rule matched; default deny applied."}}(o);return{decide:e=>n.has(e.toolId)?{action:"deny",reason:"Tool is denied by sandbox policy."}:t.get(e.toolId)??a}}function sandboxDeniedOutput(e,o){return{status:"sandbox_denied",toolId:e,reason:o.reason??"Tool execution was denied by sandbox policy.",...o.profile?{profile:o.profile}:{},...o.policyId?{policyId:o.policyId}:{}}}function readRule(e){if("string"==typeof e&&e.trim())return{action:"allow",profile:e.trim()};const o=readRecord(e);if(!o)return{action:"allow"};const t=readAction(o.action)??(!0===o.deny?"deny":"allow"),n=readString(o.profile),a=readString(o.reason),r=readString(o.policyId),d=readRecord(o.metadata);return{action:t,...n?{profile:n}:{},...a?{reason:a}:{},...r?{policyId:r}:{},...d?{metadata:d}:{}}}function readAction(e){return"allow"===e||"deny"===e?e:void 0}function readString(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function readRecord(e){return"object"!=typeof e||null===e||Array.isArray(e)?void 0:e}
@@ -10,6 +10,22 @@ export type RuntimeToolGatewayContext = {
10
10
  requestInput?: string;
11
11
  observedEvidence?: string;
12
12
  approvalIds?: string[];
13
+ sandbox?: RuntimeSandboxDecision;
14
+ };
15
+ export type RuntimeSandboxDecision = {
16
+ action: "allow" | "deny";
17
+ profile?: string;
18
+ reason?: string;
19
+ policyId?: string;
20
+ metadata?: Record<string, unknown>;
21
+ };
22
+ export type RuntimeSandboxPolicyInput = {
23
+ toolId: string;
24
+ args?: unknown;
25
+ context: RuntimeToolGatewayContext;
26
+ };
27
+ export type RuntimeSandboxPolicy = {
28
+ decide(input: RuntimeSandboxPolicyInput): Promise<RuntimeSandboxDecision> | RuntimeSandboxDecision;
13
29
  };
14
30
  export type RuntimeToolGatewayTool = {
15
31
  id: string;
@@ -1,7 +1,7 @@
1
1
  import type { ApprovalQueue } from "@stable-harness/governance";
2
2
  import type { MemoryProvider, RuntimeMemoryStore } from "@stable-harness/memory";
3
3
  import type { QualityReviewModel } from "./quality/index.js";
4
- import type { CompiledWorkspace, RuntimeCapabilityModule, RuntimeToolGateway, RuntimeAdapter, RuntimeArtifactStore, RuntimeStore, RuntimeProgressNarrationOptions, RuntimeWorkflowAdapter, StableHarnessRuntime } from "./types.js";
4
+ import type { CompiledWorkspace, RuntimeCapabilityModule, RuntimeToolGateway, RuntimeAdapter, RuntimeArtifactStore, RuntimeSandboxPolicy, RuntimeStore, RuntimeProgressNarrationOptions, RuntimeWorkflowAdapter, StableHarnessRuntime } from "./types.js";
5
5
  type RuntimeFactoryInput = {
6
6
  workspace: CompiledWorkspace;
7
7
  adapters: RuntimeAdapter[];
@@ -10,6 +10,7 @@ type RuntimeFactoryInput = {
10
10
  memoryProviders?: MemoryProvider[];
11
11
  approvals?: ApprovalQueue;
12
12
  toolGateway?: RuntimeToolGateway;
13
+ sandbox?: RuntimeSandboxPolicy | false;
13
14
  store?: RuntimeStore;
14
15
  artifacts?: RuntimeArtifactStore;
15
16
  progressNarration?: RuntimeProgressNarrationOptions | false;
@@ -1 +1 @@
1
- import{randomUUID as e}from"node:crypto";import{assertExecutionContract as t}from"./execution-contract.js";import{assertNoRawToolCallOutput as r,assertNoToolExecutionErrorOutput as a,buildAdapterErrorRecoveryPrompt as s,buildEvidenceSynthesisOutput as o,buildExecutionContractRecoveryRequest as n,buildResultRecoveryRequest as i,containsRawToolCallOutput as u,isRecoverableAdapterError as c,rawToolCallFailureMessage as l,toolCallRecoveryEnabled as p}from"./recovery/tool-call.js";import{recoverQualityReview as d,resolveQualityPolicy as m}from"./quality/index.js";import{completeRun as y,failRun as w}from"./runtime/completion.js";import{runDirectToolCall as f}from"./runtime/direct-tool-call.js";import{createApprovalGatedToolGateway as I}from"./runtime/governance/approval-gate.js";import{createRuntimeInspectionMethods as g}from"./runtime/inspection/methods.js";import{createRuntimeCapabilityRegistry as q,normalizeAdapterResult as R}from"./runtime/capabilities.js";import{createMemoryRuntimeCapability as v}from"./runtime/memory.js";import{createInMemoryRuntimeStore as k}from"./runtime/persistence/stores.js";import{createProgressNarrationCapability as b}from"./runtime/progress-narration.js";import{repairRuntimeSelection as A}from"./runtime/selection-repair.js";import{createToolFailureTracker as C}from"./runtime/tool-failure.js";import{runWorkflowRequest as x}from"./workflows/runtime.js";export function createStableHarnessRuntime(t){const r=new Set,a=t.store??k(),o=q([v(t),b({options:t.progressNarration,policy:t.workspace.runtime}),...t.capabilities??[]]),emitBase=e=>{a.appendEvent(e);for(const t of r)t(e)},emit=e=>{emitBase(e),o.emitSideEffects(e,emitBase)},i={...t,toolGateway:I({gateway:t.toolGateway,approvals:t.approvals,workspace:t.workspace,emit:emit})},u=C(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}(t.workspace.runtime.toolGateway));return{request:async t=>async function runRuntimeRequest(t){const r=t.request.requestId??e(),a=t.request.sessionId??e(),o=[],{agent:i,adapter:u}=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 A({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):function resolveRoutedAgentId(e,t){for(const r of e.runtime.routes??[])if(routeMatches(r,t))return r.agentId;return e.runtime.defaultAgentId}(e.workspace,t.input),s=e.workspace.agents.get(a);if(!s)throw new Error(`Agent ${a} is not defined in the workspace`);if(t.toolCall||t.workflow)return{agent:s,adapter:void 0};const o=e.adapters.find(e=>e.canRun(s));if(!o)throw new Error(`No runtime adapter can run backend ${s.backend} for agent ${s.id}`);return{agent:s,adapter:o}}(t.input,t.request,{requestId:r,sessionId:a,emit:e=>o.push(e)});t.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:[]}}(t.request,r,a,i)),o.forEach(t.emit),t.emit({type:"runtime.request.started",requestId:r,sessionId:a,agentId:i.id,input:t.request.input});try{if(t.request.workflow){const e=await x({workspace:t.input.workspace,adapters:t.input.workflowAdapters??[],toolGateway:t.input.toolGateway,request:{input:t.request.input,...t.request.workflow},requestId:r,sessionId:a,agentId:i.id,emit:t.emit});return y({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,result:e,artifacts:t.input.artifacts})}if(t.request.toolCall){const e=await f({gateway:t.input.toolGateway,workspace:t.input.workspace,emit:t.emit,request:t.request,requestId:r,sessionId:a,agent:i,toolFailureTracker:t.toolFailureTracker});return y({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,result:e,artifacts:t.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 t=e.adapter,r=await e.capabilities.beforeAdapterRun(createCapabilityContext(e)),a=r.memory,o=r.pluginMemories??[],i=e.input.workspace.runtime,u=m(e.input.workspace.runtime,e.agent),l=new Map;let p;try{p=await runAdapterOnce(e,t,e.request,a,o,l)}catch(r){if(!c(r,i))throw r;p=await runAdapterOnce(e,t,s(e.request,r,i),a,o,l)}p=await recoverAdapterResultOutput(e,t,e.request,p,a,o,i,l),p=await d(createQualityRuntimeInput(e,a,o,l),e.request,p,u),await e.capabilities.beforeAdapterResultContract({...createCapabilityContext(e),result:p});try{assertRequestExecutionContract(e)}catch(r){const s=n({request:e.request,events:e.store.getRun(e.requestId)?.events??[],policy:i});if(!s)throw r;p=await runAdapterOnce(e,t,s,a,o,l),p=await recoverAdapterResultOutput(e,t,s,p,a,o,i,l),p=await d(createQualityRuntimeInput(e,a,o,l),s,p,u),assertRequestExecutionContract(e)}const w=y({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,result:p,artifacts:e.input.artifacts});return await e.capabilities.afterAdapterResponse({...createCapabilityContext(e),result:p,response:w}),w}({...t,adapter:u,requestId:r,sessionId:a,agent:i})}catch(e){return w({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,error:e})}}({input:i,capabilities:o,store:a,emit:emit,request:t,toolFailureTracker:u}),subscribe:e=>(r.add(e),()=>r.delete(e)),...g({workspace:t.workspace,store:a,artifacts:t.artifacts,approvals:t.approvals,emit:emit}),cancel(e,t){const r=a.getRun(e);r&&"running"===r.state&&(a.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 o.stop(),r.clear()}}}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){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:s=>runAdapterOnce(e,e.adapter,s,t,r,a),reviewModel:e.input.qualityReviewModel,memory:t,pluginMemories:r}}async function recoverAdapterResultOutput(e,t,s,n,c,d,m,y){let w=s;const f=function resultRecoveryAttempts(e){const t="object"!=typeof e||null===e||Array.isArray(e)?void 0:e.recovery,r="object"!=typeof t||null===t||Array.isArray(t)?void 0:t.toolCall,a="object"!=typeof r||null===r||Array.isArray(r)?void 0:r.maxResultRecoveryAttempts;return"number"==typeof a&&Number.isInteger(a)&&a>0?a:3}(m);let I=0;for(let r=0;r<f;r+=1){const r=e.store.getRun(e.requestId)?.events??[],a=i({request:w,output:n.text,events:r.slice(I),availableToolIds:e.agent.tools,policy:m});if(!a)break;w=a,I=e.store.getRun(e.requestId)?.events.length??0,n=await runAdapterOnce(e,t,a,c,d,y)}if(p(m)){let t=!1;u(n.text,m)&&function rawToolCallFailureReturnsMessage(e){return"message"===("object"!=typeof e?.toolCallRecovery||null===e.toolCallRecovery||Array.isArray(e.toolCallRecovery)?{}:e.toolCallRecovery).onFailure}(s.metadata)&&(n={...n,text:l(),metadata:{...n.metadata,toolCallRecovery:{failed:!0,reason:"raw_tool_call_output"}}});const i=o({request:s,output:n.text,events:e.store.getRun(e.requestId)?.events??[],policy:m});i&&(t=!0,n={...n,text:i,metadata:{...n.metadata,toolCallRecovery:{synthesized:!0,reason:"raw_tool_call_output_with_evidence"}}}),t||(r(n.text,m),a(n.text,m))}return n}function assertRequestExecutionContract(e){t({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,metadata:e.request.metadata})}async function runAdapterOnce(e,t,r,a,s,o){return R(await t.run({workspace:e.input.workspace,agent:e.agent,request:r,requestId:e.requestId,sessionId:e.sessionId,memory:a,pluginMemories:s,toolGateway:e.input.toolGateway,toolFailureTracker:e.input.toolFailureTracker,requestState:o,emit:e.emit}))}function routeMatches(e,t){if(e.pattern)try{if(new RegExp(e.pattern,"iu").test(t))return!0}catch{return!1}const r=t.toLowerCase();return(e.keywords??[]).some(e=>r.includes(e.toLowerCase()))}
1
+ import{randomUUID as e}from"node:crypto";import{assertExecutionContract as t}from"./execution-contract.js";import{assertNoRawToolCallOutput as r,assertNoToolExecutionErrorOutput as a,buildAdapterErrorRecoveryPrompt as o,buildEvidenceSynthesisOutput as s,buildExecutionContractRecoveryRequest as n,buildResultRecoveryRequest as i,containsRawToolCallOutput as u,isRecoverableAdapterError as c,rawToolCallFailureMessage as l,toolCallRecoveryEnabled as p}from"./recovery/tool-call.js";import{recoverQualityReview as d,resolveQualityPolicy as m}from"./quality/index.js";import{completeRun as w,failRun as y}from"./runtime/completion.js";import{runDirectToolCall as f}from"./runtime/direct-tool-call.js";import{createApprovalGatedToolGateway as g}from"./runtime/governance/approval-gate.js";import{createSandboxedToolGateway as I}from"./runtime/governance/sandbox.js";import{createRuntimeInspectionMethods as q}from"./runtime/inspection/methods.js";import{createRuntimeCapabilityRegistry as R,normalizeAdapterResult as v}from"./runtime/capabilities.js";import{createMemoryRuntimeCapability as b}from"./runtime/memory.js";import{createInMemoryRuntimeStore as k}from"./runtime/persistence/stores.js";import{createProgressNarrationCapability as A}from"./runtime/progress-narration.js";import{repairRuntimeSelection as C}from"./runtime/selection-repair.js";import{createToolFailureTracker as x}from"./runtime/tool-failure.js";import{runWorkflowRequest as h}from"./workflows/runtime.js";export function createStableHarnessRuntime(t){const r=new Set,a=t.store??k(),s=R([b(t),A({options:t.progressNarration,policy:t.workspace.runtime}),...t.capabilities??[]]),emitBase=e=>{a.appendEvent(e);for(const t of r)t(e)},emit=e=>{emitBase(e),s.emitSideEffects(e,emitBase)},i=I({gateway:g({gateway:t.toolGateway,approvals:t.approvals,workspace:t.workspace,emit:emit}),workspace:t.workspace,sandbox:t.sandbox,emit:emit}),u={...t,toolGateway:i},l=x(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}(t.workspace.runtime.toolGateway));return{request:async t=>async function runRuntimeRequest(t){const r=t.request.requestId??e(),a=t.request.sessionId??e(),s=[],{agent:i,adapter:u}=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 C({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):function resolveRoutedAgentId(e,t){for(const r of e.runtime.routes??[])if(routeMatches(r,t))return r.agentId;return e.runtime.defaultAgentId}(e.workspace,t.input),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 s=e.adapters.find(e=>e.canRun(o));if(!s)throw new Error(`No runtime adapter can run backend ${o.backend} for agent ${o.id}`);return{agent:o,adapter:s}}(t.input,t.request,{requestId:r,sessionId:a,emit:e=>s.push(e)});t.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:[]}}(t.request,r,a,i)),s.forEach(t.emit),t.emit({type:"runtime.request.started",requestId:r,sessionId:a,agentId:i.id,input:t.request.input});try{if(t.request.workflow){const e=await h({workspace:t.input.workspace,adapters:t.input.workflowAdapters??[],toolGateway:t.input.toolGateway,request:{input:t.request.input,...t.request.workflow},requestId:r,sessionId:a,agentId:i.id,emit:t.emit});return w({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,result:e,artifacts:t.input.artifacts})}if(t.request.toolCall){const e=await f({gateway:t.input.toolGateway,workspace:t.input.workspace,emit:t.emit,request:t.request,requestId:r,sessionId:a,agent:i,toolFailureTracker:t.toolFailureTracker});return w({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,result:e,artifacts:t.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 t=e.adapter,r=await e.capabilities.beforeAdapterRun(createCapabilityContext(e)),a=r.memory,s=r.pluginMemories??[],i=e.input.workspace.runtime,u=m(e.input.workspace.runtime,e.agent),l=new Map;let p;try{p=await runAdapterOnce(e,t,e.request,a,s,l)}catch(r){if(!c(r,i))throw r;p=await runAdapterOnce(e,t,o(e.request,r,i),a,s,l)}p=await recoverAdapterResultOutput(e,t,e.request,p,a,s,i,l),p=await d(createQualityRuntimeInput(e,a,s,l),e.request,p,u),await e.capabilities.beforeAdapterResultContract({...createCapabilityContext(e),result:p});try{assertRequestExecutionContract(e)}catch(r){const o=n({request:e.request,events:e.store.getRun(e.requestId)?.events??[],policy:i});if(!o)throw r;p=await runAdapterOnce(e,t,o,a,s,l),p=await recoverAdapterResultOutput(e,t,o,p,a,s,i,l),p=await d(createQualityRuntimeInput(e,a,s,l),o,p,u),assertRequestExecutionContract(e)}const y=w({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,result:p,artifacts:e.input.artifacts});return await e.capabilities.afterAdapterResponse({...createCapabilityContext(e),result:p,response:y}),y}({...t,adapter:u,requestId:r,sessionId:a,agent:i})}catch(e){return y({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,error:e})}}({input:u,capabilities:s,store:a,emit:emit,request:t,toolFailureTracker:l}),subscribe:e=>(r.add(e),()=>r.delete(e)),...q({workspace:t.workspace,store:a,artifacts:t.artifacts,approvals:t.approvals,emit:emit}),cancel(e,t){const r=a.getRun(e);r&&"running"===r.state&&(a.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 s.stop(),r.clear()}}}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){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:o=>runAdapterOnce(e,e.adapter,o,t,r,a),reviewModel:e.input.qualityReviewModel,memory:t,pluginMemories:r}}async function recoverAdapterResultOutput(e,t,o,n,c,d,m,w){let y=o;const f=function resultRecoveryAttempts(e){const t="object"!=typeof e||null===e||Array.isArray(e)?void 0:e.recovery,r="object"!=typeof t||null===t||Array.isArray(t)?void 0:t.toolCall,a="object"!=typeof r||null===r||Array.isArray(r)?void 0:r.maxResultRecoveryAttempts;return"number"==typeof a&&Number.isInteger(a)&&a>0?a:3}(m);let g=0;for(let r=0;r<f;r+=1){const r=e.store.getRun(e.requestId)?.events??[],a=i({request:y,output:n.text,events:r.slice(g),availableToolIds:e.agent.tools,policy:m});if(!a)break;y=a,g=e.store.getRun(e.requestId)?.events.length??0,n=await runAdapterOnce(e,t,a,c,d,w)}if(p(m)){let t=!1;u(n.text,m)&&function rawToolCallFailureReturnsMessage(e){return"message"===("object"!=typeof e?.toolCallRecovery||null===e.toolCallRecovery||Array.isArray(e.toolCallRecovery)?{}:e.toolCallRecovery).onFailure}(o.metadata)&&(n={...n,text:l(),metadata:{...n.metadata,toolCallRecovery:{failed:!0,reason:"raw_tool_call_output"}}});const i=s({request:o,output:n.text,events:e.store.getRun(e.requestId)?.events??[],policy:m});i&&(t=!0,n={...n,text:i,metadata:{...n.metadata,toolCallRecovery:{synthesized:!0,reason:"raw_tool_call_output_with_evidence"}}}),t||(r(n.text,m),a(n.text,m))}return n}function assertRequestExecutionContract(e){t({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,metadata:e.request.metadata})}async function runAdapterOnce(e,t,r,a,o,s){return v(await t.run({workspace:e.input.workspace,agent:e.agent,request:r,requestId:e.requestId,sessionId:e.sessionId,memory:a,pluginMemories:o,toolGateway:e.input.toolGateway,toolFailureTracker:e.input.toolFailureTracker,requestState:s,emit:e.emit}))}function routeMatches(e,t){if(e.pattern)try{if(new RegExp(e.pattern,"iu").test(t))return!0}catch{return!1}const r=t.toLowerCase();return(e.keywords??[]).some(e=>r.includes(e.toLowerCase()))}
@@ -1 +1 @@
1
- export function projectRuntimeTrace(e){return e.events.map(projectEvent).filter(isTraceEntry)}export function projectEvent(e){return"runtime.request.started"===e.type||"runtime.request.completed"===e.type||"runtime.request.failed"===e.type?base(e,"request",e.type):"runtime.request.cancelled"===e.type?base(e,"request",e.type,{reason:e.reason}):"runtime.execution.contract.failed"===e.type?base(e,"request",e.type,{reason:e.reason,missingEvidenceTools:e.missingEvidenceTools}):"runtime.inventory.repair"===e.type?base(e,"adapter","runtime.inventory.repair",{status:e.status,...e.diagnostic}):"runtime.tool.direct.started"===e.type?base(e,"tool","runtime.tool.direct.started",{toolId:e.toolId}):"runtime.tool.direct.completed"===e.type?base(e,"tool","runtime.tool.direct.completed",{toolId:e.toolId}):"runtime.tool.failure"===e.type?base(e,"tool","runtime.tool.failure",{toolId:e.toolId,...e.failure}):"runtime.tool.circuit.opened"===e.type?base(e,"tool","runtime.tool.circuit.opened",{toolId:e.toolId,reason:e.reason}):"runtime.workflow.started"===e.type||"runtime.workflow.completed"===e.type?base(e,"workflow",e.type,{workflowId:e.workflowId,adapter:e.adapter}):function isSpecDrivenPhaseEvent(e){return e.type.startsWith("runtime.specDriven.phase.")}(e)?base(e,"spec",e.type,{phaseId:e.phaseId,..."workflowId"in e&&e.workflowId?{workflowId:e.workflowId}:{},..."reason"in e?{reason:e.reason}:{},..."artifact"in e&&e.artifact?{artifact:e.artifact}:{}}):"runtime.adapter.event"===e.type?function adapterTrace(e){const t=e.event;if(isRecord(t)&&"string"==typeof t.phase){const r=function semanticAdapterTrace(e,t){if("inventory.repair"===t.phase)return base(e,"adapter","runtime.inventory.repair",{status:t.status,...isRecord(t.diagnostic)?t.diagnostic:{}});const r=function readTraceType(e){const t=readString(e);return"request"===t||"tool"===t||"workflow"===t||"spec"===t||"adapter"===t||"memory"===t||"artifact"===t||"progress"===t||"plan"===t||"delegation"===t?t:void 0}(t.traceType),o=readString(t.traceLabel);return r&&o?base(e,r,o,t):void 0}(e,t);return r||base(e,"adapter",t.phase.startsWith("agent.")?t.phase:`adapter.${t.phase}`,t)}return base(e,"adapter","runtime.adapter.event",{event:t})}(e):"runtime.artifact.created"===e.type?base(e,"artifact","runtime.artifact.created",{artifact:e.artifact}):e.type.startsWith("runtime.memory.")?base(e,"memory",e.type):"runtime.progress.narration"===e.type?base(e,"progress",e.type,{message:e.message,provider:e.provider,sourceEventTypes:e.sourceEventTypes}):void 0}export function readPlanTodos(e){const t=function readPlanRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e),r=function readTodosArray(e){const t=isRecord(e?.args)?e.args:void 0;return Array.isArray(e?.todos)?e.todos:Array.isArray(t?.todos)?t.todos:[]}(t);return r.map(readTodo).filter(isPlanTodoItem)}function readTodo(e){if(isRecord(e)&&"string"==typeof e.content)return{content:e.content,status:"string"==typeof e.status?e.status:"pending"}}function isPlanTodoItem(e){return void 0!==e}function base(e,t,r,o){return{type:t,label:r,agentId:e.agentId,requestId:e.requestId,detail:o}}function isTraceEntry(e){return void 0!==e}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}
1
+ export function projectRuntimeTrace(e){return e.events.map(projectEvent).filter(isTraceEntry)}export function projectEvent(e){return"runtime.request.started"===e.type||"runtime.request.completed"===e.type||"runtime.request.failed"===e.type?base(e,"request",e.type):"runtime.request.cancelled"===e.type?base(e,"request",e.type,{reason:e.reason}):"runtime.execution.contract.failed"===e.type?base(e,"request",e.type,{reason:e.reason,missingEvidenceTools:e.missingEvidenceTools}):"runtime.inventory.repair"===e.type?base(e,"adapter","runtime.inventory.repair",{status:e.status,...e.diagnostic}):"runtime.tool.direct.started"===e.type?base(e,"tool","runtime.tool.direct.started",{toolId:e.toolId}):"runtime.tool.direct.completed"===e.type?base(e,"tool","runtime.tool.direct.completed",{toolId:e.toolId}):"runtime.sandbox.decision"===e.type?base(e,"tool","runtime.sandbox.decision",{toolId:e.toolId,...e.decision}):"runtime.tool.failure"===e.type?base(e,"tool","runtime.tool.failure",{toolId:e.toolId,...e.failure}):"runtime.tool.circuit.opened"===e.type?base(e,"tool","runtime.tool.circuit.opened",{toolId:e.toolId,reason:e.reason}):"runtime.workflow.started"===e.type||"runtime.workflow.completed"===e.type?base(e,"workflow",e.type,{workflowId:e.workflowId,adapter:e.adapter}):function isSpecDrivenPhaseEvent(e){return e.type.startsWith("runtime.specDriven.phase.")}(e)?base(e,"spec",e.type,{phaseId:e.phaseId,..."workflowId"in e&&e.workflowId?{workflowId:e.workflowId}:{},..."reason"in e?{reason:e.reason}:{},..."artifact"in e&&e.artifact?{artifact:e.artifact}:{}}):"runtime.adapter.event"===e.type?function adapterTrace(e){const t=e.event;if(isRecord(t)&&"string"==typeof t.phase){const r=function semanticAdapterTrace(e,t){if("inventory.repair"===t.phase)return base(e,"adapter","runtime.inventory.repair",{status:t.status,...isRecord(t.diagnostic)?t.diagnostic:{}});const r=function readTraceType(e){const t=readString(e);return"request"===t||"tool"===t||"workflow"===t||"spec"===t||"adapter"===t||"memory"===t||"artifact"===t||"progress"===t||"plan"===t||"delegation"===t?t:void 0}(t.traceType),o=readString(t.traceLabel);return r&&o?base(e,r,o,t):void 0}(e,t);return r||base(e,"adapter",t.phase.startsWith("agent.")?t.phase:`adapter.${t.phase}`,t)}return base(e,"adapter","runtime.adapter.event",{event:t})}(e):"runtime.artifact.created"===e.type?base(e,"artifact","runtime.artifact.created",{artifact:e.artifact}):e.type.startsWith("runtime.memory.")?base(e,"memory",e.type):"runtime.progress.narration"===e.type?base(e,"progress",e.type,{message:e.message,provider:e.provider,sourceEventTypes:e.sourceEventTypes}):void 0}export function readPlanTodos(e){const t=function readPlanRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e),r=function readTodosArray(e){const t=isRecord(e?.args)?e.args:void 0;return Array.isArray(e?.todos)?e.todos:Array.isArray(t?.todos)?t.todos:[]}(t);return r.map(readTodo).filter(isPlanTodoItem)}function readTodo(e){if(isRecord(e)&&"string"==typeof e.content)return{content:e.content,status:"string"==typeof e.status?e.status:"pending"}}function isPlanTodoItem(e){return void 0!==e}function base(e,t,r,o){return{type:t,label:r,agentId:e.agentId,requestId:e.requestId,detail:o}}function isTraceEntry(e){return void 0!==e}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}
@@ -16,7 +16,7 @@ export type { CompiledWorkspace, WorkspaceAdapterPolicy, WorkspaceAgent, Workspa
16
16
  export type { WorkspaceToolQualityDiagnostic, WorkspaceToolQualityDiagnosticCode, WorkspaceToolQualityPolicy, } from "./workspace/tool-quality.js";
17
17
  export type { WorkspaceEvaluation, WorkspaceEvaluationCase, } from "./evaluations/index.js";
18
18
  export type { SpecDrivenPhaseId, SpecDrivenPhaseRecord, SpecDrivenPhaseStatus, SpecDrivenPhaseTransition, SpecDrivenWorkflowState, WorkspaceSpecDrivenPhase, WorkspaceSpecDrivenWorkflowPolicy, } from "./spec-driven/index.js";
19
- export type { RuntimeToolCallRequest, RuntimeToolGateway, RuntimeToolGatewayContext, RuntimeToolRepairModel, RuntimeToolGatewayTool, } from "./runtime/tool-gateway.js";
19
+ export type { RuntimeToolCallRequest, RuntimeToolGateway, RuntimeToolGatewayContext, RuntimeToolRepairModel, RuntimeToolGatewayTool, RuntimeSandboxDecision, RuntimeSandboxPolicy, RuntimeSandboxPolicyInput, } from "./runtime/tool-gateway.js";
20
20
  export type { RuntimeToolFailureClassification, RuntimeToolFailureKind, RuntimeToolFailurePolicy, RuntimeToolFailureReason, RuntimeToolFailureTracker, } from "./runtime/tool-failure.js";
21
21
  export type RuntimeAdapterContext = {
22
22
  workspace: CompiledWorkspace;
@@ -63,6 +63,7 @@ export type WorkspaceRuntimePolicy = {
63
63
  recovery?: Record<string, unknown>;
64
64
  retry?: WorkspaceRetryPolicy;
65
65
  toolGateway?: Record<string, unknown>;
66
+ sandbox?: Record<string, unknown>;
66
67
  memory?: Record<string, unknown>;
67
68
  protocols?: Record<string, unknown>;
68
69
  progress?: Record<string, unknown>;
@@ -6,6 +6,14 @@ export type ToolGatewayContext = {
6
6
  requestInput?: string;
7
7
  observedEvidence?: string;
8
8
  approvalIds?: string[];
9
+ sandbox?: ToolGatewaySandboxDecision;
10
+ };
11
+ export type ToolGatewaySandboxDecision = {
12
+ action: "allow" | "deny";
13
+ profile?: string;
14
+ reason?: string;
15
+ policyId?: string;
16
+ metadata?: Record<string, unknown>;
9
17
  };
10
18
  export type ToolGatewayTool = {
11
19
  id: string;