stable-harness 0.0.140 → 0.0.144
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -17
- package/dist/index.js +1 -1
- package/dist/runtime/skills/skill-metadata.js +1 -1
- package/dist/workspace/compile.js +1 -1
- package/docs/0.1.0-tool-guard-benchmark.zh.md +5 -5
- package/docs/architecture/system-architecture.zh.md +3 -3
- package/docs/evaluation/0.1.0-bfcl-targeted-model-matrix.zh.md +306 -306
- package/docs/evaluation/0.1.0-bfcl-targeted-review-matrix.zh.md +1 -1
- package/docs/evaluation/0.1.0-bfcl-tool-guard.zh.md +1 -1
- package/docs/granite-tool-calling-comparison.zh.md +8 -8
- package/docs/guides/getting-started.md +14 -6
- package/docs/guides/index.md +5 -3
- package/docs/guides/integration-guide.md +44 -43
- package/docs/guides/operator-runbook.md +51 -3
- package/docs/guides/runtime-governance-proof.md +4 -4
- package/docs/guides/workspace-authoring.md +2 -2
- package/docs/guides/workspace-docker-build.md +3 -3
- package/docs/memory/0.1.0-memory-design.zh.md +20 -0
- package/docs/memory/0.1.0-step-09-deepagents-native-memory.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-langmem-shaped-provider.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-memory-adapter-projection.zh.md +3 -3
- package/docs/memory/0.1.0-step-09-memory-contract.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-memory-governance-approval.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-memory-lifecycle-hooks.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-memory-maintenance-boundary.zh.md +1 -1
- package/docs/memory/0.1.0-step-09-memory-persistence-boundary.zh.md +1 -1
- package/docs/protocols/coverage-matrix.md +114 -0
- package/docs/protocols/http-runtime.md +31 -8
- package/docs/protocols/langgraph-compatible.md +75 -17
- package/docs/protocols/openai-compatible.md +25 -7
- package/docs/protocols/{agent-protocols.md → protocol-facades.md} +76 -18
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/adapter.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin/task-inventory.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-call-repair.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/dist/src/internal/gateway/tool-failure-events.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/raw-tool-call-parser.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/stream-events.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/substrate/checkpoint.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/tool-repeat-visibility.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/trace-projection.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/vfs-backend.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/package.json +2 -2
- package/node_modules/@stable-harness/adapter-langgraph/dist/src/graph.js +1 -1
- package/node_modules/@stable-harness/adapter-langgraph/dist/src/index.js +1 -1
- package/node_modules/@stable-harness/adapter-langgraph/dist/src/runtime.js +1 -1
- package/node_modules/@stable-harness/adapter-langgraph/dist/src/skill-providers.js +1 -1
- package/node_modules/@stable-harness/adapter-langgraph/dist/src/types.d.ts +1 -0
- package/node_modules/@stable-harness/adapter-langgraph/package.json +2 -2
- package/node_modules/@stable-harness/core/dist/boundary-scan.js +1 -1
- package/node_modules/@stable-harness/core/dist/index.d.ts +1 -0
- package/node_modules/@stable-harness/core/dist/index.js +1 -1
- package/node_modules/@stable-harness/core/dist/memory-plugins/shared.js +1 -1
- package/node_modules/@stable-harness/core/dist/memory-plugins.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/event-evidence.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/execution-review.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/synthesis/fields.js +1 -1
- package/node_modules/@stable-harness/core/dist/recovery/execution-contract.js +1 -1
- package/node_modules/@stable-harness/core/dist/recovery/tool-call-structure.js +1 -1
- package/node_modules/@stable-harness/core/dist/recovery/tool-call.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/direct-tool-call.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/inspection/methods.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/inspection/replay.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/persistence/artifacts.d.ts +4 -0
- package/node_modules/@stable-harness/core/dist/runtime/persistence/artifacts.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/persistence/queue.d.ts +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/persistence/queue.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/persistence/stores.d.ts +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/persistence/stores.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/persistence/system-data.d.ts +34 -0
- package/node_modules/@stable-harness/core/dist/runtime/persistence/system-data.js +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/recovery/adapter-result.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/recovery/non-focused-recovery.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime.js +1 -1
- package/node_modules/@stable-harness/core/dist/workflows/index.d.ts +20 -0
- package/node_modules/@stable-harness/core/dist/workflows/index.js +1 -1
- package/node_modules/@stable-harness/core/package.json +3 -3
- package/node_modules/@stable-harness/governance/dist/src/approval-queue.d.ts +1 -0
- package/node_modules/@stable-harness/governance/dist/src/approval-queue.js +1 -1
- package/node_modules/@stable-harness/governance/dist/src/index.d.ts +1 -1
- package/node_modules/@stable-harness/governance/dist/src/index.js +1 -1
- 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/http-events.d.ts +2 -0
- package/node_modules/@stable-harness/protocols/dist/src/http-events.js +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/http-server.d.ts +5 -1
- package/node_modules/@stable-harness/protocols/dist/src/http-server.js +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/index.d.ts +3 -3
- package/node_modules/@stable-harness/protocols/dist/src/index.js +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/openai-compatible.js +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/openai-payload.d.ts +89 -0
- package/node_modules/@stable-harness/protocols/dist/src/openai-payload.js +1 -1
- package/node_modules/@stable-harness/protocols/dist/src/{agent-protocols.d.ts → protocol-facades.d.ts} +4 -10
- package/node_modules/@stable-harness/protocols/dist/src/protocol-facades.js +1 -0
- package/node_modules/@stable-harness/protocols/dist/src/protocol-utils.d.ts +505 -0
- package/node_modules/@stable-harness/protocols/dist/src/protocol-utils.js +1 -0
- 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/dist/src/schema-validation.js +1 -1
- package/node_modules/@stable-harness/tool-gateway/package.json +1 -1
- package/node_modules/@stable-harness/workspace-yaml/dist/boundary-scan.js +1 -1
- package/node_modules/@stable-harness/workspace-yaml/dist/discovery.js +1 -1
- package/node_modules/@stable-harness/workspace-yaml/dist/documents.js +1 -1
- package/node_modules/@stable-harness/workspace-yaml/dist/loader.js +1 -1
- package/node_modules/@stable-harness/workspace-yaml/dist/workflows.js +1 -1
- package/node_modules/@stable-harness/workspace-yaml/package.json +2 -2
- package/package.json +12 -11
- package/packages/adapter-deepagents/dist/src/adapter.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/builtin/task-inventory.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/builtin-call-repair.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/builtin-tool-policy.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/gateway/tool-failure-events.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/raw-tool-call-parser.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/stream-events.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/substrate/checkpoint.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/tool-repeat-visibility.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/trace-projection.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/vfs-backend.js +1 -1
- package/packages/adapter-deepagents/package.json +2 -2
- package/packages/adapter-langgraph/dist/src/graph.js +1 -1
- package/packages/adapter-langgraph/dist/src/index.js +1 -1
- package/packages/adapter-langgraph/dist/src/runtime.js +1 -1
- package/packages/adapter-langgraph/dist/src/skill-providers.js +1 -1
- package/packages/adapter-langgraph/dist/src/types.d.ts +1 -0
- package/packages/adapter-langgraph/package.json +2 -2
- package/packages/cli/dist/src/args.d.ts +3 -2
- package/packages/cli/dist/src/args.js +1 -1
- package/packages/cli/dist/src/build.js +1 -1
- package/packages/cli/dist/src/cli.js +1 -1
- package/packages/cli/dist/src/console/session.js +1 -1
- package/packages/cli/dist/src/daemon/client.d.ts +4 -3
- package/packages/cli/dist/src/daemon/client.js +1 -1
- package/packages/cli/dist/src/init.js +1 -1
- package/packages/cli/dist/src/langgraph/agent-server-compat.d.ts +8 -0
- package/packages/cli/dist/src/langgraph/agent-server-compat.js +1 -0
- package/packages/cli/dist/src/langgraph/store-projection.d.ts +1 -0
- package/packages/cli/dist/src/langgraph/store-projection.js +1 -0
- package/packages/cli/dist/src/langgraph-official.js +1 -1
- package/packages/cli/dist/src/memory/providers.js +1 -1
- package/packages/cli/dist/src/server/gateway.d.ts +12 -0
- package/packages/cli/dist/src/server/gateway.js +1 -0
- package/packages/cli/dist/src/server/protocol-defaults.d.ts +7 -0
- package/packages/cli/dist/src/server/protocol-defaults.js +1 -0
- package/packages/cli/dist/src/server/studio.d.ts +1 -0
- package/packages/cli/dist/src/server/studio.js +1 -0
- package/packages/cli/dist/src/server.js +1 -1
- package/packages/cli/package.json +8 -8
- package/packages/core/dist/boundary-scan.js +1 -1
- package/packages/core/dist/index.d.ts +1 -0
- package/packages/core/dist/index.js +1 -1
- package/packages/core/dist/memory-plugins/shared.js +1 -1
- package/packages/core/dist/memory-plugins.js +1 -1
- package/packages/core/dist/quality/event-evidence.js +1 -1
- package/packages/core/dist/quality/execution-review.js +1 -1
- package/packages/core/dist/quality/synthesis/fields.js +1 -1
- package/packages/core/dist/recovery/execution-contract.js +1 -1
- package/packages/core/dist/recovery/tool-call-structure.js +1 -1
- package/packages/core/dist/recovery/tool-call.js +1 -1
- package/packages/core/dist/runtime/direct-tool-call.js +1 -1
- package/packages/core/dist/runtime/inspection/methods.js +1 -1
- package/packages/core/dist/runtime/inspection/replay.js +1 -1
- package/packages/core/dist/runtime/persistence/artifacts.d.ts +4 -0
- package/packages/core/dist/runtime/persistence/artifacts.js +1 -1
- package/packages/core/dist/runtime/persistence/queue.d.ts +1 -0
- package/packages/core/dist/runtime/persistence/queue.js +1 -1
- package/packages/core/dist/runtime/persistence/stores.d.ts +1 -0
- package/packages/core/dist/runtime/persistence/stores.js +1 -1
- package/packages/core/dist/runtime/persistence/system-data.d.ts +34 -0
- package/packages/core/dist/runtime/persistence/system-data.js +1 -0
- package/packages/core/dist/runtime/recovery/adapter-result.js +1 -1
- package/packages/core/dist/runtime/recovery/non-focused-recovery.js +1 -1
- package/packages/core/dist/runtime.js +1 -1
- package/packages/core/dist/workflows/index.d.ts +20 -0
- package/packages/core/dist/workflows/index.js +1 -1
- package/packages/core/package.json +3 -3
- package/packages/evaluation/dist/src/benchmark.js +1 -1
- package/packages/evaluation/dist/src/run-record.js +1 -1
- package/packages/evaluation/dist/src/tool-call-metrics.js +1 -1
- package/packages/evaluation/package.json +2 -2
- package/packages/governance/dist/src/approval-queue.d.ts +1 -0
- package/packages/governance/dist/src/approval-queue.js +1 -1
- package/packages/governance/dist/src/index.d.ts +1 -1
- package/packages/governance/dist/src/index.js +1 -1
- package/packages/governance/package.json +1 -1
- package/packages/memory/package.json +1 -1
- package/packages/protocols/dist/src/http-events.d.ts +2 -0
- package/packages/protocols/dist/src/http-events.js +1 -1
- package/packages/protocols/dist/src/http-server.d.ts +5 -1
- package/packages/protocols/dist/src/http-server.js +1 -1
- package/packages/protocols/dist/src/index.d.ts +3 -3
- package/packages/protocols/dist/src/index.js +1 -1
- package/packages/protocols/dist/src/openai-compatible.js +1 -1
- package/packages/protocols/dist/src/openai-payload.d.ts +89 -0
- package/packages/protocols/dist/src/openai-payload.js +1 -1
- package/packages/protocols/dist/src/{agent-protocols.d.ts → protocol-facades.d.ts} +4 -10
- package/packages/protocols/dist/src/protocol-facades.js +1 -0
- package/packages/protocols/dist/src/protocol-utils.d.ts +505 -0
- package/packages/protocols/dist/src/protocol-utils.js +1 -0
- package/packages/protocols/package.json +2 -2
- package/packages/tool-gateway/dist/src/argument-guard.js +1 -1
- package/packages/tool-gateway/dist/src/schema-validation.js +1 -1
- package/packages/tool-gateway/package.json +1 -1
- package/packages/workspace-yaml/dist/boundary-scan.js +1 -1
- package/packages/workspace-yaml/dist/discovery.js +1 -1
- package/packages/workspace-yaml/dist/documents.js +1 -1
- package/packages/workspace-yaml/dist/loader.js +1 -1
- package/packages/workspace-yaml/dist/workflows.js +1 -1
- package/packages/workspace-yaml/package.json +2 -2
- package/node_modules/@stable-harness/protocols/dist/src/agent-protocols.js +0 -1
- package/packages/protocols/dist/src/agent-protocols.js +0 -1
|
@@ -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),i=new Set(t(r)),s=new Set;for(const e of n)collectReadyTargets(e,o,i,s,new Set([e]));const c=new Set(s),a=new Set([...i,...s]);for(const e of n){if(i.has(e)||s.has(e))continue;const t=(o.get(e)??[]).filter(e=>!i.has(e));t.length>0&&t.every(e=>a.has(e))&&c.add(e)}return[...c].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 i=(t.get(e)??[]).filter(e=>!n.has(e));if(0!==i.length)for(const e of i)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
|
-
export function hasStructuredToolEnvelope(t){const e=function extractJsonSource(t){const e=t.trim();if(e.startsWith("{")&&e.endsWith("}")||e.startsWith("[")&&e.endsWith("]"))return e;const n=function extractSingleFence(t){const e=t.indexOf("```");if(e<0||t.indexOf("```",e+3)!==t.lastIndexOf("```"))return;const n=t.indexOf("\n",e+3),r=t.lastIndexOf("```");return n<0||r<=n?void 0:t.slice(n+1,r).trim()}(e);return n&&(n.startsWith("{")&&n.endsWith("}")||n.startsWith("[")&&n.endsWith("]"))?n:void 0}(t);if(!e)return!1;try{const t=JSON.parse(e);return Array.isArray(t)?t.some(isToolEnvelopeRecord):isToolEnvelopeRecord(t)}catch{return!1}}export function hasXmlLikeToolMarkup(t){const e=t.trim().toLowerCase();return e.includes("<tool_call")||e.includes("</tool_call")||e.includes("<tool_code")||e.includes("</tool_code")||e.includes("<task")||e.includes("</task")}export function isFunctionStyleCall(t){const e=t.trim(),n=e.indexOf("(");return!(n<=0||!e.endsWith(")")||e.length>2500)&&function isIdentifierPath(t){return t.length>0&&[...t].every((t,e)=>{const n=t>="A"&&t<="Z"||t>="a"&&t<="z"||"_"===t;return 0===e?n:n||t>="0"&&t<="9"||"."===t||"-"===t})}(e.slice(0,n).trim())&&function balancedParens(t){let e,n=0;for(let r=0;r<t.length;r+=1){const o=t[r],s=t[r-1];if(e)o===e&&"\\"!==s&&(e=void 0);else if('"'===o||"'"===o)e=o;else if("("===o)n+=1;else if(")"===o&&(n-=1,n<0))return!1}return 0===n&&!e}(e.slice(n))}function isToolEnvelopeRecord(t){return!!isRecord(t)&&(isRecord(t.task)?"string"==typeof t.task.subagent_type||"string"==typeof t.task.task:["tool","toolId","toolName","tool_name","name","type","subagent_type"].some(e=>"string"==typeof t[e])&&["args","arguments","parameters","params","kwargs","task"].some(e=>e in t))}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}
|
|
1
|
+
export function hasStructuredToolEnvelope(t){const e=function extractJsonSource(t){const e=t.trim();if(e.startsWith("{")&&e.endsWith("}")||e.startsWith("[")&&e.endsWith("]"))return e;const n=function extractSingleFence(t){const e=t.indexOf("```");if(e<0||t.indexOf("```",e+3)!==t.lastIndexOf("```"))return;const n=t.indexOf("\n",e+3),r=t.lastIndexOf("```");return n<0||r<=n?void 0:t.slice(n+1,r).trim()}(e);return n&&(n.startsWith("{")&&n.endsWith("}")||n.startsWith("[")&&n.endsWith("]"))?n:void 0}(t);if(!e)return!1;try{const t=JSON.parse(e);return Array.isArray(t)?t.some(isToolEnvelopeRecord):isToolEnvelopeRecord(t)}catch{return!1}}export function hasXmlLikeToolMarkup(t){const e=t.trim().toLowerCase();return e.includes("<tool_call")||e.includes("</tool_call")||e.includes("<tool_code")||e.includes("</tool_code")||e.includes("<task")||e.includes("</task")}export function isFunctionStyleCall(t){const e=t.trim(),n=e.indexOf("(");return!(n<=0||!e.endsWith(")")||e.length>2500)&&(function isIdentifierPath(t){return t.length>0&&[...t].every((t,e)=>{const n=t>="A"&&t<="Z"||t>="a"&&t<="z"||"_"===t;return 0===e?n:n||t>="0"&&t<="9"||"."===t||"-"===t})}(e.slice(0,n).trim())&&function balancedParens(t){let e,n=0;for(let r=0;r<t.length;r+=1){const o=t[r],s=t[r-1];if(e)o===e&&"\\"!==s&&(e=void 0);else if('"'===o||"'"===o)e=o;else if("("===o)n+=1;else if(")"===o&&(n-=1,n<0))return!1}return 0===n&&!e}(e.slice(n)))}function isToolEnvelopeRecord(t){return!!isRecord(t)&&(isRecord(t.task)?"string"==typeof t.task.subagent_type||"string"==typeof t.task.task:["tool","toolId","toolName","tool_name","name","type","subagent_type"].some(e=>"string"==typeof t[e])&&["args","arguments","parameters","params","kwargs","task"].some(e=>e in t))}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}
|
|
@@ -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)|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
|
+
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 i,hasXmlLikeToolMarkup as l,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 i="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 i?recoverRequest(e.request,["Stable runtime recovery: a previous adapter event matched a configured recovery hint.",i.output,i.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){const o=readToolCallRecovery(t);return!0===o.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",i=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,i):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,i)}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)&&!!(i(e)||l(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 +1 @@
|
|
|
1
|
-
import{evaluateToolGuardrails as t}from"./policy/tool-invocation.js";import{toolCircuitOpenEvent as o,toolFailureEvent as e}from"./tool-failure.js";export async function runDirectToolCall(o){const e=o.request.toolCall;if(!e)throw new Error("Direct tool call request is missing");if(!o.gateway)throw new Error("Runtime tool gateway is not configured");const r=await async function resolveDirectToolCall(t){if(t.agent.tools.includes(t.toolId)&&t.gateway.get(t.toolId))return{toolId:t.toolId,args:t.args};const o=await(t.gateway.repairToolCall?.({toolId:t.toolId,args:t.args,allowedToolIds:t.agent.tools,context:{workspaceRoot:t.workspace.root,requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,requestInput:t.request.input,approvalIds:readApprovalIds(t.request.metadata)}}));if(o&&t.agent.tools.includes(o.toolId)&&t.gateway.get(o.toolId))return emitToolRepair(t,"repaired",o.toolId),o;if(!t.agent.tools.includes(t.toolId))throw emitToolRepair(t,"blocked",void 0,`Tool ${t.toolId} is not assigned to agent ${t.agent.id}`),new Error(`Tool ${t.toolId} is not assigned to agent ${t.agent.id}`);throw emitToolRepair(t,"blocked",void 0,`Tool is not registered: ${t.toolId}`),new Error(`Tool is not registered: ${t.toolId}`)}({gateway:o.gateway,workspace:o.workspace,requestId:o.requestId,sessionId:o.sessionId,agent:o.agent,emit:o.emit,request:o.request,toolId:e.toolId,args:e.args});o.emit({type:"runtime.tool.direct.started",requestId:o.requestId,sessionId:o.sessionId,agentId:o.agent.id,toolId:r.toolId});const s=t({agent:o.agent,args:r.args,events:o.events??[],toolId:r.toolId},o.toolGuardrails);if(s)return o.emit({type:"runtime.tool.direct.completed",requestId:o.requestId,sessionId:o.sessionId,agentId:o.agent.id,toolId:r.toolId,output:s.eventOutput}),{text:s.modelOutput,metadata:{toolCall:{toolId:r.toolId},controlStatus:s.status}};if(o.toolFailureTracker?.isCircuitOpen(r.toolId)){const t=new Error(`Tool circuit is open: ${r.toolId}`);throw emitToolFailure(o,r.toolId,t),t}const
|
|
1
|
+
import{evaluateToolGuardrails as t}from"./policy/tool-invocation.js";import{toolCircuitOpenEvent as o,toolFailureEvent as e}from"./tool-failure.js";export async function runDirectToolCall(o){const e=o.request.toolCall;if(!e)throw new Error("Direct tool call request is missing");if(!o.gateway)throw new Error("Runtime tool gateway is not configured");const r=await async function resolveDirectToolCall(t){if(t.agent.tools.includes(t.toolId)&&t.gateway.get(t.toolId))return{toolId:t.toolId,args:t.args};const o=await(t.gateway.repairToolCall?.({toolId:t.toolId,args:t.args,allowedToolIds:t.agent.tools,context:{workspaceRoot:t.workspace.root,requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,requestInput:t.request.input,approvalIds:readApprovalIds(t.request.metadata)}}));if(o&&t.agent.tools.includes(o.toolId)&&t.gateway.get(o.toolId))return emitToolRepair(t,"repaired",o.toolId),o;if(!t.agent.tools.includes(t.toolId))throw emitToolRepair(t,"blocked",void 0,`Tool ${t.toolId} is not assigned to agent ${t.agent.id}`),new Error(`Tool ${t.toolId} is not assigned to agent ${t.agent.id}`);throw emitToolRepair(t,"blocked",void 0,`Tool is not registered: ${t.toolId}`),new Error(`Tool is not registered: ${t.toolId}`)}({gateway:o.gateway,workspace:o.workspace,requestId:o.requestId,sessionId:o.sessionId,agent:o.agent,emit:o.emit,request:o.request,toolId:e.toolId,args:e.args});o.emit({type:"runtime.tool.direct.started",requestId:o.requestId,sessionId:o.sessionId,agentId:o.agent.id,toolId:r.toolId});const s=t({agent:o.agent,args:r.args,events:o.events??[],toolId:r.toolId},o.toolGuardrails);if(s)return o.emit({type:"runtime.tool.direct.completed",requestId:o.requestId,sessionId:o.sessionId,agentId:o.agent.id,toolId:r.toolId,output:s.eventOutput}),{text:s.modelOutput,metadata:{toolCall:{toolId:r.toolId},controlStatus:s.status}};if(o.toolFailureTracker?.isCircuitOpen(r.toolId)){const t=new Error(`Tool circuit is open: ${r.toolId}`);throw emitToolFailure(o,r.toolId,t),t}const i=await async function invokeToolWithFailureEvents(t,o){try{return await t.gateway.invoke({toolId:o.toolId,args:o.args,context:{workspaceRoot:t.workspace.root,requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,requestInput:t.request.input,approvalIds:readApprovalIds(t.request.metadata)}})}catch(e){throw emitToolFailure(t,o.toolId,e),e}}(o,r);return o.toolFailureTracker?.recordSuccess(i.toolId),o.emit({type:"runtime.tool.direct.completed",requestId:o.requestId,sessionId:o.sessionId,agentId:o.agent.id,toolId:i.toolId,output:i.output}),{text:stringifyToolOutput(i.output),metadata:{toolCall:{toolId:i.toolId}}}}function emitToolFailure(t,r,s){const i=e({requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,toolId:r,error:s});t.emit(i),t.toolFailureTracker?.recordFailure(r)&&t.emit(o({requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,toolId:r,reason:"runtime.tool.failure"===i.type?i.failure.reason:"unknown"}))}function emitToolRepair(t,o,e,r){t.emit({type:"runtime.inventory.repair",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,status:o,diagnostic:{layer:"tool",owner:"stable_runtime_policy",originalId:t.toolId,repairedId:e,candidateIds:t.agent.tools,reason:r}})}function stringifyToolOutput(t){if("string"==typeof t)return t;const o=JSON.stringify(t);return"string"==typeof o?o:""}function readApprovalIds(t){const o=t?.approvalIds??t?.approvalId;return"string"==typeof o&&o.trim()?[o.trim()]:Array.isArray(o)?o.filter(t=>"string"==typeof t&&t.trim().length>0):void 0}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{projectRequestInspection as t,projectRequestSummary as
|
|
1
|
+
import{projectRequestInspection as t,projectRequestSummary as s,projectSessionSummaries as e}from"../persistence/inspection.js";import{getRuntimeArtifact as r,importRuntimeArtifact as o,listRuntimeArtifacts as a,readRuntimeArtifact as i}from"./artifacts.js";import{exportRuntimeReplayBundle as n}from"./replay.js";export function createRuntimeInspectionMethods(p){return{inspect:()=>{return{workspaceRoot:p.workspace.root,agents:[...p.workspace.agents.keys()].sort(),workflows:[...p.workspace.workflows.keys()].sort(),...p.workspace.runtime.specDrivenWorkflow?{specDrivenWorkflow:(t=p.workspace.runtime.specDrivenWorkflow,{enabled:t.enabled,artifactsDir:t.artifactsDir,...t.constitution?{constitution:t.constitution}:{},phases:t.phases.map(t=>t.id)})}:{},evaluations:[...p.workspace.evaluations?.keys()??[]].sort(),...p.workspace.runtime.workflowRouting?.defaultWorkflowId?{defaultWorkflowId:p.workspace.runtime.workflowRouting.defaultWorkflowId}:{},workflowRoutes:(p.workspace.runtime.workflowRouting?.routes??[]).map(t=>t.id).sort(),models:[...p.workspace.models.keys()].sort(),tools:[...p.workspace.tools.keys()].sort(),runs:p.store.listRuns()};var t},getRuntimePolicy:()=>p.workspace.runtime,getWorkflow:t=>p.workspace.workflows.get(t),getRun:t=>p.store.getRun(t),listArtifacts:t=>a({store:p.store,artifacts:p.artifacts,filter:t}),getArtifact:t=>r({store:p.store,artifacts:p.artifacts,id:t}),readArtifact:t=>i({artifacts:p.artifacts,id:t}),importArtifact:t=>o({store:p.store,artifacts:p.artifacts,emit:p.emit,artifact:t}),exportReplayBundle:t=>n({store:p.store,artifacts:p.artifacts,requestId:t}),listRequests:t=>p.store.listRuns(t).map(s),listSessions:()=>e(p.store.listRuns()),inspectRequest:s=>{const e=p.store.getRun(s);return e?t(p.workspace,e):void 0},listApprovals:t=>p.approvals?.list(t)??Promise.resolve([]),getApproval:t=>p.approvals?.get(t)??Promise.resolve(void 0),resolveApproval:async(t,s)=>{const e=await(p.approvals?.resolve(t,s));return e&&p.emit({type:"runtime.approval.resolved",requestId:e.requestId??"",sessionId:e.sessionId??"",agentId:e.agentId??"",approval:e}),e}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash as t}from"node:crypto";import{listRuntimeArtifacts as e}from"./artifacts.js";export function exportRuntimeReplayBundle(t){const s=t.store.getRun(t.requestId);if(!s)return;const r=e({store:t.store,artifacts:t.artifacts,filter:{requestId:t.requestId}}),
|
|
1
|
+
import{createHash as t}from"node:crypto";import{listRuntimeArtifacts as e}from"./artifacts.js";export function exportRuntimeReplayBundle(t){const s=t.store.getRun(t.requestId);if(!s)return;const r=e({store:t.store,artifacts:t.artifacts,filter:{requestId:t.requestId}}),n={schemaVersion:1,kind:"stable-harness.replay-bundle",requestId:s.requestId,sessionId:s.sessionId,agentId:s.agentId,createdAt:s.completedAt??s.startedAt,run:s,events:s.events,artifacts:r};return{...n,integrity:{algorithm:"sha256",runHash:digest(s),eventsHash:digest(s.events),artifactsHash:digest(r),bundleHash:digest(n)}}}function digest(e){return t("sha256").update(function stableJson(t){return JSON.stringify(sortValue(t))}(e)).digest("hex")}function sortValue(t){return Array.isArray(t)?t.map(sortValue):t&&"object"==typeof t?Object.fromEntries(Object.entries(t).sort(([t],[e])=>t.localeCompare(e)).map(([t,e])=>[t,sortValue(e)])):t}
|
|
@@ -4,5 +4,9 @@ type ArtifactState = {
|
|
|
4
4
|
contents: Record<string, unknown>;
|
|
5
5
|
};
|
|
6
6
|
export declare function createInMemoryArtifactStore(initial?: ArtifactState): RuntimeArtifactStore;
|
|
7
|
+
export declare function createSqliteFileArtifactStore(input: {
|
|
8
|
+
dbPath: string;
|
|
9
|
+
artifactsDir: string;
|
|
10
|
+
}): RuntimeArtifactStore;
|
|
7
11
|
export declare function createJsonFileArtifactStore(filePath: string): RuntimeArtifactStore;
|
|
8
12
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as
|
|
1
|
+
import{createHash as t}from"node:crypto";import{existsSync as e,mkdirSync as r,readFileSync as n,writeFileSync as i}from"node:fs";import a from"node:path";import{DatabaseSync as s}from"node:sqlite";export function createInMemoryArtifactStore(t){const e=new Map((t?.records??[]).map(t=>[t.id,cloneRecord(t)])),r=new Map(Object.entries(t?.contents??{}).map(([t,e])=>[t,structuredClone(e)]));return{createArtifact(t){const n=toRecord(t);return e.set(n.id,n),r.set(n.id,structuredClone(t.content??null)),cloneRecord(n)},listArtifacts:t=>[...e.values()].filter(e=>function matchesFilter(t,e){return!e||!(e.requestId&&e.requestId!==t.requestId||e.sessionId&&e.sessionId!==t.sessionId||e.agentId&&e.agentId!==t.agentId)}(e,t)).map(cloneRecord),readArtifact(t){if(!r.has(t))throw new Error(`Artifact not found: ${t}`);return structuredClone(r.get(t))}}}export function createSqliteFileArtifactStore(e){const o=function openArtifactDatabase(t){const e=a.resolve(t);r(a.dirname(e),{recursive:!0});const n=new s(e);return n.exec("PRAGMA busy_timeout = 5000"),n.exec("PRAGMA journal_mode = WAL"),n.exec("PRAGMA synchronous = NORMAL"),n.exec(["CREATE TABLE IF NOT EXISTS runtime_artifacts (id TEXT PRIMARY KEY, kind TEXT NOT NULL, uri TEXT, metadata_json TEXT, request_id TEXT NOT NULL, session_id TEXT NOT NULL, agent_id TEXT NOT NULL, content_type TEXT, size INTEGER, created_at TEXT NOT NULL, content_path TEXT NOT NULL)","CREATE INDEX IF NOT EXISTS idx_runtime_artifacts_request ON runtime_artifacts(request_id)","CREATE INDEX IF NOT EXISTS idx_runtime_artifacts_session ON runtime_artifacts(session_id)","CREATE INDEX IF NOT EXISTS idx_runtime_artifacts_agent ON runtime_artifacts(agent_id)"].join(";")),n}(e.dbPath),c=a.resolve(e.artifactsDir);return{createArtifact(e){const n=toRecord(e),s=function writeArtifactContent(e,n,s){r(e,{recursive:!0});const o=a.join(e,`${function safeArtifactFileName(e){return t("sha256").update(e).digest("hex")}(n)}.json`);return i(o,`${JSON.stringify(s,null,2)}\n`),o}(c,n.id,e.content??null);return o.prepare(["INSERT OR REPLACE INTO runtime_artifacts","(id, kind, uri, metadata_json, request_id, session_id, agent_id, content_type, size, created_at, content_path)","VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"].join(" ")).run(n.id,n.kind,n.uri??null,JSON.stringify(n.metadata??null),n.requestId,n.sessionId,n.agentId,n.contentType??null,n.size??null,n.createdAt,s),cloneRecord(n)},listArtifacts:t=>function readArtifactRows(t,e){const r=[],n=[];e?.requestId&&addArtifactClause(r,n,"request_id",e.requestId),e?.sessionId&&addArtifactClause(r,n,"session_id",e.sessionId),e?.agentId&&addArtifactClause(r,n,"agent_id",e.agentId);const i=r.length?` WHERE ${r.join(" AND ")}`:"";return t.prepare(`SELECT * FROM runtime_artifacts${i} ORDER BY created_at ASC`).all(...n).map(toArtifactRecord)}(o,t).map(({contentPath:t,...e})=>cloneRecord(e)),readArtifact(t){const e=o.prepare("SELECT content_path AS contentPath FROM runtime_artifacts WHERE id = ?").get(t);if(!e)throw new Error(`Artifact not found: ${t}`);return JSON.parse(n(e.contentPath,"utf8"))}}}export function createJsonFileArtifactStore(t){const s=a.resolve(t),o=createInMemoryArtifactStore(function readArtifactFile(t){if(!e(t))return{records:[],contents:{}};const r=JSON.parse(n(t,"utf8"));if(!function isState(t){return"object"==typeof t&&null!==t&&Array.isArray(t.records)&&"object"==typeof t.contents}(r))throw new Error(`Invalid artifact store file: ${t}`);return r}(s));return{createArtifact(t){const e=o.createArtifact(t);return function writeArtifactFile(t,e){r(a.dirname(t),{recursive:!0}),i(t,`${JSON.stringify({version:1,...e},null,2)}\n`)}(s,function snapshot(t){const e=t.listArtifacts(),r=Object.fromEntries(e.map(e=>[e.id,t.readArtifact(e.id)]));return{records:e,contents:r}}(o)),e},listArtifacts:t=>o.listArtifacts(t),readArtifact:t=>o.readArtifact(t)}}function toArtifactRecord(t){const e=t.metadata_json?JSON.parse(t.metadata_json):null;return{id:t.id,kind:t.kind,...t.uri?{uri:t.uri}:{},...e?{metadata:e}:{},requestId:t.request_id,sessionId:t.session_id,agentId:t.agent_id,...t.content_type?{contentType:t.content_type}:{},..."number"==typeof t.size?{size:t.size}:{},createdAt:t.created_at,contentPath:t.content_path}}function addArtifactClause(t,e,r,n){t.push(`${r} = ?`),e.push(n)}function toRecord(t){return{id:t.id,kind:t.kind,uri:t.uri,metadata:t.metadata,requestId:t.requestId,sessionId:t.sessionId,agentId:t.agentId,contentType:t.contentType,createdAt:t.createdAt??(new Date).toISOString(),size:(e=t.content,Buffer.byteLength(JSON.stringify(e??null),"utf8"))};var e}function cloneRecord(t){return structuredClone(t)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function createInMemoryRuntimeQueueStore(){const e=new Map,t=new Map,r=new Map;return{enqueue(t){const r=t.enqueuedAt??(new Date).toISOString(),n=cloneQueueRecord({...t,enqueuedAt:r,attemptCount:t.attemptCount??0});return e.set(n.requestId,n),cloneQueueRecord(n)},listQueue:()=>sortQueue([...e.values()]).map(cloneQueueRecord),getQueuedRequest:t=>cloneOptional(e.get(t),cloneQueueRecord),claimNext(r){const n=
|
|
1
|
+
import{mkdirSync as e}from"node:fs";import t from"node:path";import{DatabaseSync as r}from"node:sqlite";export function createInMemoryRuntimeQueueStore(){const e=new Map,t=new Map,r=new Map;return{enqueue(t){const r=t.enqueuedAt??(new Date).toISOString(),n=cloneQueueRecord({...t,enqueuedAt:r,attemptCount:t.attemptCount??0});return e.set(n.requestId,n),cloneQueueRecord(n)},listQueue:()=>sortQueue([...e.values()]).map(cloneQueueRecord),getQueuedRequest:t=>cloneOptional(e.get(t),cloneQueueRecord),claimNext(r){const n=findClaimCandidate([...e.values()],r);if(!n)return;const o=r.now??(new Date).toISOString(),u=claimRecord(n,r.workerId,o,r.leaseMs);return e.set(u.requestId,u),t.set(u.requestId,{requestId:u.requestId,cancelRequested:t.get(u.requestId)?.cancelRequested??!1,workerId:r.workerId,workerStartedAt:t.get(u.requestId)?.workerStartedAt??o,heartbeatAt:o}),cloneQueueRecord(u)},heartbeat(e){const r=t.get(e.requestId);if(!r||r.workerId!==e.workerId)return;const n={...r,heartbeatAt:e.now??(new Date).toISOString()};return t.set(e.requestId,n),cloneControl(n)},requestCancel(e){const r={...t.get(e.requestId),requestId:e.requestId,cancelRequested:!0,cancelReason:e.reason,cancelRequestedAt:e.now??(new Date).toISOString()};return t.set(e.requestId,r),cloneControl(r)},getControl:e=>cloneOptional(t.get(e),cloneControl),listStuck(r){const n=Date.parse(r.now??(new Date).toISOString());return[...e.values()].filter(e=>isStuck(e,t.get(e.requestId),n,r.staleAfterMs)).map(cloneQueueRecord)},saveRecoveryIntent:e=>(r.set(e.requestId,cloneRecovery(e)),cloneRecovery(e)),getRecoveryIntent:e=>cloneOptional(r.get(e),cloneRecovery),clearRecoveryIntent:e=>r.delete(e)}}export function createSqliteRuntimeQueueStore(n){const o=function openQueueDatabase(n){const o=t.resolve(n);e(t.dirname(o),{recursive:!0});const u=new r(o);return u.exec("PRAGMA busy_timeout = 5000; PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL"),u.exec(["CREATE TABLE IF NOT EXISTS runtime_queue (request_id TEXT PRIMARY KEY, record_json TEXT NOT NULL)","CREATE TABLE IF NOT EXISTS runtime_controls (request_id TEXT PRIMARY KEY, control_json TEXT NOT NULL)","CREATE TABLE IF NOT EXISTS runtime_recovery_intents (request_id TEXT PRIMARY KEY, intent_json TEXT NOT NULL)"].join(";")),u}(n);return{enqueue(e){const t=cloneQueueRecord({...e,enqueuedAt:e.enqueuedAt??(new Date).toISOString(),attemptCount:e.attemptCount??0});return upsertQueue(o,t),cloneQueueRecord(t)},listQueue:()=>sortQueue(readQueue(o)).map(cloneQueueRecord),getQueuedRequest:e=>cloneOptional(function readQueuedRequest(e,t){const r=e.prepare("SELECT record_json AS recordJson FROM runtime_queue WHERE request_id = ?").get(t);return r?JSON.parse(r.recordJson):void 0}(o,e),cloneQueueRecord),claimNext(e){const t=findClaimCandidate(readQueue(o),e);if(!t)return;const r=e.now??(new Date).toISOString(),n=claimRecord(t,e.workerId,r,e.leaseMs);return upsertQueue(o,n),upsertControl(o,{requestId:n.requestId,cancelRequested:readControl(o,n.requestId)?.cancelRequested??!1,workerId:e.workerId,workerStartedAt:readControl(o,n.requestId)?.workerStartedAt??r,heartbeatAt:r}),cloneQueueRecord(n)},heartbeat(e){const t=readControl(o,e.requestId);if(!t||t.workerId!==e.workerId)return;const r={...t,heartbeatAt:e.now??(new Date).toISOString()};return upsertControl(o,r),cloneControl(r)},requestCancel(e){const t={...readControl(o,e.requestId),requestId:e.requestId,cancelRequested:!0,cancelReason:e.reason,cancelRequestedAt:e.now??(new Date).toISOString()};return upsertControl(o,t),cloneControl(t)},getControl:e=>cloneOptional(readControl(o,e),cloneControl),listStuck(e){const t=Date.parse(e.now??(new Date).toISOString());return readQueue(o).filter(r=>isStuck(r,readControl(o,r.requestId),t,e.staleAfterMs)).map(cloneQueueRecord)},saveRecoveryIntent:e=>(o.prepare("INSERT OR REPLACE INTO runtime_recovery_intents(request_id, intent_json) VALUES (?, ?)").run(e.requestId,JSON.stringify(e)),cloneRecovery(e)),getRecoveryIntent(e){const t=o.prepare("SELECT intent_json AS intentJson FROM runtime_recovery_intents WHERE request_id = ?").get(e);return t?cloneRecovery(JSON.parse(t.intentJson)):void 0},clearRecoveryIntent:e=>o.prepare("DELETE FROM runtime_recovery_intents WHERE request_id = ?").run(e).changes>0}}function upsertQueue(e,t){e.prepare("INSERT OR REPLACE INTO runtime_queue(request_id, record_json) VALUES (?, ?)").run(t.requestId,JSON.stringify(t))}function upsertControl(e,t){e.prepare("INSERT OR REPLACE INTO runtime_controls(request_id, control_json) VALUES (?, ?)").run(t.requestId,JSON.stringify(t))}function readQueue(e){return e.prepare("SELECT record_json AS recordJson FROM runtime_queue").all().map(e=>JSON.parse(e.recordJson))}function readControl(e,t){const r=e.prepare("SELECT control_json AS controlJson FROM runtime_controls WHERE request_id = ?").get(t);return r?JSON.parse(r.controlJson):void 0}function findClaimCandidate(e,t){const r=Date.parse(t.now??(new Date).toISOString());return sortQueue(e).find(e=>{const n=Date.parse(e.availableAt)<=r,o=!t.queueKey||e.queueKey===t.queueKey,u=!e.leaseExpiresAt||Date.parse(e.leaseExpiresAt)<=r;return n&&o&&u})}function claimRecord(e,t,r,n){return{...e,claimedBy:t,claimedAt:r,leaseExpiresAt:new Date(Date.parse(r)+n).toISOString(),attemptCount:e.attemptCount+1}}function sortQueue(e){return[...e].sort((e,t)=>{const r=t.priority-e.priority;return 0===r?e.enqueuedAt.localeCompare(t.enqueuedAt):r})}function isStuck(e,t,r,n){if(!e.claimedAt)return!1;const o=Date.parse(t?.heartbeatAt??e.claimedAt);return!!e.leaseExpiresAt&&Date.parse(e.leaseExpiresAt)<r||r-o>n}function cloneOptional(e,t){return e?t(e):void 0}function cloneQueueRecord(e){return structuredClone(e)}function cloneControl(e){return structuredClone(e)}function cloneRecovery(e){return structuredClone(e)}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { RuntimeRunRecord, RuntimeStore } from "../types.js";
|
|
2
2
|
export declare function createInMemoryRuntimeStore(initialRuns?: RuntimeRunRecord[]): RuntimeStore;
|
|
3
|
+
export declare function createSqliteRuntimeStore(filePath: string): RuntimeStore;
|
|
3
4
|
export declare function createJsonFileRuntimeStore(filePath: string): RuntimeStore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as e,mkdirSync as
|
|
1
|
+
import{existsSync as e,mkdirSync as n,readFileSync as t,writeFileSync as r}from"node:fs";import s from"node:path";import{DatabaseSync as u}from"node:sqlite";export function createInMemoryRuntimeStore(e=[]){const n=new Map(e.map(e=>[e.requestId,cloneRun(e)]));return{createRun(e){n.set(e.requestId,cloneRun(e))},updateRun(e,t){const r=n.get(e);if(r)return Object.assign(r,clonePatch(t)),cloneRun(r)},appendEvent(e){const t=n.get(e.requestId);if(!t)return;const r=eventArtifact(e);return r&&!t.artifacts.some(e=>e.id===r.id)&&t.artifacts.push(structuredClone(r)),t.events.push(cloneEvent(e)),cloneRun(t)},getRun:e=>cloneOptionalRun(n.get(e)),listRuns:e=>[...n.values()].filter(n=>function matchesFilter(e,n){return!n||!(n.agentId&&n.agentId!==e.agentId||n.sessionId&&n.sessionId!==e.sessionId||n.state&&n.state!==e.state)}(n,e)).map(cloneRun),deleteRun(e){const t=n.get(e);if(t)return n.delete(e),cloneRun(t)},deleteSession(e){const t=[...n.values()].filter(n=>n.sessionId===e).map(e=>e.requestId);for(const e of t)n.delete(e);return{deletedRequestIds:t,deletedCount:t.length}}}}export function createSqliteRuntimeStore(e){const t=function openRuntimeStoreDatabase(e){const t=s.resolve(e);n(s.dirname(t),{recursive:!0});const r=new u(t);return r.exec("PRAGMA busy_timeout = 5000"),r.exec("PRAGMA journal_mode = WAL"),r.exec("PRAGMA synchronous = NORMAL"),r.exec(["CREATE TABLE IF NOT EXISTS runtime_runs (request_id TEXT PRIMARY KEY, session_id TEXT NOT NULL, agent_id TEXT NOT NULL, state TEXT NOT NULL, started_at TEXT NOT NULL, completed_at TEXT, run_json TEXT NOT NULL)","CREATE INDEX IF NOT EXISTS idx_runtime_runs_session ON runtime_runs(session_id)","CREATE INDEX IF NOT EXISTS idx_runtime_runs_agent ON runtime_runs(agent_id)","CREATE INDEX IF NOT EXISTS idx_runtime_runs_state ON runtime_runs(state)"].join(";")),r}(e);return{createRun(e){upsertRun(t,e)},updateRun(e,n){const r=readRun(t,e);if(!r)return;const s={...r,...clonePatch(n)};return upsertRun(t,s),cloneRun(s)},appendEvent(e){const n=readRun(t,e.requestId);if(!n)return;const r=eventArtifact(e);return r&&!n.artifacts.some(e=>e.id===r.id)&&n.artifacts.push(structuredClone(r)),n.events.push(cloneEvent(e)),upsertRun(t,n),cloneRun(n)},getRun:e=>cloneOptionalRun(readRun(t,e)),listRuns:e=>readRuns(t,e).map(cloneRun),deleteRun(e){const n=readRun(t,e);return t.prepare("DELETE FROM runtime_runs WHERE request_id = ?").run(e),cloneOptionalRun(n)},deleteSession(e){const n=readRuns(t,{sessionId:e}).map(e=>e.requestId);return t.prepare("DELETE FROM runtime_runs WHERE session_id = ?").run(e),{deletedRequestIds:n,deletedCount:n.length}}}}export function createJsonFileRuntimeStore(n){const r=s.resolve(n),u=createInMemoryRuntimeStore(function readStoreFile(n){if(!e(n))return[];const r=JSON.parse(t(n,"utf8"));if(!isRecord(r)||!Array.isArray(r.runs))throw new Error(`Invalid runtime store file: ${n}`);return r.runs.map(assertRunRecord)}(r));return{createRun(e){u.createRun(e),writeStoreFile(r,u.listRuns())},updateRun(e,n){const t=u.updateRun(e,n);return writeStoreFile(r,u.listRuns()),t},appendEvent(e){const n=u.appendEvent(e);return writeStoreFile(r,u.listRuns()),n},getRun:e=>u.getRun(e),listRuns:e=>u.listRuns(e),deleteRun(e){const n=u.deleteRun(e);return writeStoreFile(r,u.listRuns()),n},deleteSession(e){const n=u.deleteSession(e);return writeStoreFile(r,u.listRuns()),n}}}function upsertRun(e,n){e.prepare(["INSERT OR REPLACE INTO runtime_runs","(request_id, session_id, agent_id, state, started_at, completed_at, run_json)","VALUES (?, ?, ?, ?, ?, ?, ?)"].join(" ")).run(n.requestId,n.sessionId,n.agentId,n.state,n.startedAt,n.completedAt??null,JSON.stringify(n))}function readRun(e,n){const t=e.prepare("SELECT run_json AS runJson FROM runtime_runs WHERE request_id = ?").get(n);return t?assertRunRecord(JSON.parse(t.runJson)):void 0}function readRuns(e,n){const t=[],r=[];n?.agentId&&addClause(t,r,"agent_id",n.agentId),n?.sessionId&&addClause(t,r,"session_id",n.sessionId),n?.state&&addClause(t,r,"state",n.state);const s=t.length?` WHERE ${t.join(" AND ")}`:"";return e.prepare(`SELECT run_json AS runJson FROM runtime_runs${s} ORDER BY started_at ASC`).all(...r).map(e=>assertRunRecord(JSON.parse(e.runJson)))}function addClause(e,n,t,r){e.push(`${t} = ?`),n.push(r)}function writeStoreFile(e,t){n(s.dirname(e),{recursive:!0}),r(e,`${JSON.stringify({version:1,runs:t},null,2)}\n`)}function assertRunRecord(e){if(!isRecord(e)||"string"!=typeof e.requestId)throw new Error("Invalid runtime run record in store file");return cloneRun(e)}function cloneOptionalRun(e){return e?cloneRun(e):void 0}function cloneRun(e){return structuredClone(e)}function cloneEvent(e){return structuredClone(e)}function eventArtifact(e){return"artifact"in e&&e.artifact?e.artifact:void 0}function clonePatch(e){return structuredClone(e)}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { CompiledWorkspace } from "../../types.js";
|
|
2
|
+
export type RuntimeSystemDataPaths = {
|
|
3
|
+
root: string;
|
|
4
|
+
manifest: string;
|
|
5
|
+
controlPlane: string;
|
|
6
|
+
artifacts: string;
|
|
7
|
+
memoryLangMem: string;
|
|
8
|
+
checkpointsDeepAgents: string;
|
|
9
|
+
storeDeepAgents: string;
|
|
10
|
+
langgraph: string;
|
|
11
|
+
logs: string;
|
|
12
|
+
tmp: string;
|
|
13
|
+
};
|
|
14
|
+
export type RuntimeSystemDataInspection = {
|
|
15
|
+
schemaVersion: 1;
|
|
16
|
+
root: string;
|
|
17
|
+
paths: RuntimeSystemDataPaths;
|
|
18
|
+
entries: RuntimeSystemDataEntry[];
|
|
19
|
+
};
|
|
20
|
+
export type RuntimeSystemDataEntry = {
|
|
21
|
+
id: string;
|
|
22
|
+
path: string;
|
|
23
|
+
role: "source-of-truth" | "index" | "content" | "generated" | "diagnostic" | "temporary";
|
|
24
|
+
exists: boolean;
|
|
25
|
+
sizeBytes?: number;
|
|
26
|
+
};
|
|
27
|
+
export declare function resolveRuntimeSystemDataPaths(workspace: CompiledWorkspace): RuntimeSystemDataPaths;
|
|
28
|
+
export declare function ensureRuntimeSystemDataManifest(workspace: CompiledWorkspace): RuntimeSystemDataInspection;
|
|
29
|
+
export declare function inspectRuntimeSystemData(workspace: CompiledWorkspace): RuntimeSystemDataInspection;
|
|
30
|
+
export declare function collectRuntimeSystemDataDiagnostics(workspace: CompiledWorkspace): string[];
|
|
31
|
+
export declare function cleanupRuntimeSystemDataTmp(workspace: CompiledWorkspace): {
|
|
32
|
+
path: string;
|
|
33
|
+
removed: boolean;
|
|
34
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{existsSync as t,mkdirSync as e,readdirSync as n,rmSync as o,statSync as r,writeFileSync as s}from"node:fs";import a from"node:path";export function resolveRuntimeSystemDataPaths(t){const e=a.resolve(t.root,function runtimeDataRoot(t){const e=t.runtime.dataRoot;return"string"==typeof e&&e.trim()?e.trim():".stable-harness"}(t));return{root:e,manifest:a.join(e,"manifest.json"),controlPlane:a.join(e,"control-plane","stable.sqlite"),artifacts:a.join(e,"artifacts"),memoryLangMem:a.join(e,"memory","langmem","langmem.sqlite"),checkpointsDeepAgents:a.join(e,"checkpoints","deepagents.sqlite"),storeDeepAgents:a.join(e,"store","deepagents.sqlite"),langgraph:a.join(e,"langgraph"),logs:a.join(e,"logs"),tmp:a.join(e,"tmp")}}export function ensureRuntimeSystemDataManifest(t){const n=inspectRuntimeSystemData(t);return e(a.dirname(n.paths.manifest),{recursive:!0}),s(n.paths.manifest,`${JSON.stringify(function manifestBody(t,e){return{schemaVersion:1,product:"stable-harness",workspaceRoot:t.root,workspaceId:t.runtime.workspaceId??a.basename(t.root),createdAt:(new Date).toISOString(),paths:e,roles:{controlPlane:"runs, events, sessions, approvals, queue, recovery intents, and artifact metadata",artifacts:"artifact content files",memoryLangMem:"LangMem memory_records and memory_vectors",checkpointsDeepAgents:"DeepAgents checkpoint substrate",storeDeepAgents:"DeepAgents/LangGraph store substrate",langgraph:"generated LangGraph compatibility projection"}}}(t,n.paths),null,2)}\n`),inspectRuntimeSystemData(t)}export function inspectRuntimeSystemData(t){const e=resolveRuntimeSystemDataPaths(t);return{schemaVersion:1,root:e.root,paths:e,entries:systemEntries(e).map(inspectEntry)}}export function collectRuntimeSystemDataDiagnostics(t){const e=inspectRuntimeSystemData(t),n=[];for(const t of e.entries)"root"!==t.id&&"manifest"!==t.id&&(t.exists||"source-of-truth"!==t.role||n.push(`${t.id} missing: ${t.path}`));return n}export function cleanupRuntimeSystemDataTmp(n){const r=resolveRuntimeSystemDataPaths(n).tmp,s=t(r);return o(r,{recursive:!0,force:!0}),e(r,{recursive:!0}),{path:r,removed:s}}function systemEntries(t){return[{id:"root",path:t.root,role:"source-of-truth"},{id:"manifest",path:t.manifest,role:"index"},{id:"control-plane",path:t.controlPlane,role:"source-of-truth"},{id:"artifacts",path:t.artifacts,role:"content"},{id:"memory-langmem",path:t.memoryLangMem,role:"source-of-truth"},{id:"checkpoints-deepagents",path:t.checkpointsDeepAgents,role:"source-of-truth"},{id:"store-deepagents",path:t.storeDeepAgents,role:"source-of-truth"},{id:"langgraph",path:t.langgraph,role:"generated"},{id:"logs",path:t.logs,role:"diagnostic"},{id:"tmp",path:t.tmp,role:"temporary"}]}function inspectEntry(e){return t(e.path)?{...e,exists:!0,sizeBytes:entrySize(e.path)}:{...e,exists:!1}}function entrySize(t){const e=r(t);return e.isDirectory()?n(t).reduce((e,n)=>e+entrySize(a.join(t,n)),0):e.size}
|
|
@@ -1 +1 @@
|
|
|
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")}
|
|
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 n}from"../../recovery/raw-args.js";import{assertNoProgressOnlyToolIntentOutput as i,assertNoRawToolCallOutput as c,assertNoRawToolResultOutput as l,assertNoStructurallyIncompleteFinalOutput as u,assertNoToolExecutionErrorOutput as d,buildAdapterErrorRecoveryPrompt as y,buildEvidenceSynthesisOutput as v,buildResultRecoveryRequest as p,containsRawToolCallOutput as g,isRecoverableAdapterError as m,rawToolCallFailureMessage as w,rawToolCallOutputPreview as f,toolCallRecoveryEnabled as R}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 I,visibleToolCandidates as A}from"./non-focused-recovery.js";import{maxNonFocusedRecoveryRedirects as b,resultRecoveryAttempts as k}from"./recovery-policy.js";export async function recoverAdapterResultOutput(o){let r=o.result,s=o.request;const y=k(o.recoveryPolicy),m=new Set,_=new Set;let T=0;for(let e=0;;e+=1){const a=e+1,i=o.store.getRun(o.requestId)?.events??[],c=effectiveRecoveryToolIds(s,o.agent.tools),l=await recoverNonFocusedRawArgsByToolGateway(o,s,r,_,a,c,i);if(l){s=l.request,r=l.result;continue}const u=I({request:s,output:r.text,events:i,policy:o.recoveryPolicy,declaredToolIds:o.agent.tools,visibleToolIds:c});if(u){s=u,emitRepair(o,"runtime.repair.started","result_output",a,"non_focused_recovery_intent",void 0,repairDiagnostics(r.text,c)),r=await runResultRecoveryAdapter(o,u,a),emitRepair(o,"runtime.repair.completed","result_output",a,"non_focused_recovery_intent","retried",repairDiagnostics(r.text,c));continue}q(r.text,o.recoveryPolicy,o.agent.tools,c,i);const d=await recoverFocusedTextByToolGateway(o,s,r,_,a,c);if(d){s=d.request,r=d.result;continue}const v=await recoverRawArgsSequenceByToolGateway(o,s,r,_,a,c);if(v){s=v.request,r=v.result;continue}const g=n({output:r.text,agent:o.agent,workspace:o.workspace,toolGateway:o.toolGateway,events:i,candidateToolIds:c,policy:o.recoveryPolicy}),w=g?rawArgsToolKey(g):void 0;if(g&&w&&_.size>0&&!_.has(w)){const e=await recoverRawArgsByToolGateway(o,s,r,g,_,a);if(e){s=e.request,r=e.result;continue}}const f=w&&!m.has(w)?t({request:s,output:r.text,agent:o.agent,workspace:o.workspace,toolGateway:o.toolGateway,events:i,candidateToolIds:c,policy:o.recoveryPolicy}):void 0,R=T<y?p({request:s,output:r.text,events:i,availableToolIds:c,policy:o.recoveryPolicy}):void 0,x=f??R;if(!x)break;if(x===f&&m.add(w),s=x,x===R&&(T+=1),emitRepair(o,"runtime.repair.started","result_output",a,"recoverable_result_output",void 0,repairDiagnostics(r.text,c)),r=await runResultRecoveryAdapter(o,x,a),emitRepair(o,"runtime.repair.completed","result_output",a,"recoverable_result_output","retried",repairDiagnostics(r.text,c)),x===f){const e=await recoverRepeatedRawArgsByToolGateway(o,s,r,m,_,a);e&&(s=e.request,r=e.result)}}return function finalizeRecoveredOutput(t,o){if(!R(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:w(),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)),c(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: ${f(t)}`)}(t,o.text),i(o.text,t.agent.tools,t.recoveryPolicy),l(o.text,t.store.getRun(t.requestId)?.events??[],t.recoveryPolicy),d(o.text,t.recoveryPolicy),u(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 n=s[0],i=h(e,n),c=o.text.trim();if(!i||0===c.length||T(e.store.getRun(e.requestId)?.events??[]).includes(n))return;const l={toolId:n,args:{[i]:c}},u=rawArgsToolKey(l);if(r.has(u))return;r.add(u),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,l)),y=x({request:t,match:l,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,i){if(!e.runRecoveredToolCall||s.length===e.agent.tools.length||0===b(e.recoveryPolicy))return;const c=n({output:o.text,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:i,candidateToolIds:e.agent.tools,policy:e.recoveryPolicy});return!c||s.includes(c.toolId)||T(i).includes(c.toolId)?void 0:recoverRawArgsByToolGateway(e,t,o,c,r,a)}async function recoverRawArgsSequenceByToolGateway(e,t,o,a,n,i){if(!e.runRecoveredToolCall)return;const c=s({output:o.text,agent:e.agent,workspace:e.workspace,toolGateway:e.toolGateway,events:e.store.getRun(e.requestId)?.events??[],candidateToolIds:i,policy:e.recoveryPolicy});if(c.length<2||c.some(e=>a.has(rawArgsToolKey(e))))return;emitRepair(e,"runtime.repair.started","result_output",n,"raw_args_tool_sequence_gateway_recovery",void 0,repairDiagnostics(o.text,i));const l=[];for(const t of c){a.add(rawArgsToolKey(t));const o=await e.runRecoveredToolCall(t.toolId,t.args);l.push({match:t,toolOutput:visibleRecoveredToolOutput(o)})}const u=r({request:t,evidences:l}),d=await runResultRecoveryAdapter(e,u,n),y=d.text.trim()?d:{...d,text:buildEmptyRecoveredToolSequenceBlocker({evidences:l,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",n,"raw_args_tool_sequence_gateway_recovery","retried",repairDiagnostics(y.text,i)),{request:u,result:y}}async function recoverRepeatedRawArgsByToolGateway(e,t,o,r,a,s){const i=n({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(!i||!e.runRecoveredToolCall)return;const c=rawArgsToolKey(i);return r.has(c)&&!a.has(c)?recoverRawArgsByToolGateway(e,t,o,i,a,s):void 0}async function recoverRawArgsByToolGateway(e,t,r,a,s,n){if(!e.runRecoveredToolCall)return;const i=rawArgsToolKey(a);if(s.has(i))return;s.add(i),emitRepair(e,"runtime.repair.started","result_output",n,"raw_args_tool_gateway_recovery",void 0,repairDiagnostics(r.text,e.agent.tools));const c=visibleRecoveredToolOutput(await runRecoveredToolCallAsEvidence(e,a)),l=o({request:t,match:a,toolOutput:c}),u=await runResultRecoveryAdapter(e,l,n),d=u.text.trim()?u:{...u,text:buildEmptyRecoveredToolBlocker({match:a,toolOutput:c,events:e.store.getRun(e.requestId)?.events??[]}),metadata:{...u.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:l,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(!m(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,n){const i={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,...i}:{type:t,...i,outcome:s??"retried"})}function errorMessage(e){return e instanceof Error?e.message:String(e)}function repairDiagnostics(e,t){return{outputPreview:f(e),toolCandidateIds:A(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")}
|
|
@@ -1 +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
|
|
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 u=i.length>0?i:l.nonFocused;throw new Error(`Focused recovery output referenced non-focused tool(s): ${u.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)),u=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)}`),a=l(t.request.metadata);if(a>=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:",...u,"","Previous invalid recovery output:",t.output].filter(Boolean).join("\n"),metadata:{...t.request.metadata,stableHarnessRecovery:"tool_call",stableHarnessRequiredEvidenceTools:d,stableHarnessNonFocusedRecoveryRedirects:a+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};
|
|
@@ -1 +1 @@
|
|
|
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
|
|
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 p}from"./runtime/admin/administration.js";import{runDirectToolCall as c}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 g}from"./runtime/inspection/methods.js";import{createRuntimeCapabilityRegistry as f,normalizeAdapterResult as y}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 k}from"./runtime/admin/memory.js";import{createInMemoryRuntimeStore as R}from"./runtime/persistence/stores.js";import{createProgressNarrationCapability as A}from"./runtime/progress-narration.js";import{repairRuntimeSelection as j}from"./runtime/selection-repair.js";import{createLangSmithTracingCapability as b}from"./runtime/tracing/langsmith.js";import{createToolFailureTracker as C}from"./runtime/tool-failure.js";import{recoverExecutionContract as G}from"./runtime/recovery/execution-contract-runtime.js";import{runWorkflowRequest as x}from"./workflows/runtime.js";export function createStableHarnessRuntime(y){const E=new Set,T=y.store??R(),S=y.improvements??I(),h=f([q(y),A({options:y.progressNarration,policy:y.workspace.runtime}),b({policy:y.workspace.runtime,store:T,options:y.langSmithTracing}),...y.capabilities??[]]),emitBase=t=>{const r=function enrichRuntimeEvent(t){return{...t,eventId:t.eventId??e(),emittedAt:t.emittedAt??(new Date).toISOString()}}(t);T.appendEvent(r);for(const e of E)e(r)},emit=e=>{emitBase(e),h.emitSideEffects(e,emitBase)},O=m({gateway:d({gateway:y.toolGateway,approvals:y.approvals,workspace:y.workspace,emit:emit}),workspace:y.workspace,sandbox:y.sandbox,emit:emit}),M={...y,toolGateway:O},F=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}(y.workspace.runtime.toolGateway));return{request:async p=>async function runRuntimeRequest(p){const d=p.request.requestId??e(),m=p.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 j({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}}(p.input,p.request,{requestId:d,sessionId:m,emit:e=>l.push(e)});p.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:[]}}(p.request,d,m,w)),l.forEach(p.emit),p.emit({type:"runtime.request.started",requestId:d,sessionId:m,agentId:w.id,input:p.request.input});try{if(p.request.workflow){const e=await x({workspace:p.input.workspace,adapters:p.input.workflowAdapters??[],toolGateway:p.input.toolGateway,request:{input:p.request.input,...p.request.workflow},requestId:d,sessionId:m,agentId:w.id,emit:p.emit});return i({store:p.store,emit:p.emit,requestId:d,sessionId:m,agent:w,result:e,artifacts:p.input.artifacts})}if(p.request.toolCall){const e=await c({gateway:p.input.toolGateway,workspace:p.input.workspace,emit:p.emit,request:p.request,requestId:d,sessionId:m,agent:w,toolFailureTracker:p.toolFailureTracker,toolGuardrails:p.input.toolGuardrails,events:p.store.getRun(d)?.events??[]});return i({store:p.store,emit:p.emit,requestId:d,sessionId:m,agent:w,result:e,artifacts:p.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,p=await e.capabilities.beforeAdapterRun(createCapabilityContext(e)),c=p.memory,d=p.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,c,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),c,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,c,d,w,m),runRecoveredToolCall:(t,r)=>runRecoveredToolCall(e,t,r)}),I=await o(createQualityRuntimeInput(e,c,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,c,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,c,d,w,m),runRecoveredToolCall:(t,r)=>runRecoveredToolCall(e,t,r)}),recoverQuality:(t,r)=>o(createQualityRuntimeInput(e,c,d,w,m),t,r,l)});const g=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:g}),g}({...p,adapter:I,requestId:d,sessionId:m,agent:w})}catch(e){return u({store:p.store,emit:p.emit,requestId:d,sessionId:m,agent:w,error:e})}}({input:M,capabilities:h,store:T,emit:emit,request:p,toolFailureTracker:F}),subscribe:e=>(E.add(e),()=>E.delete(e)),...g({workspace:y.workspace,store:T,artifacts:y.artifacts,approvals:y.approvals,emit:emit}),...p({store:T,emit:emit}),...l({runtimeStore:T,store:S,emit:emit}),...w({runtimeStore:T,emit:emit}),...k({memory:y.memory}),cancel(e,t){const r=T.getRun(e);r&&"running"===r.state&&(T.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(),E.clear()}}}function runRecoveredToolCall(e,t,r){return c({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 y(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)}
|
|
@@ -19,8 +19,28 @@ export type WorkspaceWorkflowNode = {
|
|
|
19
19
|
id: string;
|
|
20
20
|
use: string;
|
|
21
21
|
type?: string;
|
|
22
|
+
input?: WorkspaceWorkflowNodeInput;
|
|
22
23
|
config?: Record<string, unknown>;
|
|
23
24
|
};
|
|
25
|
+
export type WorkspaceWorkflowNodeInput = {
|
|
26
|
+
from: "request";
|
|
27
|
+
path?: string;
|
|
28
|
+
} | {
|
|
29
|
+
from: "previous";
|
|
30
|
+
path?: string;
|
|
31
|
+
} | {
|
|
32
|
+
from: "node";
|
|
33
|
+
nodeId: string;
|
|
34
|
+
path?: string;
|
|
35
|
+
} | {
|
|
36
|
+
from: "outputs";
|
|
37
|
+
path?: string;
|
|
38
|
+
} | {
|
|
39
|
+
from: "state";
|
|
40
|
+
path?: string;
|
|
41
|
+
} | {
|
|
42
|
+
value: unknown;
|
|
43
|
+
};
|
|
24
44
|
export type WorkspaceWorkflowEdge = {
|
|
25
45
|
from: string;
|
|
26
46
|
to: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function compileWorkflowPlan(e){const n=e.entry??e.nodes[0]?.id;if(!n)throw new Error(`Workflow ${e.id} has no entry node`);const t=function buildAdjacency(e){const n=new Map(e.nodes.map(e=>[e.id,[]]));for(const t of e.edges)n.get(t.from)?.push(t.to);return n}(e),o=function collectReachable(e,n){const t=new Set,o=[e];for(;o.length>0;){const e=o.pop();t.has(e)||(t.add(e),o.push(...n.get(e)??[]))}return t}(n,t),a=function findCycles(e,n){const t=[];for(const o of e)collectCycles(o,o,n,[],t);return function dedupeCycles(e){const n=new Set;return e.filter(e=>{const t=function canonicalCycleKey(e){const n=e.slice(0,-1);return n.map((e,t)=>[...n.slice(t),...n.slice(0,t)].join("|")).sort()[0]??""}(e);return!n.has(t)&&(n.add(t),!0)})}(t)}(e.nodes.map(e=>e.id),t);return{workflowId:e.id,...e.adapter?{adapter:e.adapter}:{},entry:n,nodes:e.nodes,edges:e.edges,terminalNodes:e.nodes.map(e=>e.id).filter(e=>0===(t.get(e)??[]).length),unreachableNodes:e.nodes.map(e=>e.id).filter(e=>!o.has(e)),cycles:a}}export function renderWorkflowMermaid(e){const n=["flowchart TD"];for(const t of e.nodes)n.push(` ${escapeId(t.id)}["${escapeLabel(`${t.id}\\n${t.use}`)}"]`);for(const t of e.edges){const e=t.condition?`|${escapeLabel(t.condition)}|`:"";n.push(` ${escapeId(t.from)} --\x3e${e} ${escapeId(t.to)}`)}return n.join("\n")}export function renderAgentMermaid(e,n){const t=e.agents.get(n);if(!t)throw new Error(`Agent is not defined: ${n}`);const o=function agentGraphNodes(e){return[...e.subagents.map(e=>agentGraphNode("agent",e)),...(e.skills??[]).map(e=>agentGraphNode("skill",e)),...e.tools.map(e=>agentGraphNode("tool",e))]}(t),a=["flowchart TD",` START_${escapeId(t.id)}([START])`,` END_${escapeId(t.id)}([END])`];for(const e of o)a.push(` ${e.diagramId}["${escapeLabel(`${e.id}\\n${e.label}`)}"]`);return 0===o.length?(a.push(` START_${escapeId(t.id)} --\x3e END_${escapeId(t.id)}`),a.join("\n")):[...a,...t.edges?.length?explicitAgentMermaidEdges(t,o):inventoryAgentMermaidEdges(t,o)].join("\n")}function agentGraphNode(e,n){return{id:n,diagramId:`${e}_${escapeId(n)}`,label:`${e}: ${n}`}}function explicitAgentMermaidEdges(e,n){const t=new Map(n.map(e=>[e.id,e.diagramId])),o=new Set((e.edges??[]).map(e=>e.to)),a=new Set((e.edges??[]).map(e=>e.from)),d=n.filter(e=>!o.has(e.id)).map(e=>e.diagramId),r=n.filter(e=>!a.has(e.id)).map(e=>e.diagramId);return[...d.map(n=>` START_${escapeId(e.id)} --\x3e ${escapeId(n)}`),...(e.edges??[]).flatMap(e=>function renderAgentEdge(e,n){const t=n.get(e.from),o=n.get(e.to);
|
|
1
|
+
export function compileWorkflowPlan(e){const n=e.entry??e.nodes[0]?.id;if(!n)throw new Error(`Workflow ${e.id} has no entry node`);const t=function buildAdjacency(e){const n=new Map(e.nodes.map(e=>[e.id,[]]));for(const t of e.edges)n.get(t.from)?.push(t.to);return n}(e),o=function collectReachable(e,n){const t=new Set,o=[e];for(;o.length>0;){const e=o.pop();t.has(e)||(t.add(e),o.push(...n.get(e)??[]))}return t}(n,t),a=function findCycles(e,n){const t=[];for(const o of e)collectCycles(o,o,n,[],t);return function dedupeCycles(e){const n=new Set;return e.filter(e=>{const t=function canonicalCycleKey(e){const n=e.slice(0,-1);return n.map((e,t)=>[...n.slice(t),...n.slice(0,t)].join("|")).sort()[0]??""}(e);return!n.has(t)&&(n.add(t),!0)})}(t)}(e.nodes.map(e=>e.id),t);return{workflowId:e.id,...e.adapter?{adapter:e.adapter}:{},entry:n,nodes:e.nodes,edges:e.edges,terminalNodes:e.nodes.map(e=>e.id).filter(e=>0===(t.get(e)??[]).length),unreachableNodes:e.nodes.map(e=>e.id).filter(e=>!o.has(e)),cycles:a}}export function renderWorkflowMermaid(e){const n=["flowchart TD"];for(const t of e.nodes)n.push(` ${escapeId(t.id)}["${escapeLabel(`${t.id}\\n${t.use}`)}"]`);for(const t of e.edges){const e=t.condition?`|${escapeLabel(t.condition)}|`:"";n.push(` ${escapeId(t.from)} --\x3e${e} ${escapeId(t.to)}`)}return n.join("\n")}export function renderAgentMermaid(e,n){const t=e.agents.get(n);if(!t)throw new Error(`Agent is not defined: ${n}`);const o=function agentGraphNodes(e){return[...e.subagents.map(e=>agentGraphNode("agent",e)),...(e.skills??[]).map(e=>agentGraphNode("skill",e)),...e.tools.map(e=>agentGraphNode("tool",e))]}(t),a=["flowchart TD",` START_${escapeId(t.id)}([START])`,` END_${escapeId(t.id)}([END])`];for(const e of o)a.push(` ${e.diagramId}["${escapeLabel(`${e.id}\\n${e.label}`)}"]`);return 0===o.length?(a.push(` START_${escapeId(t.id)} --\x3e END_${escapeId(t.id)}`),a.join("\n")):[...a,...t.edges?.length?explicitAgentMermaidEdges(t,o):inventoryAgentMermaidEdges(t,o)].join("\n")}function agentGraphNode(e,n){return{id:n,diagramId:`${e}_${escapeId(n)}`,label:`${e}: ${n}`}}function explicitAgentMermaidEdges(e,n){const t=new Map(n.map(e=>[e.id,e.diagramId])),o=new Set((e.edges??[]).map(e=>e.to)),a=new Set((e.edges??[]).map(e=>e.from)),d=n.filter(e=>!o.has(e.id)).map(e=>e.diagramId),r=n.filter(e=>!a.has(e.id)).map(e=>e.diagramId);return[...d.map(n=>` START_${escapeId(e.id)} --\x3e ${escapeId(n)}`),...(e.edges??[]).flatMap(e=>function renderAgentEdge(e,n){const t=n.get(e.from),o=n.get(e.to);if(!t||!o)return[];return[` ${t} --\x3e${e.condition?`|${escapeLabel(e.condition)}|`:""} ${o}`]}(e,t)),...r.map(n=>` ${escapeId(n)} --\x3e END_${escapeId(e.id)}`)]}function inventoryAgentMermaidEdges(e,n){return n.flatMap(n=>[` START_${escapeId(e.id)} -. available .-> ${n.diagramId}`,` ${n.diagramId} -.-> END_${escapeId(e.id)}`])}function collectCycles(e,n,t,o,a){const d=[...o,n];for(const r of t.get(n)??[])r===e?a.push([...d,e]):o.includes(r)||collectCycles(e,r,t,d,a)}function escapeId(e){return e.replace(/[^A-Za-z0-9_]/gu,"_")}function escapeLabel(e){return e.replace(/"/gu,'\\"')}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stable-harness/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.144",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
".": "./dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"@stable-harness/governance": "0.0.
|
|
16
|
-
"@stable-harness/memory": "0.0.
|
|
15
|
+
"@stable-harness/governance": "0.0.144",
|
|
16
|
+
"@stable-harness/memory": "0.0.144"
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID as e}from"node:crypto";export function createInMemoryApprovalQueue(){const t=[];return{async create(
|
|
1
|
+
import{randomUUID as e}from"node:crypto";import{mkdirSync as t}from"node:fs";import r from"node:path";import{DatabaseSync as s}from"node:sqlite";export function createInMemoryApprovalQueue(){const t=[];return{async create(r){const s={id:e(),kind:r.kind,reason:r.reason,status:"pending",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agentId,subject:r.subject,createdAt:(new Date).toISOString()};return t.push(s),s},get:async e=>t.find(t=>t.id===e),list:async e=>e?t.filter(t=>t.status===e):[...t],async resolve(e,r){const s=t.find(t=>t.id===e);if(s)return s.status=r,s.resolvedAt=(new Date).toISOString(),s}}}export function createSqliteApprovalQueue(n){const a=function openApprovalDatabase(e){const n=r.resolve(e);t(r.dirname(n),{recursive:!0});const a=new s(n);return a.exec("PRAGMA busy_timeout = 5000; PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL"),a.exec(["CREATE TABLE IF NOT EXISTS runtime_approvals (id TEXT PRIMARY KEY, status TEXT NOT NULL, request_id TEXT, session_id TEXT, agent_id TEXT, approval_json TEXT NOT NULL)","CREATE INDEX IF NOT EXISTS idx_runtime_approvals_status ON runtime_approvals(status)"].join(";")),a}(n);return{async create(t){const r={id:e(),kind:t.kind,reason:t.reason,status:"pending",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agentId,subject:t.subject,createdAt:(new Date).toISOString()};return writeApproval(a,r),r},get:async e=>readApproval(a,e),list:async e=>function readApprovals(e,t){const r=t?"SELECT approval_json AS approvalJson FROM runtime_approvals WHERE status = ? ORDER BY id ASC":"SELECT approval_json AS approvalJson FROM runtime_approvals ORDER BY id ASC";return(t?e.prepare(r).all(t):e.prepare(r).all()).map(e=>JSON.parse(e.approvalJson))}(a,e),async resolve(e,t){const r=readApproval(a,e);if(!r)return;const s={...r,status:t,resolvedAt:(new Date).toISOString()};return writeApproval(a,s),s}}}function writeApproval(e,t){e.prepare(["INSERT OR REPLACE INTO runtime_approvals","(id, status, request_id, session_id, agent_id, approval_json)","VALUES (?, ?, ?, ?, ?, ?)"].join(" ")).run(t.id,t.status,t.requestId??null,t.sessionId??null,t.agentId??null,JSON.stringify(t))}function readApproval(e,t){const r=e.prepare("SELECT approval_json AS approvalJson FROM runtime_approvals WHERE id = ?").get(t);return r?JSON.parse(r.approvalJson):void 0}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createInMemoryApprovalQueue } from "./approval-queue.js";
|
|
1
|
+
export { createInMemoryApprovalQueue, createSqliteApprovalQueue } from "./approval-queue.js";
|
|
2
2
|
export { createPolicyEngine } from "./policy-engine.js";
|
|
3
3
|
export { createSqliteSkillCandidateStore } from "./skill-candidates.js";
|
|
4
4
|
export type { ApprovalQueue, ApprovalRequest, ApprovalRequestKind, ApprovalRequestStatus, PolicyDecision, RuntimePolicyEngine, SkillCandidate, SkillCandidateEvidence, SkillCandidateInput, SkillCandidateStatus, SkillCandidateStore, ToolPolicy, } from "./types.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{createInMemoryApprovalQueue}from"./approval-queue.js";export{createPolicyEngine}from"./policy-engine.js";export{createSqliteSkillCandidateStore}from"./skill-candidates.js";
|
|
1
|
+
export{createInMemoryApprovalQueue,createSqliteApprovalQueue}from"./approval-queue.js";export{createPolicyEngine}from"./policy-engine.js";export{createSqliteSkillCandidateStore}from"./skill-candidates.js";
|
|
@@ -8,9 +8,11 @@ export type RuntimeEventFilter = {
|
|
|
8
8
|
since?: string;
|
|
9
9
|
};
|
|
10
10
|
export declare function readRuntimeEventFilter(url: string | undefined): RuntimeEventFilter | undefined;
|
|
11
|
+
export declare function readRunScopedEventFilter(url: string | undefined): RuntimeEventFilter | undefined;
|
|
11
12
|
export declare function streamRuntimeEvents(input: {
|
|
12
13
|
runtime: StableHarnessRuntime;
|
|
13
14
|
request: IncomingMessage;
|
|
14
15
|
response: ServerResponse;
|
|
15
16
|
filter: RuntimeEventFilter;
|
|
17
|
+
headers?: Record<string, string>;
|
|
16
18
|
}): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function readRuntimeEventFilter(e){if(!e?.startsWith("/events"))return;const t=new URL(e,"http://stable-harness.local");if("/events"!==t.pathname)return;const n=t.searchParams.get("types")?.split(",").map(e=>e.trim()).filter(Boolean);return{...readParam(t,"requestId")?{requestId:readParam(t,"requestId")}:{},...readParam(t,"sessionId")?{sessionId:readParam(t,"sessionId")}:{},...readParam(t,"agentId")?{agentId:readParam(t,"agentId")}:{},...n&&n.length>0?{types:n}:{},...readParam(t,"since")?{since:readParam(t,"since")}:{}}}export function streamRuntimeEvents(e){e.response.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"}),e.response.write(": stable-harness runtime event stream\n\n"),e.response.flushHeaders();for(const t of function replayEvents(e,t){return e.inspect().runs.flatMap(e=>e.events).filter(e=>matchesEventFilter(e,t))}(e.runtime,e.filter))writeRuntimeEvent(e.response,t);const t=e.runtime.subscribe(t=>{matchesEventFilter(t,e.filter)&&writeRuntimeEvent(e.response,t)});e.request.on("close",()=>{t(),e.response.end()})}function matchesEventFilter(e,t){return matchesValue(t.requestId,e.requestId)&&matchesValue(t.sessionId,e.sessionId)&&matchesValue(t.agentId,e.agentId)&&function matchesTypeFilter(e,t){return!t||0===t.length||t.some(t=>t.endsWith("*")?e.startsWith(t.slice(0,-1)):e===t)}(e.type,t.types)&&function matchesSince(e,t){return!t||e.eventId!==t&&Boolean(e.emittedAt&&e.emittedAt>t)}(e,t.since)}function matchesValue(e,t){return!e||e===t}function writeRuntimeEvent(e,t){e.write(`event: ${t.type}\n`),t.eventId&&e.write(`id: ${t.eventId}\n`),e.write(`data: ${JSON.stringify(t)}\n\n`)}function readParam(e,t){const n=e.searchParams.get(t);return n&&n.trim()?n:void 0}
|
|
1
|
+
export function readRuntimeEventFilter(e){if(!e?.startsWith("/events"))return;const t=new URL(e,"http://stable-harness.local");if("/events"!==t.pathname)return;const n=t.searchParams.get("types")?.split(",").map(e=>e.trim()).filter(Boolean);return{...readParam(t,"requestId")?{requestId:readParam(t,"requestId")}:{},...readParam(t,"sessionId")?{sessionId:readParam(t,"sessionId")}:{},...readParam(t,"agentId")?{agentId:readParam(t,"agentId")}:{},...n&&n.length>0?{types:n}:{},...readParam(t,"since")?{since:readParam(t,"since")}:{}}}export function readRunScopedEventFilter(e){const t=new URL(e??"/","http://stable-harness.local"),n=t.pathname.match(/^\/runs\/([^/]+)\/events$/u);return n?.[1]?{...readEventQueryFilter(t),requestId:decodeURIComponent(n[1])}:void 0}export function streamRuntimeEvents(e){e.response.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive",...e.headers}),e.response.write(": stable-harness runtime event stream\n\n"),e.response.flushHeaders();for(const t of function replayEvents(e,t){return e.inspect().runs.flatMap(e=>e.events).filter(e=>matchesEventFilter(e,t))}(e.runtime,e.filter))writeRuntimeEvent(e.response,t);const t=e.runtime.subscribe(t=>{matchesEventFilter(t,e.filter)&&writeRuntimeEvent(e.response,t)});e.request.on("close",()=>{t(),e.response.end()})}function matchesEventFilter(e,t){return matchesValue(t.requestId,e.requestId)&&matchesValue(t.sessionId,e.sessionId)&&matchesValue(t.agentId,e.agentId)&&function matchesTypeFilter(e,t){return!t||0===t.length||t.some(t=>t.endsWith("*")?e.startsWith(t.slice(0,-1)):e===t)}(e.type,t.types)&&function matchesSince(e,t){return!t||e.eventId!==t&&Boolean(e.emittedAt&&e.emittedAt>t)}(e,t.since)}function matchesValue(e,t){return!e||e===t}function writeRuntimeEvent(e,t){e.write(`event: ${t.type}\n`),t.eventId&&e.write(`id: ${t.eventId}\n`),e.write(`data: ${JSON.stringify(t)}\n\n`)}function readParam(e,t){const n=e.searchParams.get(t);return n&&n.trim()?n:void 0}function readEventQueryFilter(e){const t=e.searchParams.get("types")?.split(",").map(e=>e.trim()).filter(Boolean);return{...readParam(e,"sessionId")?{sessionId:readParam(e,"sessionId")}:{},...readParam(e,"agentId")?{agentId:readParam(e,"agentId")}:{},...t&&t.length>0?{types:t}:{},...readParam(e,"since")?{since:readParam(e,"since")}:{}}}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { type IncomingMessage, type ServerResponse } from "node:http";
|
|
2
2
|
import { type StableHarnessRuntime } from "@stable-harness/core";
|
|
3
|
-
export
|
|
3
|
+
export type StableRuntimeHttpServerOptions = {
|
|
4
|
+
bearerToken?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function createHttpServer(runtime: StableHarnessRuntime, options?: StableRuntimeHttpServerOptions): import("node:http").Server<typeof IncomingMessage, typeof ServerResponse>;
|
|
7
|
+
export declare function handleStableRuntimeHttpRequest(runtime: StableHarnessRuntime, request: IncomingMessage, response: ServerResponse): Promise<void>;
|