stable-harness 0.0.49 → 0.0.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/node_modules/@stable-harness/adapter-deepagents/dist/src/adapter.js +1 -1
  2. package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-tool-policy.js +1 -1
  3. package/node_modules/@stable-harness/core/dist/memory-plugins.d.ts +3 -0
  4. package/node_modules/@stable-harness/core/dist/memory-plugins.js +1 -1
  5. package/node_modules/@stable-harness/core/dist/runtime/events.d.ts +19 -0
  6. package/node_modules/@stable-harness/core/dist/runtime/memory.js +1 -1
  7. package/node_modules/@stable-harness/core/dist/runtime/policy/projection.js +1 -1
  8. package/node_modules/@stable-harness/core/dist/runtime/progress-narration.js +1 -1
  9. package/node_modules/@stable-harness/core/dist/runtime/recovery/adapter-result.d.ts +12 -0
  10. package/node_modules/@stable-harness/core/dist/runtime/recovery/adapter-result.js +1 -0
  11. package/node_modules/@stable-harness/core/dist/runtime.js +1 -1
  12. package/node_modules/@stable-harness/core/dist/trace.js +1 -1
  13. package/package.json +1 -1
  14. package/packages/adapter-deepagents/dist/src/adapter.js +1 -1
  15. package/packages/adapter-deepagents/dist/src/internal/builtin-tool-policy.js +1 -1
  16. package/packages/cli/dist/src/cli.js +1 -1
  17. package/packages/cli/dist/src/event-view.js +1 -1
  18. package/packages/cli/dist/src/init.js +1 -1
  19. package/packages/cli/dist/src/memory/defaults.d.ts +1 -0
  20. package/packages/cli/dist/src/memory/defaults.js +1 -0
  21. package/packages/cli/dist/src/memory/lifecycle.js +1 -1
  22. package/packages/cli/dist/src/memory/providers.js +1 -1
  23. package/packages/core/dist/memory-plugins.d.ts +3 -0
  24. package/packages/core/dist/memory-plugins.js +1 -1
  25. package/packages/core/dist/runtime/events.d.ts +19 -0
  26. package/packages/core/dist/runtime/memory.js +1 -1
  27. package/packages/core/dist/runtime/policy/projection.js +1 -1
  28. package/packages/core/dist/runtime/progress-narration.js +1 -1
  29. package/packages/core/dist/runtime/recovery/adapter-result.d.ts +12 -0
  30. package/packages/core/dist/runtime/recovery/adapter-result.js +1 -0
  31. package/packages/core/dist/runtime.js +1 -1
  32. package/packages/core/dist/trace.js +1 -1
  33. package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/skill-file-policy.d.ts +0 -10
  34. package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/skill-file-policy.js +0 -1
  35. package/packages/adapter-deepagents/dist/src/internal/skill-file-policy.d.ts +0 -10
  36. package/packages/adapter-deepagents/dist/src/internal/skill-file-policy.js +0 -1
@@ -1 +1 @@
1
- import{realpathSync as e}from"node:fs";import t from"node:path";import{buildRuntimeSystemPrompt as r}from"@stable-harness/core";import{createBuiltinToolPolicyMiddleware as n,createObserverMiddleware as o}from"./internal/builtin-tool-policy.js";import{resolveFilesystemPermissions as s}from"./internal/builtin/permissions.js";import{createToolRepeatState as a}from"@stable-harness/core";import{buildGatewayTools as i,stringifyDeepAgentResult as p}from"./internal/gateway-tools.js";import{resolveDeepAgentsNativeMemories as d}from"./memory.js";import{buildDeepAgentRequest as c}from"./internal/messages.js";import{createRawToolCallParserMiddleware as l}from"./internal/raw-tool-call-parser.js";import{createBackendModel as u}from"./model-providers.js";import{createDeepAgentsRetryMiddleware as m}from"./retry-policy.js";import{streamDeepAgentResult as g}from"./internal/stream-events.js";export function createDeepAgentsAdapter(e={}){return{name:"deepagents",canRun:e=>"deepagents"===e.backend,async run(t){if(t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",phase:"agent.handoff",modelRef:t.agent.modelRef,tools:t.agent.tools,subagents:t.agent.subagents}}),e.runner)return e.runner(t);const r=e.createDeepAgent?void 0:await async function loadDeepAgentsModule(){try{return await async function importOptionalPackage(e){return import(e)}("deepagents")}catch(e){throw new Error(`DeepAgents package is required for the default adapter path: ${function formatError(e){return e instanceof Error?e.message:String(e)}(e)}`)}}(),n=e.createDeepAgent??function readCreateDeepAgent(e){const t=e?.createDeepAgent;if("function"==typeof t)return t;throw new Error("DeepAgents package does not export createDeepAgent.")}(r),o=n(function buildDeepAgentParams(e,t,r){const n={...readDeepAgentsConfig(t),...readDeepAgentsConfig(e.agent.config.deepagents)},o=resolveDeepAgentsSkills(e,e.agent),a=n.permissions??s(e,e.agent),p=requestScopedRepeatState(e,e.agent.id);return pruneUndefined({name:e.agent.id,model:n.model??resolveAgentModel(e,e.agent),systemPrompt:buildSystemPrompt(e,e.agent),backend:n.backend??resolveDeepAgentsBackend(e,r,o),checkpointer:n.checkpointer,store:n.store,middleware:mergeMiddleware(e,e.agent,n.middleware,p),responseFormat:n.responseFormat,contextSchema:n.contextSchema,interruptOn:n.interruptOn,generalPurposeAgent:readBoolean(n.generalPurposeAgent),taskDescription:readString(n.taskDescription),permissions:a,tools:i(e,e.agent.id,e.agent.tools,resolveAgentRepairModel(e,e.agent,n),p),subagents:e.agent.subagents.map(t=>{const r=e.workspace.agents.get(t),n=readDeepAgentsConfig(r?.config.deepagents),o=n.permissions??s(e,r),a=scopedInput(e,r),p=requestScopedRepeatState(e,t);return pruneUndefined({name:t,description:r?.description??readString(r?.config.description)??r?.id,systemPrompt:buildSystemPrompt(e,r),model:n.model??(r?resolveAgentModel(e,r):void 0),middleware:mergeMiddleware(a,r,n.middleware,p),interruptOn:n.interruptOn,generalPurposeAgent:readBoolean(n.generalPurposeAgent),taskDescription:readString(n.taskDescription),permissions:o,responseFormat:n.responseFormat,tools:i(e,t,r?.tools??[],resolveAgentRepairModel(a,r,n),p),memory:resolveDeepAgentsMemory(e,r),skills:resolveDeepAgentsSkills(e,r)})}),memory:resolveDeepAgentsMemory(e,e.agent),skills:o})}(t,e.config,r)),a=c(t),d=function buildDeepAgentInvokeConfig(e){return pruneUndefined({recursionLimit:readNumber(readDeepAgentsConfig(e.config.deepagents).recursionLimit)??readNumber(e.config.recursionLimit)})}(t.agent);if(!0===t.request.metadata?.openaiStream&&o.streamEvents){const e=await o.streamEvents(a,{version:"v3",...d});return g(t,e,p)}const l=await o.invoke(a,d);return p(l)}}}function buildSystemPrompt(e,t){const n=t?.systemPrompt??readString(t?.config.systemPrompt);return r({workspace:e.workspace,request:e.request,agent:t},n)}function resolveDeepAgentsMemory(e,t){const r=readDeepAgentsStringArray(t?.config,"memory");if(r)return r;const n=[...readAgentMemorySources(e.workspace.root,t),...d(e.workspace).map(e=>`/memories/${e.id}.md`)],o=[...new Set(n)];return o.length>0?o:void 0}function readAgentMemorySources(e,t){return(t?.memory??[]).flatMap(t=>"string"==typeof t&&t.trim()?[backendMemorySourcePath(e,t.trim())]:isRecord(t)&&"string"==typeof t.path&&t.path.trim()?[backendMemorySourcePath(e,t.path.trim())]:[])}function backendMemorySourcePath(e,r){if(r.startsWith("/"))return r;if(t.isAbsolute(r)){const n=t.relative(e,r);return n&&!n.startsWith("..")?`/${n.split(t.sep).join("/")}`:canonicalPath(r)}const n=r.split(t.sep).join("/");return n.startsWith("/")?n:`/${n}`}function resolveDeepAgentsSkills(e,r){const n=readDeepAgentsStringArray(r?.config,"skills");if(n)return n;const o=[...new Set((r?.skills??[]).map(t=>e.workspace.skills.get(t)?.path).filter(e=>"string"==typeof e&&e.trim().length>0).map(r=>function backendSkillSourcePath(e,r){const n=t.dirname(t.dirname(r)),o=t.relative(e,n);return!o||o.startsWith("..")||t.isAbsolute(o)?""===o?"/":canonicalPath(n):`/${o.split(t.sep).join("/")}`}(e.workspace.root,r)))];return o.length>0?o:void 0}function resolveDeepAgentsBackend(e,t,r){if(t?.FilesystemBackend&&r&&0!==r.length)return()=>new t.FilesystemBackend({rootDir:e.workspace.root})}function mergeMiddleware(e,t,r,s=a(e.workspace.runtime.toolGateway)){const i=Array.isArray(r)?r:[],p=scopedInput(e,t),d=new Set,c=readDeepAgentsConfig(t?.config.deepagents);return[o(p,{observedToolIds:d,repeatState:s,repairModel:resolveAgentRepairModel(p,t,c)}),n(p,{repeatState:s}),...m(e.workspace.runtime.retry),...i,l(p)]}function requestScopedRepeatState(e,t){const r=`deepagents.repeat.${t}`,n=e.requestState?.get(r);if(n)return n;const o=a(e.workspace.runtime.toolGateway);return e.requestState&&o&&e.requestState.set(r,o),o}function scopedInput(e,t){return t?{...e,agent:t}:e}function resolveAgentModel(e,t){const r=t.modelRef?e.workspace.models.get(t.modelRef):void 0;return r?u(r):void 0}function resolveAgentRepairModel(e,t,r){const n=r.model;if(isRepairModel(n))return n;if(!t)return;const o=resolveAgentModel(e,t);return isRepairModel(o)?o:void 0}function readDeepAgentsConfig(e){return isRecord(e)?e:{}}function readDeepAgentsStringArray(e,t){const r=isRecord(e)?e:{},n=readDeepAgentsConfig(r.deepagents),o="memory"===t?["memory","memorySources"]:["skills","skillSources"];for(const e of o){const t=readStringArray(n[e]);if(t)return t}return readStringArray(r[t])}function pruneUndefined(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>void 0!==e))}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readNumber(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function readBoolean(e){return"boolean"==typeof e?e:void 0}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e):void 0}function canonicalPath(t){try{return e.native(t)}catch{return t}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function isRepairModel(e){return"object"==typeof e&&null!==e&&"invoke"in e&&"function"==typeof e.invoke}
1
+ import{realpathSync as e}from"node:fs";import t from"node:path";import{buildRuntimeSystemPrompt as r}from"@stable-harness/core";import{createBuiltinToolPolicyMiddleware as n,createObserverMiddleware as o}from"./internal/builtin-tool-policy.js";import{resolveFilesystemPermissions as s}from"./internal/builtin/permissions.js";import{createToolRepeatState as a}from"@stable-harness/core";import{buildGatewayTools as i,stringifyDeepAgentResult as p}from"./internal/gateway-tools.js";import{resolveDeepAgentsNativeMemories as d}from"./memory.js";import{buildDeepAgentRequest as c}from"./internal/messages.js";import{createRawToolCallParserMiddleware as l}from"./internal/raw-tool-call-parser.js";import{createBackendModel as u}from"./model-providers.js";import{createDeepAgentsRetryMiddleware as m}from"./retry-policy.js";import{streamDeepAgentResult as g}from"./internal/stream-events.js";export function createDeepAgentsAdapter(e={}){return{name:"deepagents",canRun:e=>"deepagents"===e.backend,async run(t){if(t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",phase:"agent.handoff",modelRef:t.agent.modelRef,tools:t.agent.tools,skills:t.agent.skills,subagents:t.agent.subagents}}),e.runner)return e.runner(t);const r=e.createDeepAgent?void 0:await async function loadDeepAgentsModule(){try{return await async function importOptionalPackage(e){return import(e)}("deepagents")}catch(e){throw new Error(`DeepAgents package is required for the default adapter path: ${function formatError(e){return e instanceof Error?e.message:String(e)}(e)}`)}}(),n=e.createDeepAgent??function readCreateDeepAgent(e){const t=e?.createDeepAgent;if("function"==typeof t)return t;throw new Error("DeepAgents package does not export createDeepAgent.")}(r),o=n(function buildDeepAgentParams(e,t,r){const n={...readDeepAgentsConfig(t),...readDeepAgentsConfig(e.agent.config.deepagents)},o=resolveDeepAgentsSkills(e,e.agent),a=n.permissions??s(e,e.agent),p=requestScopedRepeatState(e,e.agent.id);return pruneUndefined({name:e.agent.id,model:n.model??resolveAgentModel(e,e.agent),systemPrompt:buildSystemPrompt(e,e.agent),backend:n.backend??resolveDeepAgentsBackend(e,r,o),checkpointer:n.checkpointer,store:n.store,middleware:mergeMiddleware(e,e.agent,n.middleware,p),responseFormat:n.responseFormat,contextSchema:n.contextSchema,interruptOn:n.interruptOn,generalPurposeAgent:readBoolean(n.generalPurposeAgent),taskDescription:readString(n.taskDescription),permissions:a,tools:i(e,e.agent.id,e.agent.tools,resolveAgentRepairModel(e,e.agent,n),p),subagents:e.agent.subagents.map(t=>{const r=e.workspace.agents.get(t),n=readDeepAgentsConfig(r?.config.deepagents),o=n.permissions??s(e,r),a=scopedInput(e,r),p=requestScopedRepeatState(e,t);return pruneUndefined({name:t,description:r?.description??readString(r?.config.description)??r?.id,systemPrompt:buildSystemPrompt(e,r),model:n.model??(r?resolveAgentModel(e,r):void 0),middleware:mergeMiddleware(a,r,n.middleware,p),interruptOn:n.interruptOn,generalPurposeAgent:readBoolean(n.generalPurposeAgent),taskDescription:readString(n.taskDescription),permissions:o,responseFormat:n.responseFormat,tools:i(e,t,r?.tools??[],resolveAgentRepairModel(a,r,n),p),memory:resolveDeepAgentsMemory(e,r),skills:resolveDeepAgentsSkills(e,r)})}),memory:resolveDeepAgentsMemory(e,e.agent),skills:o})}(t,e.config,r)),a=c(t),d=function buildDeepAgentInvokeConfig(e){return pruneUndefined({recursionLimit:readNumber(readDeepAgentsConfig(e.config.deepagents).recursionLimit)??readNumber(e.config.recursionLimit)})}(t.agent);if(!0===t.request.metadata?.openaiStream&&o.streamEvents){const e=await o.streamEvents(a,{version:"v3",...d});return g(t,e,p)}const l=await o.invoke(a,d);return p(l)}}}function buildSystemPrompt(e,t){const n=t?.systemPrompt??readString(t?.config.systemPrompt);return r({workspace:e.workspace,request:e.request,agent:t},n)}function resolveDeepAgentsMemory(e,t){const r=readDeepAgentsStringArray(t?.config,"memory");if(r)return r;const n=[...readAgentMemorySources(e.workspace.root,t),...d(e.workspace).map(e=>`/memories/${e.id}.md`)],o=[...new Set(n)];return o.length>0?o:void 0}function readAgentMemorySources(e,t){return(t?.memory??[]).flatMap(t=>"string"==typeof t&&t.trim()?[backendMemorySourcePath(e,t.trim())]:isRecord(t)&&"string"==typeof t.path&&t.path.trim()?[backendMemorySourcePath(e,t.path.trim())]:[])}function backendMemorySourcePath(e,r){if(r.startsWith("/"))return r;if(t.isAbsolute(r)){const n=t.relative(e,r);return n&&!n.startsWith("..")?`/${n.split(t.sep).join("/")}`:canonicalPath(r)}const n=r.split(t.sep).join("/");return n.startsWith("/")?n:`/${n}`}function resolveDeepAgentsSkills(e,r){const n=readDeepAgentsStringArray(r?.config,"skills");if(n)return n;const o=[...new Set((r?.skills??[]).map(t=>e.workspace.skills.get(t)?.path).filter(e=>"string"==typeof e&&e.trim().length>0).map(r=>function backendSkillSourcePath(e,r){const n=t.dirname(t.dirname(r)),o=t.relative(e,n);return!o||o.startsWith("..")||t.isAbsolute(o)?""===o?"/":canonicalPath(n):`/${o.split(t.sep).join("/")}`}(e.workspace.root,r)))];return o.length>0?o:void 0}function resolveDeepAgentsBackend(e,t,r){if(t?.FilesystemBackend&&r&&0!==r.length)return()=>new t.FilesystemBackend({rootDir:e.workspace.root})}function mergeMiddleware(e,t,r,s=a(e.workspace.runtime.toolGateway)){const i=Array.isArray(r)?r:[],p=scopedInput(e,t),d=new Set,c=readDeepAgentsConfig(t?.config.deepagents);return[o(p,{observedToolIds:d,repeatState:s,repairModel:resolveAgentRepairModel(p,t,c)}),n(p,{repeatState:s}),...m(e.workspace.runtime.retry),...i,l(p)]}function requestScopedRepeatState(e,t){const r=`deepagents.repeat.${t}`,n=e.requestState?.get(r);if(n)return n;const o=a(e.workspace.runtime.toolGateway);return e.requestState&&o&&e.requestState.set(r,o),o}function scopedInput(e,t){return t?{...e,agent:t}:e}function resolveAgentModel(e,t){const r=t.modelRef?e.workspace.models.get(t.modelRef):void 0;return r?u(r):void 0}function resolveAgentRepairModel(e,t,r){const n=r.model;if(isRepairModel(n))return n;if(!t)return;const o=resolveAgentModel(e,t);return isRepairModel(o)?o:void 0}function readDeepAgentsConfig(e){return isRecord(e)?e:{}}function readDeepAgentsStringArray(e,t){const r=isRecord(e)?e:{},n=readDeepAgentsConfig(r.deepagents),o="memory"===t?["memory","memorySources"]:["skills","skillSources"];for(const e of o){const t=readStringArray(n[e]);if(t)return t}return readStringArray(r[t])}function pruneUndefined(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>void 0!==e))}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readNumber(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function readBoolean(e){return"boolean"==typeof e?e:void 0}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e):void 0}function canonicalPath(t){try{return e.native(t)}catch{return t}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function isRepairModel(e){return"object"==typeof e&&null!==e&&"invoke"in e&&"function"==typeof e.invoke}
@@ -1 +1 @@
1
- import{ToolMessage as t}from"@langchain/core/messages";import{afterToolInvoke as e,beforeToolInvoke as o,createToolRepeatState as r}from"@stable-harness/core";import{filesystemBuiltinToolIds as i,isFilesystemDisabled as n,isFilesystemTool as s,validateFilesystemBuiltinCall as a}from"./builtin/permissions.js";import{repairTaskCall as l}from"./builtin/task-inventory.js";import{repairBuiltinToolRequest as u}from"./builtin-call-repair.js";import{stringifyDeepAgentResult as c,toolControlProjection as d}from"./gateway-tools.js";import{isSuccessfulEvidenceOutput as p,observedToolEvidence as m,recordObservedToolEvidence as g}from"./gateway/tool-evidence.js";import{validateSkillFileBuiltinCall as f}from"./skill-file-policy.js";import{filterRepeatLimitedTools as v}from"./tool-repeat-visibility.js";import{traceProjectionForBuiltinTool as b}from"./trace-projection.js";const T=new Set(["write_todos","read_todos","task","execute",...i]);export function createBuiltinToolPolicyMiddleware(t,e={}){return{name:"StableHarnessBuiltinToolPolicy",async wrapModelCall(o,r){const i=Array.isArray(o.tools)?v(o.tools.filter(e=>!function hasHiddenBuiltins(t){return n(t)||!isTaskVisible(t)}(t)||isModelVisibleBuiltin(t,e.name)),e.repeatState):o.tools,s=function normalizeToolChoice(t,e,o){return"required"===e?o&&o.length>0?e:"auto":function isForcedHiddenTool(t,e){return"string"==typeof e?.function?.name&&!isModelVisibleBuiltin(t,e.function.name)}(t,e)?"auto":e}(t,o.toolChoice,i);return r({...o,tools:i,toolChoice:s})}}}export function createObserverMiddleware(i,n={}){const s=n.repeatState??r(i.workspace.runtime.toolGateway);return{name:"StableHarnessObserver",async wrapToolCall(r,d){const g=r.toolCall?.name;if(!g||!T.has(g))return d(r);const v=await u({toolId:g,request:r,workspaceRoot:i.workspace.root});emitToolEvent(i,g,"agent.tool.start",v.toolCall?.args);const b="task"===g?await l(i,v,{repairModel:n.repairModel}):{request:v},h=b.request,y=b.blocked;if(y)return emitToolEvent(i,g,"agent.tool.result",h.toolCall?.args,{output:y.content}),y;const k=a(i,g,h);if(k)return emitToolEvent(i,g,"agent.tool.result",h.toolCall?.args,{output:k.content}),k;const C=f(i,g,h);if(C)return emitToolEvent(i,g,"agent.tool.result",h.toolCall?.args,{output:C.content}),C;try{const a=s?o(g,h.toolCall?.args,s):void 0;if(a)return emitToolEvent(i,g,"agent.tool.result",h.toolCall?.args,{output:a.eventOutput}),builtinToolMessage(r,g,function modelOutputForRepeatedBuiltin(t,e){return"task"!==t?e:function readPreviousOutput(t){try{const e=JSON.parse(t);if(!isRecord(e)||"repeated_tool_call_limit"!==e.status||"string"!=typeof e.previousOutput)return;const o=e.previousOutput.trim();return o.length>0?o:void 0}catch{return}}(e)??e}(g,a.modelOutput));const l=await d(h),u=function observedToolOutput(t,e,o){return"write_todos"===t?JSON.stringify({status:"recorded",args:e.toolCall?.args}):c(o)}(g,h,l),m=s?e({toolId:g,args:h.toolCall?.args,output:u,successful:!(l instanceof t&&"error"===l.status)&&p(u),state:s}):{};return emitToolEvent(i,g,"agent.tool.result",h.toolCall?.args,{output:m.eventOutput??u}),n.observedToolIds?.add(g),void 0===m.modelOutput?l:builtinToolMessage(r,g,m.modelOutput)}catch(e){const o=function recoverableBuiltinToolError(e,o,r,i){const n=formatError(i);if("task"===o&&/repeat limit reached for tool/iu.test(n)){const o=function formatObservedEvidence(t){const e=m(t);if(0===e.length)return"";const o=e.map(t=>[`Agent: ${t.agentId}`,`Tool: ${t.toolId}`,t.output].join("\n")).join("\n\n---\n\n");return o.length>12e3?`${o.slice(0,12e3)}\n[truncated]`:o}(e);return new t({tool_call_id:r.toolCall?.id??"stable-harness-task-repeat-limit",name:"task",content:JSON.stringify({status:"delegated_task_repeat_limit",finalizationRequired:!0,instruction:"The delegated agent reached a configured tool repeat limit. Stop delegating this evidence need and do not send a synthesis task to another subagent for the same need. Finalize only from observedEvidence and other evidence that is already visible in this run. If the visible evidence is insufficient for a requested claim, report an explicit blocker or evidence gap instead of estimating, inventing, or using generic knowledge.",...o?{observedEvidence:o}:{},error:previewError(n)})})}if(/Received tool input did not match expected schema|Invalid input:/iu.test(n))return new t({tool_call_id:r.toolCall?.id??`stable-harness-${o}-argument-error`,name:o,status:"error",content:JSON.stringify({status:"tool_argument_error",toolId:o,instruction:"The upstream builtin tool rejected these arguments. Fix the tool arguments according to the tool schema, or choose a more appropriate available tool.",error:previewError(n)})})}(i,g,r,e);if(o)return emitToolEvent(i,g,"agent.tool.result",v.toolCall?.args,{output:o.content}),o;throw emitToolEvent(i,g,"agent.tool.result",v.toolCall?.args,{error:formatError(e)}),e}}}}function builtinToolMessage(e,o,r){return new t({tool_call_id:e.toolCall?.id??`stable-harness-${o}-repeat-guard`,name:o,content:r})}function emitToolEvent(t,e,o,r,i={}){"string"==typeof i.output&&g(t,t.agent.id,e,i.output),t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",eventGroup:"tool_execution",eventType:"agent.tool.start"===o?"deepagents.tool_execution.start":"deepagents.tool_execution.result",phase:o,toolId:e,..."agent.tool.start"===o?{args:r}:{},...i,..."string"==typeof i.output?d(i.output):{},...b(e,o,r)}})}function isTaskVisible(t){const e=function readConfigRecord(t,e){const o=isRecord(t)?t:{};return isRecord(o[e])?o[e]:void 0}(t.agent.config,"builtinTools")?.modelExposed;return!1!==e&&(!Array.isArray(e)||e.includes("task"))}function isModelVisibleBuiltin(t,e){return(!n(t)||!s(e))&&("task"!==e||isTaskVisible(t))}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function formatError(t){return t instanceof Error?t.message:String(t)}function previewError(t){const e=t.replace(/\s+/gu," ").trim();return e.length>800?`${e.slice(0,797)}...`:e}
1
+ import{ToolMessage as t}from"@langchain/core/messages";import{afterToolInvoke as e,beforeToolInvoke as o,createToolRepeatState as r}from"@stable-harness/core";import{filesystemBuiltinToolIds as n,isFilesystemDisabled as i,isFilesystemTool as s,validateFilesystemBuiltinCall as a}from"./builtin/permissions.js";import{repairTaskCall as l}from"./builtin/task-inventory.js";import{repairBuiltinToolRequest as u}from"./builtin-call-repair.js";import{stringifyDeepAgentResult as c,toolControlProjection as d}from"./gateway-tools.js";import{isSuccessfulEvidenceOutput as p,observedToolEvidence as g,recordObservedToolEvidence as m}from"./gateway/tool-evidence.js";import{filterRepeatLimitedTools as f}from"./tool-repeat-visibility.js";import{traceProjectionForBuiltinTool as v}from"./trace-projection.js";const b=new Set(["write_todos","read_todos","task","execute",...n]);export function createBuiltinToolPolicyMiddleware(t,e={}){return{name:"StableHarnessBuiltinToolPolicy",async wrapModelCall(o,r){const n=Array.isArray(o.tools)?f(o.tools.filter(e=>!function hasHiddenBuiltins(t){return i(t)||!isTaskVisible(t)}(t)||isModelVisibleBuiltin(t,e.name)),e.repeatState):o.tools,s=function normalizeToolChoice(t,e,o){return"required"===e?o&&o.length>0?e:"auto":function isForcedHiddenTool(t,e){return"string"==typeof e?.function?.name&&!isModelVisibleBuiltin(t,e.function.name)}(t,e)?"auto":e}(t,o.toolChoice,n);return r({...o,tools:n,toolChoice:s})}}}export function createObserverMiddleware(n,i={}){const s=i.repeatState??r(n.workspace.runtime.toolGateway);return{name:"StableHarnessObserver",async wrapToolCall(r,d){const m=r.toolCall?.name;if(!m||!b.has(m))return d(r);const f=await u({toolId:m,request:r,workspaceRoot:n.workspace.root});emitToolEvent(n,m,"agent.tool.start",f.toolCall?.args);const v="task"===m?await l(n,f,{repairModel:i.repairModel}):{request:f},T=v.request,h=v.blocked;if(h)return emitToolEvent(n,m,"agent.tool.result",T.toolCall?.args,{output:h.content}),h;const y=a(n,m,T);if(y)return emitToolEvent(n,m,"agent.tool.result",T.toolCall?.args,{output:y.content}),y;try{const a=s?o(m,T.toolCall?.args,s):void 0;if(a)return emitToolEvent(n,m,"agent.tool.result",T.toolCall?.args,{output:a.eventOutput}),builtinToolMessage(r,m,function modelOutputForRepeatedBuiltin(t,e){return"task"!==t?e:function readPreviousOutput(t){try{const e=JSON.parse(t);if(!isRecord(e)||"repeated_tool_call_limit"!==e.status||"string"!=typeof e.previousOutput)return;const o=e.previousOutput.trim();return o.length>0?o:void 0}catch{return}}(e)??e}(m,a.modelOutput));const l=await d(T),u=function observedToolOutput(t,e,o){return"write_todos"===t?JSON.stringify({status:"recorded",args:e.toolCall?.args}):c(o)}(m,T,l),g=s?e({toolId:m,args:T.toolCall?.args,output:u,successful:!(l instanceof t&&"error"===l.status)&&p(u),state:s}):{};return emitToolEvent(n,m,"agent.tool.result",T.toolCall?.args,{output:g.eventOutput??u}),i.observedToolIds?.add(m),void 0===g.modelOutput?l:builtinToolMessage(r,m,g.modelOutput)}catch(e){const o=function recoverableBuiltinToolError(e,o,r,n){const i=formatError(n);if("task"===o&&/repeat limit reached for tool/iu.test(i)){const o=function formatObservedEvidence(t){const e=g(t);if(0===e.length)return"";const o=e.map(t=>[`Agent: ${t.agentId}`,`Tool: ${t.toolId}`,t.output].join("\n")).join("\n\n---\n\n");return o.length>12e3?`${o.slice(0,12e3)}\n[truncated]`:o}(e);return new t({tool_call_id:r.toolCall?.id??"stable-harness-task-repeat-limit",name:"task",content:JSON.stringify({status:"delegated_task_repeat_limit",finalizationRequired:!0,instruction:"The delegated agent reached a configured tool repeat limit. Stop delegating this evidence need and do not send a synthesis task to another subagent for the same need. Finalize only from observedEvidence and other evidence that is already visible in this run. If the visible evidence is insufficient for a requested claim, report an explicit blocker or evidence gap instead of estimating, inventing, or using generic knowledge.",...o?{observedEvidence:o}:{},error:previewError(i)})})}if(/Received tool input did not match expected schema|Invalid input:/iu.test(i))return new t({tool_call_id:r.toolCall?.id??`stable-harness-${o}-argument-error`,name:o,status:"error",content:JSON.stringify({status:"tool_argument_error",toolId:o,instruction:"The upstream builtin tool rejected these arguments. Fix the tool arguments according to the tool schema, or choose a more appropriate available tool.",error:previewError(i)})})}(n,m,r,e);if(o)return emitToolEvent(n,m,"agent.tool.result",f.toolCall?.args,{output:o.content}),o;throw emitToolEvent(n,m,"agent.tool.result",f.toolCall?.args,{error:formatError(e)}),e}}}}function builtinToolMessage(e,o,r){return new t({tool_call_id:e.toolCall?.id??`stable-harness-${o}-repeat-guard`,name:o,content:r})}function emitToolEvent(t,e,o,r,n={}){"string"==typeof n.output&&m(t,t.agent.id,e,n.output),t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",eventGroup:"tool_execution",eventType:"agent.tool.start"===o?"deepagents.tool_execution.start":"deepagents.tool_execution.result",phase:o,toolId:e,..."agent.tool.start"===o?{args:r}:{},...n,..."string"==typeof n.output?d(n.output):{},...v(e,o,r)}})}function isTaskVisible(t){const e=function readConfigRecord(t,e){const o=isRecord(t)?t:{};return isRecord(o[e])?o[e]:void 0}(t.agent.config,"builtinTools")?.modelExposed;return!1!==e&&(!Array.isArray(e)||e.includes("task"))}function isModelVisibleBuiltin(t,e){return(!i(t)||!s(e))&&("task"!==e||isTaskVisible(t))}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function formatError(t){return t instanceof Error?t.message:String(t)}function previewError(t){const e=t.replace(/\s+/gu," ").trim();return e.length>800?`${e.slice(0,797)}...`:e}
@@ -15,6 +15,9 @@ export declare function runMemoryPlugins(input: {
15
15
  }): Promise<void>;
16
16
  export declare function recallMemoryPlugins(input: {
17
17
  providers: MemoryProvider[] | undefined;
18
+ emit?: RuntimeEmit;
19
+ requestId?: string;
20
+ sessionId?: string;
18
21
  request: RuntimeRequest;
19
22
  agent: WorkspaceAgent;
20
23
  workspace: CompiledWorkspace;
@@ -1 +1 @@
1
- import{formatError as e,readRecord as r,readWorkspaceId as t,resolveEnabledMemories as n,resolveMemoryProvider as o,resolvePluginNamespace as a}from"./memory-plugins/shared.js";export{resolveEnabledMemories,resolvePluginNamespace}from"./memory-plugins/shared.js";export{createLangMemMaintenanceTarget,createMemoryMaintenanceDaemon,createSkillCandidateMinerTarget}from"./memory-plugins/maintenance.js";export async function runMemoryPlugins(e){const r=n(e.workspace,"write");if(e.providers?.length&&0!==r.length&&!1!==e.request.metadata?.memoryWrite)for(const t of r)await runMemoryPlugin(e,t)}export async function recallMemoryPlugins(e){const r=n(e.workspace,"recall");if(!e.providers?.length||0===r.length)return[];const t=await Promise.all(r.map(async r=>{try{return await async function recallMemoryPlugin(e,r){const t=o(e.providers??[],r.provider);if(!t)return;const n=a(e.workspace,e.agent,e.request,r),s=await t.search({namespace:n,query:buildRecallQuery(e),limit:readRecallLimit(e.workspace)});return{namespace:n,records:s,context:formatRecallContext(e.workspace,s)}}(e,r)}catch{return}}));return t.filter(e=>Boolean(e?.context))}async function runMemoryPlugin(r,t){const n=o(r.providers??[],t.provider);if(!n)return;const s=a(r.workspace,r.agent,r.request,t);r.emit({type:"runtime.memory.plugin.started",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s});try{const e=await n.propose(function createPluginProposeInput(e,r,t){return{namespace:t,content:[`User input:\n${e.request.input}`,`Agent output:\n${e.result.text}`].join("\n\n"),sourceType:"runtime-run",sourceRef:e.requestId,metadata:{memoryId:r.id,provider:r.provider,profile:r.profile,mode:r.mode,prompts:r.prompts,workspaceRoot:e.workspace.root,agentId:e.agent.id,sessionId:e.sessionId,requestMetadata:e.request.metadata}}}(r,t,s));r.emit({type:"runtime.memory.plugin.completed",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s,candidateCount:e.length})}catch(o){r.emit({type:"runtime.memory.plugin.failed",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s,error:e(o)})}}function buildRecallQuery(e){const r=[`task: ${e.request.input}`,`workspace: ${t(e.workspace)}`,`agent: ${e.agent.id}`,"memory_needed: durable preferences, workspace facts, reusable procedures, prior corrections"],n=function readRecentContext(e){return"string"==typeof e?.recentContext?e.recentContext.slice(0,3e3):Array.isArray(e?.recentTurns)?e.recentTurns.filter(e=>"string"==typeof e).slice(-6).join("\n").slice(0,3e3):void 0}(e.request.metadata);return n?[...r,`recent_context: ${n}`].join("\n"):r.join("\n")}function readRecallLimit(e){const t=r(e.runtime.memory?.LangMem),n=r(t?.recall),o=n?.topK??n?.limit;return"number"==typeof o&&Number.isFinite(o)?o:10}function formatRecallContext(e,t){const n=function readRecallContextLimits(e){const t=r(e.runtime.memory?.LangMem),n=r(t?.recall);return{maxContextChars:readPositiveNumber(n?.maxContextChars)??4e3,maxRecordChars:readPositiveNumber(n?.maxRecordChars)??1e3}}(e),o=[];let a=n.maxContextChars;for(const e of t){if(a<=0)break;const r=truncateText(formatRecallRecord(e),Math.min(n.maxRecordChars,a));r.trim()&&(o.push(r),a-=r.length+1)}return o.join("\n")}function formatRecallRecord(e){return`- ${e.summary??e.content}\n ${e.content}`}function readPositiveNumber(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?Math.floor(e):void 0}function truncateText(e,r){return e.length>r?`${e.slice(0,Math.max(0,r-13))}\n [truncated]`:e}
1
+ import{formatError as e,readRecord as r,readWorkspaceId as t,resolveEnabledMemories as n,resolveMemoryProvider as o,resolvePluginNamespace as a}from"./memory-plugins/shared.js";export{resolveEnabledMemories,resolvePluginNamespace}from"./memory-plugins/shared.js";export{createLangMemMaintenanceTarget,createMemoryMaintenanceDaemon,createSkillCandidateMinerTarget}from"./memory-plugins/maintenance.js";export async function runMemoryPlugins(e){const r=n(e.workspace,"write");if(e.providers?.length&&0!==r.length&&!1!==e.request.metadata?.memoryWrite)for(const t of r)await runMemoryPlugin(e,t)}export async function recallMemoryPlugins(e){const r=n(e.workspace,"recall");if(!e.providers?.length||0===r.length)return[];const t=await Promise.all(r.map(async r=>{try{return await async function recallMemoryPlugin(e,r){const t=o(e.providers??[],r.provider);if(!t)return;const n=a(e.workspace,e.agent,e.request,r),s=await t.search({namespace:n,query:buildRecallQuery(e),limit:readRecallLimit(e.workspace)});return e.emit&&e.requestId&&e.sessionId&&e.emit({type:"runtime.memory.recall.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,namespace:n,recordIds:s.map(e=>e.id),context:formatRecallContext(e.workspace,s)}),{namespace:n,records:s,context:formatRecallContext(e.workspace,s)}}(e,r)}catch{return}}));return t.filter(e=>Boolean(e?.context))}async function runMemoryPlugin(r,t){const n=o(r.providers??[],t.provider);if(!n)return;const s=a(r.workspace,r.agent,r.request,t);r.emit({type:"runtime.memory.plugin.started",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s});try{const e=await n.propose(function createPluginProposeInput(e,r,t){return{namespace:t,content:[`User input:\n${e.request.input}`,`Agent output:\n${e.result.text}`].join("\n\n"),sourceType:"runtime-run",sourceRef:e.requestId,metadata:{memoryId:r.id,provider:r.provider,profile:r.profile,mode:r.mode,prompts:r.prompts,workspaceRoot:e.workspace.root,agentId:e.agent.id,sessionId:e.sessionId,requestMetadata:e.request.metadata}}}(r,t,s));r.emit({type:"runtime.memory.plugin.completed",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s,candidateCount:e.length})}catch(o){r.emit({type:"runtime.memory.plugin.failed",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s,error:e(o)})}}function buildRecallQuery(e){const r=[`task: ${e.request.input}`,`workspace: ${t(e.workspace)}`,`agent: ${e.agent.id}`,"memory_needed: durable preferences, workspace facts, reusable procedures, prior corrections"],n=function readRecentContext(e){return"string"==typeof e?.recentContext?e.recentContext.slice(0,3e3):Array.isArray(e?.recentTurns)?e.recentTurns.filter(e=>"string"==typeof e).slice(-6).join("\n").slice(0,3e3):void 0}(e.request.metadata);return n?[...r,`recent_context: ${n}`].join("\n"):r.join("\n")}function readRecallLimit(e){const t=r(e.runtime.memory?.LangMem),n=r(t?.recall),o=n?.topK??n?.limit;return"number"==typeof o&&Number.isFinite(o)?o:10}function formatRecallContext(e,t){const n=function readRecallContextLimits(e){const t=r(e.runtime.memory?.LangMem),n=r(t?.recall);return{maxContextChars:readPositiveNumber(n?.maxContextChars)??4e3,maxRecordChars:readPositiveNumber(n?.maxRecordChars)??1e3}}(e),o=[];let a=n.maxContextChars;for(const e of t){if(a<=0)break;const r=truncateText(formatRecallRecord(e),Math.min(n.maxRecordChars,a));r.trim()&&(o.push(r),a-=r.length+1)}return o.join("\n")}function formatRecallRecord(e){return`- ${e.summary??e.content}\n ${e.content}`}function readPositiveNumber(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?Math.floor(e):void 0}function truncateText(e,r){return e.length>r?`${e.slice(0,Math.max(0,r-13))}\n [truncated]`:e}
@@ -5,6 +5,8 @@ import type { RuntimeSandboxDecision } from "./tool-gateway.js";
5
5
  import type { RuntimeToolFailureClassification, RuntimeToolFailureReason } from "./tool-failure.js";
6
6
  export type RuntimeInventoryRepairLayer = "agent" | "workflow_route" | "workflow" | "tool" | "task" | "skill";
7
7
  export type RuntimeInventoryRepairStatus = "repaired" | "blocked";
8
+ export type RuntimeRepairLayer = "adapter_error" | "result_output" | "execution_contract" | "evidence_synthesis";
9
+ export type RuntimeRepairOutcome = "retried" | "synthesized" | "blocked";
8
10
  export type RuntimeInventoryRepairDiagnostic = {
9
11
  layer: RuntimeInventoryRepairLayer;
10
12
  owner: "stable_runtime_policy" | "protocol_adapter" | "upstream_backend" | "workspace_config";
@@ -56,6 +58,23 @@ export type RuntimeEvent = RuntimeEventMetadata & ({
56
58
  agentId: string;
57
59
  reason: string;
58
60
  missingEvidenceTools?: string[];
61
+ } | {
62
+ type: "runtime.repair.started";
63
+ requestId: string;
64
+ sessionId: string;
65
+ agentId: string;
66
+ layer: RuntimeRepairLayer;
67
+ attempt?: number;
68
+ reason?: string;
69
+ } | {
70
+ type: "runtime.repair.completed";
71
+ requestId: string;
72
+ sessionId: string;
73
+ agentId: string;
74
+ layer: RuntimeRepairLayer;
75
+ outcome: RuntimeRepairOutcome;
76
+ attempt?: number;
77
+ reason?: string;
59
78
  } | {
60
79
  type: "runtime.inventory.repair";
61
80
  requestId: string;
@@ -1 +1 @@
1
- import{recallMemoryPlugins as e,runMemoryPlugins as r}from"../memory-plugins.js";export function emitMemoryLifecycle(e,r,s,t,o,a){e&&r({type:"runtime.memory.lifecycle",requestId:s,sessionId:t,agentId:o,hook:a})}export async function runMemoryRecall(e){if(!e.memory)return;if(emitMemoryLifecycle(e.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"read-before-plan"),!1===e.request.memory?.recall)return;const r=resolveMemoryNamespace(e.workspace,e.agent,e.request),s=e.request.memory?.recall?.query??e.request.input,t=await e.memory.recall({namespace:r,query:s,limit:e.request.memory?.recall?.limit});return e.emit({type:"runtime.memory.recall.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,namespace:r,recordIds:t.records.map(e=>e.id),context:t.context}),{namespace:r,records:t.records,context:t.context}}export async function submitMemoryCandidates(e){if(!e.memory||!e.request.memory?.candidates?.length)return;emitMemoryLifecycle(e.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"write-after-run");const r=resolveMemoryNamespace(e.workspace,e.agent,e.request);for(const s of e.request.memory.candidates){const t={...s,namespace:s.namespace??r},o=await e.memory.submitCandidate(t);if(e.emit({type:"runtime.memory.candidate.submitted",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,candidate:o.candidate,decision:o.decision,record:o.record}),"review"===o.decision.action&&e.approvals){const r=await e.approvals.create({kind:"memory_write",reason:o.decision.reason,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,subject:{candidate:o.candidate,decision:o.decision}});e.emit({type:"runtime.memory.approval.requested",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,approval:r})}}}export function createMemoryRuntimeCapability(s){return{id:"runtime.memory",beforeAdapterRun:async r=>({memory:await runMemoryRecall({memory:s.memory,emit:r.emit,request:r.request,requestId:r.requestId,sessionId:r.sessionId,agent:r.agent,workspace:r.workspace}),pluginMemories:await e({providers:s.memoryProviders,request:r.request,agent:r.agent,workspace:r.workspace})}),async beforeAdapterResultContract(e){emitMemoryLifecycle(s.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"read-before-finalize"),await submitMemoryCandidates({memory:s.memory,approvals:s.approvals,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,workspace:e.workspace})},async afterAdapterResponse(e){await r({providers:s.memoryProviders,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,workspace:e.workspace,result:e.result})}}}function resolveMemoryNamespace(e,r,s){return s.memory?.namespace??`${e.root}:${r.id}`}
1
+ import{recallMemoryPlugins as e,runMemoryPlugins as r}from"../memory-plugins.js";export function emitMemoryLifecycle(e,r,s,t,o,a){e&&r({type:"runtime.memory.lifecycle",requestId:s,sessionId:t,agentId:o,hook:a})}export async function runMemoryRecall(e){if(!e.memory)return;if(emitMemoryLifecycle(e.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"read-before-plan"),!1===e.request.memory?.recall)return;const r=resolveMemoryNamespace(e.workspace,e.agent,e.request),s=e.request.memory?.recall?.query??e.request.input,t=await e.memory.recall({namespace:r,query:s,limit:e.request.memory?.recall?.limit});return e.emit({type:"runtime.memory.recall.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,namespace:r,recordIds:t.records.map(e=>e.id),context:t.context}),{namespace:r,records:t.records,context:t.context}}export async function submitMemoryCandidates(e){if(!e.memory||!e.request.memory?.candidates?.length)return;emitMemoryLifecycle(e.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"write-after-run");const r=resolveMemoryNamespace(e.workspace,e.agent,e.request);for(const s of e.request.memory.candidates){const t={...s,namespace:s.namespace??r},o=await e.memory.submitCandidate(t);if(e.emit({type:"runtime.memory.candidate.submitted",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,candidate:o.candidate,decision:o.decision,record:o.record}),"review"===o.decision.action&&e.approvals){const r=await e.approvals.create({kind:"memory_write",reason:o.decision.reason,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,subject:{candidate:o.candidate,decision:o.decision}});e.emit({type:"runtime.memory.approval.requested",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,approval:r})}}}export function createMemoryRuntimeCapability(s){return{id:"runtime.memory",beforeAdapterRun:async r=>({memory:await runMemoryRecall({memory:s.memory,emit:r.emit,request:r.request,requestId:r.requestId,sessionId:r.sessionId,agent:r.agent,workspace:r.workspace}),pluginMemories:await e({providers:s.memoryProviders,emit:r.emit,requestId:r.requestId,sessionId:r.sessionId,request:r.request,agent:r.agent,workspace:r.workspace})}),async beforeAdapterResultContract(e){emitMemoryLifecycle(s.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"read-before-finalize"),await submitMemoryCandidates({memory:s.memory,approvals:s.approvals,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,workspace:e.workspace})},async afterAdapterResponse(e){await r({providers:s.memoryProviders,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,workspace:e.workspace,result:e.result})}}}function resolveMemoryNamespace(e,r,s){return s.memory?.namespace??`${e.root}:${r.id}`}
@@ -1 +1 @@
1
- export function projectRuntimePolicies(e){return{systemPromptSections:[skillInventoryPolicy(e),responseLanguagePolicy(e),responsePresentationPolicy(e)].filter(e=>Boolean(e))}}export function buildRuntimeSystemPrompt(e,t){const n=[t,...projectRuntimePolicies(e).systemPromptSections].filter(e=>Boolean(e));return n.length>0?n.join("\n\n"):void 0}function skillInventoryPolicy(e){const t=(e.agent?.skills??[]).map(t=>e.workspace.skills.get(t)).filter(e=>Boolean(e));if(0!==t.length)return["## Stable Harness Skill Inventory","Use only the skills listed in this workspace inventory. Do not infer or invent skill names, skill directories, or SKILL.md paths from generic examples.","Skill files are already registered with the backend. Do not read local SKILL.md files or skill directories through filesystem tools.","If none of these skills match the task, continue with the configured tools and collected evidence instead of reading an unlisted skill path.",t.map(e=>{const t=e.allowedTools.length>0?`; allowed tools: ${e.allowedTools.join(", ")}`:"",n=e.description?`: ${e.description}${t}`:t;return`- ${e.id}${n}`}).join("\n")].join("\n")}function responseLanguagePolicy(e){const t=readRecord(e.workspace.runtime.responseLanguage);if("matchUser"!==(readString(t.mode)??readString(t.strategy)))return;const n=function detectRequestLanguage(e){return/\p{Script=Han}/u.test(e)?"Chinese":/[\p{Script=Hiragana}\p{Script=Katakana}]/u.test(e)?"Japanese":/\p{Script=Hangul}/u.test(e)?"Korean":/\p{Script=Arabic}/u.test(e)?"Arabic":/\p{Script=Hebrew}/u.test(e)?"Hebrew":/\p{Script=Thai}/u.test(e)?"Thai":/\p{Script=Cyrillic}/u.test(e)?"Cyrillic-script language":void 0}(e.request.input);return["Stable runtime response language policy:",...n?[`- Detected request language: ${n}.`]:[],"- Match the final answer language to the original user request unless the user explicitly asks for another language.","- If tool or subagent evidence is in a different language, translate the final user-facing answer into the detected request language.","- When delegating to subagents, include the same response-language requirement in delegated instructions.","- Do not call another tool or subagent only to translate, rewrite, format, or synthesize a completed answer.",`Original user request:\n${e.request.input}`].join("\n")}function responsePresentationPolicy(e){const t=readRecord(e.workspace.runtime.responsePresentation);if(!0===t.enabled&&!function hasStructuredResponseFormat(e){return void 0!==e?.config.responseFormat||isRecord(e?.config.deepagents)&&void 0!==e.config.deepagents.responseFormat}(e.agent))return"markdown"===(readString(t.style)??"markdown")?["Stable runtime final-answer presentation policy:","- For user-facing natural-language final answers, use GitHub-flavored Markdown.","- Prefer clear section headings, short paragraphs, and concise bullets over dense prose.","- Use tables only when they make comparison or planning details easier to scan.","- For detailed investigations, plans, or reports, include assumptions, findings, recommendations, and concrete next steps.","- Preserve exact plain text, JSON, code, or other structured output when the user or response format asks for it.","- Do not end with generic follow-up offers; deliver the requested answer directly."].join("\n"):void 0}function readRecord(e){return isRecord(e)?e:{}}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
1
+ export function projectRuntimePolicies(e){return{systemPromptSections:[skillInventoryPolicy(e),responseLanguagePolicy(e),responsePresentationPolicy(e)].filter(e=>Boolean(e))}}export function buildRuntimeSystemPrompt(e,t){const n=[t,...projectRuntimePolicies(e).systemPromptSections].filter(e=>Boolean(e));return n.length>0?n.join("\n\n"):void 0}function skillInventoryPolicy(e){const t=(e.agent?.skills??[]).map(t=>e.workspace.skills.get(t)).filter(e=>Boolean(e));if(0!==t.length)return["## Stable Harness Skill Inventory","Use only the skills listed in this workspace inventory. Do not infer or invent skill names, skill directories, or SKILL.md paths from generic examples.","When a listed skill matches the task, use DeepAgents progressive disclosure: read that registered SKILL.md path through builtin filesystem tools before applying the detailed workflow.","If none of these skills match the task, continue with the configured tools and collected evidence instead of reading an unlisted skill path.",t.map(e=>{const t=e.allowedTools.length>0?`; allowed tools: ${e.allowedTools.join(", ")}`:"",n=e.description?`: ${e.description}${t}`:t;return`- ${e.id}${n}`}).join("\n")].join("\n")}function responseLanguagePolicy(e){const t=readRecord(e.workspace.runtime.responseLanguage);if("matchUser"!==(readString(t.mode)??readString(t.strategy)))return;const n=function detectRequestLanguage(e){return/\p{Script=Han}/u.test(e)?"Chinese":/[\p{Script=Hiragana}\p{Script=Katakana}]/u.test(e)?"Japanese":/\p{Script=Hangul}/u.test(e)?"Korean":/\p{Script=Arabic}/u.test(e)?"Arabic":/\p{Script=Hebrew}/u.test(e)?"Hebrew":/\p{Script=Thai}/u.test(e)?"Thai":/\p{Script=Cyrillic}/u.test(e)?"Cyrillic-script language":void 0}(e.request.input);return["Stable runtime response language policy:",...n?[`- Detected request language: ${n}.`]:[],"- Match the final answer language to the original user request unless the user explicitly asks for another language.","- If tool or subagent evidence is in a different language, translate the final user-facing answer into the detected request language.","- When delegating to subagents, include the same response-language requirement in delegated instructions.","- Do not call another tool or subagent only to translate, rewrite, format, or synthesize a completed answer.",`Original user request:\n${e.request.input}`].join("\n")}function responsePresentationPolicy(e){const t=readRecord(e.workspace.runtime.responsePresentation);if(!0===t.enabled&&!function hasStructuredResponseFormat(e){return void 0!==e?.config.responseFormat||isRecord(e?.config.deepagents)&&void 0!==e.config.deepagents.responseFormat}(e.agent))return"markdown"===(readString(t.style)??"markdown")?["Stable runtime final-answer presentation policy:","- For user-facing natural-language final answers, use GitHub-flavored Markdown.","- Prefer clear section headings, short paragraphs, and concise bullets over dense prose.","- Use tables only when they make comparison or planning details easier to scan.","- For detailed investigations, plans, or reports, include assumptions, findings, recommendations, and concrete next steps.","- Preserve exact plain text, JSON, code, or other structured output when the user or response format asks for it.","- Do not end with generic follow-up offers; deliver the requested answer directly."].join("\n"):void 0}function readRecord(e){return isRecord(e)?e:{}}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
@@ -1 +1 @@
1
- export function resolveProgressNarrator(e){if(!1===e.options)return;const t=readProgressPolicy(e.policy);return e.options?.enabled??t.enabled?e.options?.provider??function createTemplateProgressNarrator(){const e=new Map,t=new Map;return{name:"template",narrate(r,n){var o;"runtime.request.started"===r.type&&(e.set(r.requestId,{language:(o=r.input??"",/\p{Script=Han}/u.test(o)?"zh":void 0),input:r.input}),t.delete(r.requestId));const i=function templateMessage(e,t){const r="zh"===t?.language;return"runtime.request.started"===e.type?r?`我开始处理这个请求:${summarizeText(e.input)}`:`I'm starting on this request: ${summarizeText(e.input)}`:"runtime.request.completed"===e.type?r?"我已经完成执行链,正在交付最终结果。":"I've finished the execution chain and am returning the final result.":"runtime.request.failed"===e.type?r?"执行链失败了,我会保留具体错误方便定位。":"The execution chain failed; I'm keeping the concrete error visible for diagnosis.":"runtime.request.cancelled"===e.type?r?"这个请求已取消,后续执行会停止。":"The request was cancelled, so the remaining execution will stop.":"runtime.tool.direct.started"===e.type?r?`我正在运行 ${e.toolId}。`:`I'm running ${e.toolId}.`:"runtime.tool.direct.completed"===e.type?r?`${e.toolId} 已返回结果,我会继续使用这份证据。`:`${e.toolId} returned; I'll keep using that evidence.`:"runtime.workflow.started"===e.type?r?`我正在启动 workflow ${e.workflowId}。`:`I'm starting workflow ${e.workflowId}.`:"runtime.workflow.completed"===e.type?r?`workflow ${e.workflowId} 已完成。`:`Workflow ${e.workflowId} is complete.`:"runtime.specDriven.phase.started"===e.type?r?`我正在进入 spec-driven 阶段 ${e.phaseId}。`:`I'm starting spec-driven phase ${e.phaseId}.`:"runtime.specDriven.phase.blocked"===e.type?r?`spec-driven 阶段 ${e.phaseId} 被 gate 阻塞。`:`Spec-driven phase ${e.phaseId} is blocked by a gate.`:"runtime.specDriven.phase.completed"===e.type?r?`spec-driven 阶段 ${e.phaseId} 已完成。`:`Spec-driven phase ${e.phaseId} is complete.`:"runtime.specDriven.phase.verified"===e.type?r?`spec-driven 阶段 ${e.phaseId} 已验证。`:`Spec-driven phase ${e.phaseId} is verified.`:"runtime.artifact.created"===e.type?r?"我已经保存一份运行产物。":"I've saved a runtime artifact.":"runtime.execution.contract.failed"===e.type?r?"运行证据没有满足执行契约,我会进入恢复或失败路径。":"The run evidence did not satisfy the execution contract, so I'll recover or fail explicitly.":"runtime.inventory.repair"===e.type?inventoryRepairMessage(e.status,e.diagnostic.layer,r):"runtime.skill.candidate.created"===e.type?r?`我发现一个可沉淀的 skill 候选:${e.name}。`:`I found a reusable skill candidate: ${e.name}.`:e.type.startsWith("runtime.memory.")?function memoryMessage(e,t){return"runtime.memory.lifecycle"===e.type?t?`我进入记忆阶段:${e.hook}。`:`I'm in the memory lifecycle phase: ${e.hook}.`:"runtime.memory.recall.completed"===e.type?t?`我召回了 ${e.recordIds.length} 条相关记忆。`:`I recalled ${e.recordIds.length} relevant memory records.`:"runtime.memory.candidate.submitted"===e.type?t?"我提交了一条候选记忆。":"I submitted a memory candidate.":"runtime.memory.approval.requested"===e.type?t?"我提交了记忆审批请求。":"I requested memory approval.":"runtime.memory.plugin.started"===e.type?t?`我正在运行记忆插件 ${e.provider}。`:`I'm running memory plugin ${e.provider}.`:"runtime.memory.plugin.completed"===e.type?t?`记忆插件 ${e.provider} 已完成。`:`Memory plugin ${e.provider} completed.`:"runtime.memory.plugin.failed"===e.type?t?`记忆插件 ${e.provider} 失败了;主任务会继续,不把它当成执行结果。`:`Memory plugin ${e.provider} failed; the main task will continue without treating it as the result.`:"runtime.memory.maintenance.started"===e.type?t?`我正在维护 ${e.target} 记忆。`:`I'm maintaining ${e.target} memory.`:"runtime.memory.maintenance.completed"===e.type?t?`${e.target} 记忆维护完成。`:`${e.target} memory maintenance completed.`:"runtime.memory.maintenance.failed"===e.type?t?`${e.target} 记忆维护失败。`:`${e.target} memory maintenance failed.`:void 0}(e,r):"runtime.adapter.event"===e.type?function adapterMessage(e,t){if(isRecord(e)){if("agent.handoff"===e.phase)return t?"我把请求交给上游 agent backend,让它负责规划和执行。":"I'm handing the request to the upstream agent backend for planning and execution.";if(function isToolStartEvent(e){return"deepagents.tool_execution.start"===e.eventType||"agent.tool.start"===e.phase}(e)&&"string"==typeof e.toolId)return function toolStartMessage(e,t,r){if("task"===e){const e=function readTaskTarget(e){const t=isRecord(e)?e:{};return readString(t.subagent_type)??readString(t.subagentType)}(t),n=function readDescription(e){const t=isRecord(e)?e:{};return summarizeText(readString(t.description)??readString(t.task))}(t);if(e&&n)return r?`我正在请求 task 工具委派给 ${e}:${n}`:`I'm asking the task tool to delegate to ${e}: ${n}`;if(e)return r?`我正在请求 task 工具委派给 ${e}。`:`I'm asking the task tool to delegate to ${e}.`}return r?`我正在运行 ${e} 收集证据。`:`I'm running ${e} to gather evidence.`}(e.toolId,e.args,t);if(function isToolResultEvent(e){return"deepagents.tool_execution.result"===e.eventType||"agent.tool.result"===e.phase}(e)&&"string"==typeof e.toolId)return function toolResultMessage(e,t,r,n,o){if(r)return o?`${e} 返回错误:${summarizeText(String(r))}`:`${e} returned an error: ${summarizeText(String(r))}`;const i="string"==typeof n?n:function readToolControlStatus(e){const t=function parseToolOutputRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e);return"string"==typeof t?.status?t.status:"string"==typeof t?.error?t.error:"string"==typeof e&&e.startsWith("Task delegation target is not in the workspace inventory")?"task_inventory_blocked":void 0}(t);if(i)return function toolControlMessage(e,t,r){return"duplicate_tool_call"===t?r?`${e} 重复调用已复用已有证据。`:`${e} repeated an equivalent call, so the existing evidence was reused.`:"repeated_tool_call_limit"===t?r?`${e} 出现重复调用循环,我会基于已有证据继续收敛。`:`${e} entered a repeated-call loop, so I'll continue from the evidence already collected.`:"tool_argument_error"===t||"tool_argument_validation_failed"===t?r?`${e} 参数被工具 schema 拒绝,我会让 agent 修正参数或改用合适工具。`:`${e} arguments were rejected by the tool schema; I'll have the agent repair them or choose a suitable tool.`:"task_inventory_blocked"===t?r?"task 委派目标不在当前 workspace inventory 中,已被运行时策略阻止。":"The task delegation target is not in the current workspace inventory and was blocked by runtime policy.":r?`${e} 返回运行时控制状态:${t}。`:`${e} returned runtime control status: ${t}.`}(e,i,o);if("task"===e)return o?"委派任务已返回结果,我会基于这些证据继续推进。":"The delegated task returned; I'll keep going with that evidence.";const a=function summarizeToolOutput(e){if("string"==typeof e)return summarizeText(e);if(isRecord(e)){if("string"==typeof e.status)return summarizeText(e.status);if("string"==typeof e.summary)return summarizeText(e.summary)}}(t);return o?`${e} 已返回${a?`:${a}`:",我会继续判断下一步。"}`:`${e} returned${a?`: ${a}`:"; I'll decide the next step from here."}`}(e.toolId,e.output,e.error,e.controlStatus,t);if("agent.langgraph.invoke"===e.phase)return t?"我正在调用 workflow backend。":"I'm invoking the workflow backend.";if("agent.node.completed"===e.phase&&"string"==typeof e.nodeId)return t?`节点 ${e.nodeId} 已完成。`:`Node ${e.nodeId} is complete.`;if("inventory.repair"===e.phase&&"string"==typeof e.status){const r=isRecord(e.diagnostic)?e.diagnostic:{};return inventoryRepairMessage(e.status,readString(r.layer)??"selection",t)}}}(e.event,r):void 0}(r,e.get(r.requestId));if(i&&i!==t.get(r.requestId))return t.set(r.requestId,i),"runtime.request.failed"!==r.type&&"runtime.request.cancelled"!==r.type||(e.delete(r.requestId),t.delete(r.requestId)),function pruneRequestState(e,t){for(;e.size>200;){const r=e.keys().next().value;if(!r)break;e.delete(r),t.delete(r)}}(e,t),{message:i,style:n.style,model:n.model}}}}():void 0}export function createProgressNarrationEvent(e){if(!e.narrator||"runtime.progress.narration"===e.source.type)return;const t=readProgressPolicy(e.policy),r=!1===e.options?void 0:e.options,n=e.narrator.narrate(e.source,{style:r?.style??t.style,model:r?.model??t.model});return function isPromiseLike(e){return isRecord(e)&&"function"==typeof e.then}(n)?n.then(t=>toNarrationEvent(e.source,e.narrator,t)):toNarrationEvent(e.source,e.narrator,n)}export function createProgressNarrationCapability(e){const t=resolveProgressNarrator(e);if(t)return{id:"runtime.progress.narration",onEvent(r,n){try{const o=createProgressNarrationEvent({source:r,narrator:t,options:e.options,policy:e.policy});!function isRuntimeEventPromise(e){return isRecord(e)&&"function"==typeof e.then}(o)?o&&n(o):o.then(e=>{e&&n(e)}).catch(()=>{})}catch{return}}}}function toNarrationEvent(e,t,r){if(r?.message.trim())return{type:"runtime.progress.narration",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agentId,message:r.message,provider:t.name,sourceEventTypes:r.sourceEventTypes??[e.type],sourceEventIds:r.sourceEventIds??(e.eventId?[e.eventId]:void 0),model:r.model,style:r.style}}function inventoryRepairMessage(e,t,r){return"repaired"===e?r?`${t} 选择已按 workspace inventory 修正。`:`${t} selection was repaired against the workspace inventory.`:r?`${t} 选择不在 workspace inventory 中,已被阻止。`:`${t} selection was blocked because it is outside the workspace inventory.`}function summarizeText(e){const t=e?.replace(/\s+/gu," ").trim();return t?t.length>120?`${t.slice(0,117)}...`:t:""}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readProgressPolicy(e){const t=isRecord(e?.progress)?e.progress:{},r=isRecord(t.narration)?t.narration:{};return{enabled:"boolean"==typeof r.enabled?r.enabled:void 0,style:"string"==typeof r.style?r.style:void 0,model:"string"==typeof r.model?r.model:void 0}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
1
+ export function resolveProgressNarrator(e){if(!1===e.options)return;const t=readProgressPolicy(e.policy);return e.options?.enabled??t.enabled?e.options?.provider??function createTemplateProgressNarrator(){const e=new Map,t=new Map;return{name:"template",narrate(r,n){var o;"runtime.request.started"===r.type&&(e.set(r.requestId,{language:(o=r.input??"",/\p{Script=Han}/u.test(o)?"zh":void 0),input:r.input}),t.delete(r.requestId));const i=function templateMessage(e,t){const r="zh"===t?.language;return"runtime.request.started"===e.type?r?`我开始处理这个请求:${summarizeText(e.input)}`:`I'm starting on this request: ${summarizeText(e.input)}`:"runtime.request.completed"===e.type?r?"我已经完成执行链,正在交付最终结果。":"I've finished the execution chain and am returning the final result.":"runtime.request.failed"===e.type?r?"执行链失败了,我会保留具体错误方便定位。":"The execution chain failed; I'm keeping the concrete error visible for diagnosis.":"runtime.request.cancelled"===e.type?r?"这个请求已取消,后续执行会停止。":"The request was cancelled, so the remaining execution will stop.":"runtime.tool.direct.started"===e.type?r?`我正在运行 ${e.toolId}。`:`I'm running ${e.toolId}.`:"runtime.tool.direct.completed"===e.type?r?`${e.toolId} 已返回结果,我会继续使用这份证据。`:`${e.toolId} returned; I'll keep using that evidence.`:"runtime.workflow.started"===e.type?r?`我正在启动 workflow ${e.workflowId}。`:`I'm starting workflow ${e.workflowId}.`:"runtime.workflow.completed"===e.type?r?`workflow ${e.workflowId} 已完成。`:`Workflow ${e.workflowId} is complete.`:"runtime.specDriven.phase.started"===e.type?r?`我正在进入 spec-driven 阶段 ${e.phaseId}。`:`I'm starting spec-driven phase ${e.phaseId}.`:"runtime.specDriven.phase.blocked"===e.type?r?`spec-driven 阶段 ${e.phaseId} 被 gate 阻塞。`:`Spec-driven phase ${e.phaseId} is blocked by a gate.`:"runtime.specDriven.phase.completed"===e.type?r?`spec-driven 阶段 ${e.phaseId} 已完成。`:`Spec-driven phase ${e.phaseId} is complete.`:"runtime.specDriven.phase.verified"===e.type?r?`spec-driven 阶段 ${e.phaseId} 已验证。`:`Spec-driven phase ${e.phaseId} is verified.`:"runtime.artifact.created"===e.type?r?"我已经保存一份运行产物。":"I've saved a runtime artifact.":"runtime.execution.contract.failed"===e.type?r?"运行证据没有满足执行契约,我会进入恢复或失败路径。":"The run evidence did not satisfy the execution contract, so I'll recover or fail explicitly.":"runtime.repair.started"===e.type?repairMessage(e.layer,"started",r):"runtime.repair.completed"===e.type?repairMessage(e.layer,e.outcome,r):"runtime.inventory.repair"===e.type?inventoryRepairMessage(e.status,e.diagnostic.layer,r):"runtime.skill.candidate.created"===e.type?r?`我发现一个可沉淀的 skill 候选:${e.name}。`:`I found a reusable skill candidate: ${e.name}.`:e.type.startsWith("runtime.memory.")?function memoryMessage(e,t){return"runtime.memory.lifecycle"===e.type?t?`我进入记忆阶段:${e.hook}。`:`I'm in the memory lifecycle phase: ${e.hook}.`:"runtime.memory.recall.completed"===e.type?t?`我召回了 ${e.recordIds.length} 条相关记忆。`:`I recalled ${e.recordIds.length} relevant memory records.`:"runtime.memory.candidate.submitted"===e.type?t?"我提交了一条候选记忆。":"I submitted a memory candidate.":"runtime.memory.approval.requested"===e.type?t?"我提交了记忆审批请求。":"I requested memory approval.":"runtime.memory.plugin.started"===e.type?t?`我正在运行记忆插件 ${e.provider}。`:`I'm running memory plugin ${e.provider}.`:"runtime.memory.plugin.completed"===e.type?t?`记忆插件 ${e.provider} 已完成。`:`Memory plugin ${e.provider} completed.`:"runtime.memory.plugin.failed"===e.type?t?`记忆插件 ${e.provider} 失败了;主任务会继续,不把它当成执行结果。`:`Memory plugin ${e.provider} failed; the main task will continue without treating it as the result.`:"runtime.memory.maintenance.started"===e.type?t?`我正在维护 ${e.target} 记忆。`:`I'm maintaining ${e.target} memory.`:"runtime.memory.maintenance.completed"===e.type?t?`${e.target} 记忆维护完成。`:`${e.target} memory maintenance completed.`:"runtime.memory.maintenance.failed"===e.type?t?`${e.target} 记忆维护失败。`:`${e.target} memory maintenance failed.`:void 0}(e,r):"runtime.adapter.event"===e.type?function adapterMessage(e,t){if(isRecord(e)){if("agent.handoff"===e.phase)return t?"我把请求交给上游 agent backend,让它负责规划和执行。":"I'm handing the request to the upstream agent backend for planning and execution.";if(function isToolStartEvent(e){return"deepagents.tool_execution.start"===e.eventType||"agent.tool.start"===e.phase}(e)&&"string"==typeof e.toolId)return function toolStartMessage(e,t,r){if("task"===e){const e=function readTaskTarget(e){const t=isRecord(e)?e:{};return readString(t.subagent_type)??readString(t.subagentType)}(t),n=function readDescription(e){const t=isRecord(e)?e:{};return summarizeText(readString(t.description)??readString(t.task))}(t);if(e&&n)return r?`我正在请求 task 工具委派给 ${e}:${n}`:`I'm asking the task tool to delegate to ${e}: ${n}`;if(e)return r?`我正在请求 task 工具委派给 ${e}。`:`I'm asking the task tool to delegate to ${e}.`}return r?`我正在运行 ${e} 收集证据。`:`I'm running ${e} to gather evidence.`}(e.toolId,e.args,t);if(function isToolResultEvent(e){return"deepagents.tool_execution.result"===e.eventType||"agent.tool.result"===e.phase}(e)&&"string"==typeof e.toolId)return function toolResultMessage(e,t,r,n,o){if(r)return o?`${e} 返回错误:${summarizeText(String(r))}`:`${e} returned an error: ${summarizeText(String(r))}`;const i="string"==typeof n?n:function readToolControlStatus(e){const t=function parseToolOutputRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e);return"string"==typeof t?.status?t.status:"string"==typeof t?.error?t.error:"string"==typeof e&&e.startsWith("Task delegation target is not in the workspace inventory")?"task_inventory_blocked":void 0}(t);if(i)return function toolControlMessage(e,t,r){return"duplicate_tool_call"===t?r?`${e} 重复调用已复用已有证据。`:`${e} repeated an equivalent call, so the existing evidence was reused.`:"repeated_tool_call_limit"===t?r?`${e} 出现重复调用循环,我会基于已有证据继续收敛。`:`${e} entered a repeated-call loop, so I'll continue from the evidence already collected.`:"tool_argument_error"===t||"tool_argument_validation_failed"===t?r?`${e} 参数被工具 schema 拒绝,我会让 agent 修正参数或改用合适工具。`:`${e} arguments were rejected by the tool schema; I'll have the agent repair them or choose a suitable tool.`:"task_inventory_blocked"===t?r?"task 委派目标不在当前 workspace inventory 中,已被运行时策略阻止。":"The task delegation target is not in the current workspace inventory and was blocked by runtime policy.":r?`${e} 返回运行时控制状态:${t}。`:`${e} returned runtime control status: ${t}.`}(e,i,o);if("task"===e)return o?"委派任务已返回结果,我会基于这些证据继续推进。":"The delegated task returned; I'll keep going with that evidence.";const a=function summarizeToolOutput(e){if("string"==typeof e)return summarizeText(e);if(isRecord(e)){if("string"==typeof e.status)return summarizeText(e.status);if("string"==typeof e.summary)return summarizeText(e.summary)}}(t);return o?`${e} 已返回${a?`:${a}`:",我会继续判断下一步。"}`:`${e} returned${a?`: ${a}`:"; I'll decide the next step from here."}`}(e.toolId,e.output,e.error,e.controlStatus,t);if("agent.langgraph.invoke"===e.phase)return t?"我正在调用 workflow backend。":"I'm invoking the workflow backend.";if("agent.node.completed"===e.phase&&"string"==typeof e.nodeId)return t?`节点 ${e.nodeId} 已完成。`:`Node ${e.nodeId} is complete.`;if("inventory.repair"===e.phase&&"string"==typeof e.status){const r=isRecord(e.diagnostic)?e.diagnostic:{};return inventoryRepairMessage(e.status,readString(r.layer)??"selection",t)}}}(e.event,r):void 0}(r,e.get(r.requestId));if(i&&i!==t.get(r.requestId))return t.set(r.requestId,i),"runtime.request.failed"!==r.type&&"runtime.request.cancelled"!==r.type||(e.delete(r.requestId),t.delete(r.requestId)),function pruneRequestState(e,t){for(;e.size>200;){const r=e.keys().next().value;if(!r)break;e.delete(r),t.delete(r)}}(e,t),{message:i,style:n.style,model:n.model}}}}():void 0}export function createProgressNarrationEvent(e){if(!e.narrator||"runtime.progress.narration"===e.source.type)return;const t=readProgressPolicy(e.policy),r=!1===e.options?void 0:e.options,n=e.narrator.narrate(e.source,{style:r?.style??t.style,model:r?.model??t.model});return function isPromiseLike(e){return isRecord(e)&&"function"==typeof e.then}(n)?n.then(t=>toNarrationEvent(e.source,e.narrator,t)):toNarrationEvent(e.source,e.narrator,n)}export function createProgressNarrationCapability(e){const t=resolveProgressNarrator(e);if(t)return{id:"runtime.progress.narration",onEvent(r,n){try{const o=createProgressNarrationEvent({source:r,narrator:t,options:e.options,policy:e.policy});!function isRuntimeEventPromise(e){return isRecord(e)&&"function"==typeof e.then}(o)?o&&n(o):o.then(e=>{e&&n(e)}).catch(()=>{})}catch{return}}}}function toNarrationEvent(e,t,r){if(r?.message.trim())return{type:"runtime.progress.narration",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agentId,message:r.message,provider:t.name,sourceEventTypes:r.sourceEventTypes??[e.type],sourceEventIds:r.sourceEventIds??(e.eventId?[e.eventId]:void 0),model:r.model,style:r.style}}function inventoryRepairMessage(e,t,r){return"repaired"===e?r?`${t} 选择已按 workspace inventory 修正。`:`${t} selection was repaired against the workspace inventory.`:r?`${t} 选择不在 workspace inventory 中,已被阻止。`:`${t} selection was blocked because it is outside the workspace inventory.`}function repairMessage(e,t,r){return r?"started"===t?`runtime 正在执行 ${e} repair。`:"synthesized"===t?`runtime 已通过 ${e} repair 合成可交付结果。`:"blocked"===t?`runtime 已阻止 ${e} repair 的不可靠输出。`:`runtime 已完成 ${e} repair。`:"started"===t?`Runtime is starting ${e} repair.`:"synthesized"===t?`Runtime synthesized a deliverable result through ${e} repair.`:"blocked"===t?`Runtime blocked unreliable output during ${e} repair.`:`Runtime completed ${e} repair.`}function summarizeText(e){const t=e?.replace(/\s+/gu," ").trim();return t?t.length>120?`${t.slice(0,117)}...`:t:""}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readProgressPolicy(e){const t=isRecord(e?.progress)?e.progress:{},r=isRecord(t.narration)?t.narration:{};return{enabled:"boolean"==typeof r.enabled?r.enabled:void 0,style:"string"==typeof r.style?r.style:void 0,model:"string"==typeof r.model?r.model:void 0}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
@@ -0,0 +1,12 @@
1
+ import type { RuntimeEvent, RuntimeOutput, RuntimeRequest, RuntimeStore, WorkspaceAgent } from "../../types.js";
2
+ export declare function recoverAdapterResultOutput(input: {
3
+ request: RuntimeRequest;
4
+ result: RuntimeOutput;
5
+ recoveryPolicy: unknown;
6
+ store: RuntimeStore;
7
+ emit: (event: RuntimeEvent) => void;
8
+ requestId: string;
9
+ sessionId: string;
10
+ agent: WorkspaceAgent;
11
+ runAdapter: (request: RuntimeRequest) => Promise<RuntimeOutput>;
12
+ }): Promise<RuntimeOutput>;
@@ -0,0 +1 @@
1
+ import{assertNoRawToolCallOutput as e,assertNoToolExecutionErrorOutput as t,buildEvidenceSynthesisOutput as r,buildResultRecoveryRequest as o,containsRawToolCallOutput as l,rawToolCallFailureMessage as a,toolCallRecoveryEnabled as u}from"../../recovery/tool-call.js";export async function recoverAdapterResultOutput(s){let i=s.result,n=s.request;const c=function resultRecoveryAttempts(e){const t="object"!=typeof e||null===e||Array.isArray(e)?void 0:e.recovery,r="object"!=typeof t||null===t||Array.isArray(t)?void 0:t.toolCall,o="object"!=typeof r||null===r||Array.isArray(r)?void 0:r.maxResultRecoveryAttempts;return"number"==typeof o&&Number.isInteger(o)&&o>0?o:3}(s.recoveryPolicy);let y=0;for(let e=0;e<c;e+=1){const t=s.store.getRun(s.requestId)?.events??[],r=o({request:n,output:i.text,events:t.slice(y),availableToolIds:s.agent.tools,policy:s.recoveryPolicy});if(!r)break;n=r,y=s.store.getRun(s.requestId)?.events.length??0,emitRepair(s,"runtime.repair.started","result_output",e+1,"recoverable_result_output"),i=await s.runAdapter(r),emitRepair(s,"runtime.repair.completed","result_output",e+1,"recoverable_result_output","retried")}return function finalizeRecoveredOutput(o,s){if(!u(o.recoveryPolicy))return s;let i=!1;l(s.text,o.recoveryPolicy)&&function rawToolCallFailureReturnsMessage(e){return"message"===("object"!=typeof e?.toolCallRecovery||null===e.toolCallRecovery||Array.isArray(e.toolCallRecovery)?{}:e.toolCallRecovery).onFailure}(o.request.metadata)&&(s={...s,text:a(),metadata:{...s.metadata,toolCallRecovery:{failed:!0,reason:"raw_tool_call_output"}}},emitRepair(o,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked"));const n=r({request:o.request,output:s.text,events:o.store.getRun(o.requestId)?.events??[],policy:o.recoveryPolicy});return n&&(i=!0,s={...s,text:n,metadata:{...s.metadata,toolCallRecovery:{synthesized:!0,reason:"raw_tool_call_output_with_evidence"}}},emitRepair(o,"runtime.repair.completed","evidence_synthesis",void 0,"raw_tool_call_output_with_evidence","synthesized")),i||(e(s.text,o.recoveryPolicy),t(s.text,o.recoveryPolicy)),s}(s,i)}function emitRepair(e,t,r,o,l,a){const u={requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:r,attempt:o,reason:l};e.emit("runtime.repair.started"===t?{type:t,...u}:{type:t,...u,outcome:a??"retried"})}
@@ -1 +1 @@
1
- import{randomUUID as e}from"node:crypto";import{assertExecutionContract as t}from"./execution-contract.js";import{assertNoRawToolCallOutput as r,assertNoToolExecutionErrorOutput as a,buildAdapterErrorRecoveryPrompt as o,buildEvidenceSynthesisOutput as s,buildExecutionContractRecoveryRequest as n,buildResultRecoveryRequest as i,containsRawToolCallOutput as u,isRecoverableAdapterError as c,rawToolCallFailureMessage as l,toolCallRecoveryEnabled as p}from"./recovery/tool-call.js";import{recoverQualityReview as d,resolveQualityPolicy as m}from"./quality/index.js";import{completeRun as w,failRun as y}from"./runtime/completion.js";import{runDirectToolCall as f}from"./runtime/direct-tool-call.js";import{createApprovalGatedToolGateway as g}from"./runtime/governance/approval-gate.js";import{createSandboxedToolGateway as I}from"./runtime/governance/sandbox.js";import{createRuntimeInspectionMethods as q}from"./runtime/inspection/methods.js";import{createRuntimeCapabilityRegistry as R,normalizeAdapterResult as v}from"./runtime/capabilities.js";import{createMemoryRuntimeCapability as b}from"./runtime/memory.js";import{createInMemoryRuntimeStore as k}from"./runtime/persistence/stores.js";import{createProgressNarrationCapability as A}from"./runtime/progress-narration.js";import{repairRuntimeSelection as C}from"./runtime/selection-repair.js";import{createLangSmithTracingCapability as x}from"./runtime/tracing/langsmith.js";import{createToolFailureTracker as h}from"./runtime/tool-failure.js";import{runWorkflowRequest as j}from"./workflows/runtime.js";export function createStableHarnessRuntime(t){const r=new Set,a=t.store??k(),s=R([b(t),A({options:t.progressNarration,policy:t.workspace.runtime}),x({policy:t.workspace.runtime,store:a,options:t.langSmithTracing}),...t.capabilities??[]]),emitBase=t=>{const o=function enrichRuntimeEvent(t){return{...t,eventId:t.eventId??e(),emittedAt:t.emittedAt??(new Date).toISOString()}}(t);a.appendEvent(o);for(const e of r)e(o)},emit=e=>{emitBase(e),s.emitSideEffects(e,emitBase)},i=I({gateway:g({gateway:t.toolGateway,approvals:t.approvals,workspace:t.workspace,emit:emit}),workspace:t.workspace,sandbox:t.sandbox,emit:emit}),u={...t,toolGateway:i},l=h(function readToolFailurePolicy(e){if("object"!=typeof e||null===e||Array.isArray(e))return;const t=e.failurePolicy;return"object"!=typeof t||null===t||Array.isArray(t)?void 0:t}(t.workspace.runtime.toolGateway));return{request:async t=>async function runRuntimeRequest(t){const r=t.request.requestId??e(),a=t.request.sessionId??e(),s=[],{agent:i,adapter:u}=await async function resolveExecution(e,t,r){const a=t.agentId?await async function resolveRequestedAgentId(e,t,r){if(e.agents.has(t))return t;const a=await C({id:t,candidates:[...e.agents.values()].map(e=>({id:e.id,description:e.description})),trace:{...r,agentId:t,layer:"agent",owner:"stable_runtime_policy"}});return a.ok?a.id:t}(e.workspace,t.agentId,r):function resolveRoutedAgentId(e,t){for(const r of e.runtime.routes??[])if(routeMatches(r,t))return r.agentId;return e.runtime.defaultAgentId}(e.workspace,t.input),o=e.workspace.agents.get(a);if(!o)throw new Error(`Agent ${a} is not defined in the workspace`);if(t.toolCall||t.workflow)return{agent:o,adapter:void 0};const s=e.adapters.find(e=>e.canRun(o));if(!s)throw new Error(`No runtime adapter can run backend ${o.backend} for agent ${o.id}`);return{agent:o,adapter:s}}(t.input,t.request,{requestId:r,sessionId:a,emit:e=>s.push(e)});t.store.createRun(function createRunRecord(e,t,r,a){return{requestId:t,sessionId:r,agentId:a.id,input:e.input,state:"running",parentRunId:e.parentRunId,metadata:e.metadata,artifacts:[],startedAt:(new Date).toISOString(),events:[]}}(t.request,r,a,i)),s.forEach(t.emit),t.emit({type:"runtime.request.started",requestId:r,sessionId:a,agentId:i.id,input:t.request.input});try{if(t.request.workflow){const e=await j({workspace:t.input.workspace,adapters:t.input.workflowAdapters??[],toolGateway:t.input.toolGateway,request:{input:t.request.input,...t.request.workflow},requestId:r,sessionId:a,agentId:i.id,emit:t.emit});return w({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,result:e,artifacts:t.input.artifacts})}if(t.request.toolCall){const e=await f({gateway:t.input.toolGateway,workspace:t.input.workspace,emit:t.emit,request:t.request,requestId:r,sessionId:a,agent:i,toolFailureTracker:t.toolFailureTracker});return w({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,result:e,artifacts:t.input.artifacts})}return await async function runAdapterRequest(e){if(!e.adapter)throw new Error(`No runtime adapter can run backend ${e.agent.backend} for agent ${e.agent.id}`);const t=e.adapter,r=await e.capabilities.beforeAdapterRun(createCapabilityContext(e)),a=r.memory,s=r.pluginMemories??[],i=e.input.workspace.runtime,u=m(e.input.workspace.runtime,e.agent),l=new Map;let p;try{p=await runAdapterOnce(e,t,e.request,a,s,l)}catch(r){if(!c(r,i))throw r;p=await runAdapterOnce(e,t,o(e.request,r,i),a,s,l)}p=await recoverAdapterResultOutput(e,t,e.request,p,a,s,i,l),p=await d(createQualityRuntimeInput(e,a,s,l),e.request,p,u),await e.capabilities.beforeAdapterResultContract({...createCapabilityContext(e),result:p});try{assertRequestExecutionContract(e)}catch(r){const o=n({request:e.request,events:e.store.getRun(e.requestId)?.events??[],policy:i});if(!o)throw r;p=await runAdapterOnce(e,t,o,a,s,l),p=await recoverAdapterResultOutput(e,t,o,p,a,s,i,l),p=await d(createQualityRuntimeInput(e,a,s,l),o,p,u),assertRequestExecutionContract(e)}const y=w({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,result:p,artifacts:e.input.artifacts});return await e.capabilities.afterAdapterResponse({...createCapabilityContext(e),result:p,response:y}),y}({...t,adapter:u,requestId:r,sessionId:a,agent:i})}catch(e){return y({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,error:e})}}({input:u,capabilities:s,store:a,emit:emit,request:t,toolFailureTracker:l}),subscribe:e=>(r.add(e),()=>r.delete(e)),...q({workspace:t.workspace,store:a,artifacts:t.artifacts,approvals:t.approvals,emit:emit}),cancel(e,t){const r=a.getRun(e);r&&"running"===r.state&&(a.updateRun(e,{state:"cancelled",completedAt:(new Date).toISOString()}),emit({type:"runtime.request.cancelled",requestId:e,sessionId:r.sessionId,agentId:r.agentId,reason:t}))},async stop(){await s.stop(),r.clear()}}}function createCapabilityContext(e){return{workspace:e.input.workspace,store:e.store,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent}}function createQualityRuntimeInput(e,t,r,a){return{workspace:e.input.workspace,agent:e.agent,request:e.request,requestId:e.requestId,sessionId:e.sessionId,events:e.store.getRun(e.requestId)?.events??[],emit:e.emit,getEvents:()=>e.store.getRun(e.requestId)?.events??[],runAdapter:o=>runAdapterOnce(e,e.adapter,o,t,r,a),reviewModel:e.input.qualityReviewModel,memory:t,pluginMemories:r}}async function recoverAdapterResultOutput(e,t,o,n,c,d,m,w){let y=o;const f=function resultRecoveryAttempts(e){const t="object"!=typeof e||null===e||Array.isArray(e)?void 0:e.recovery,r="object"!=typeof t||null===t||Array.isArray(t)?void 0:t.toolCall,a="object"!=typeof r||null===r||Array.isArray(r)?void 0:r.maxResultRecoveryAttempts;return"number"==typeof a&&Number.isInteger(a)&&a>0?a:3}(m);let g=0;for(let r=0;r<f;r+=1){const r=e.store.getRun(e.requestId)?.events??[],a=i({request:y,output:n.text,events:r.slice(g),availableToolIds:e.agent.tools,policy:m});if(!a)break;y=a,g=e.store.getRun(e.requestId)?.events.length??0,n=await runAdapterOnce(e,t,a,c,d,w)}if(p(m)){let t=!1;u(n.text,m)&&function rawToolCallFailureReturnsMessage(e){return"message"===("object"!=typeof e?.toolCallRecovery||null===e.toolCallRecovery||Array.isArray(e.toolCallRecovery)?{}:e.toolCallRecovery).onFailure}(o.metadata)&&(n={...n,text:l(),metadata:{...n.metadata,toolCallRecovery:{failed:!0,reason:"raw_tool_call_output"}}});const i=s({request:o,output:n.text,events:e.store.getRun(e.requestId)?.events??[],policy:m});i&&(t=!0,n={...n,text:i,metadata:{...n.metadata,toolCallRecovery:{synthesized:!0,reason:"raw_tool_call_output_with_evidence"}}}),t||(r(n.text,m),a(n.text,m))}return n}function assertRequestExecutionContract(e){t({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,metadata:e.request.metadata})}async function runAdapterOnce(e,t,r,a,o,s){return v(await t.run({workspace:e.input.workspace,agent:e.agent,request:r,requestId:e.requestId,sessionId:e.sessionId,memory:a,pluginMemories:o,toolGateway:e.input.toolGateway,toolFailureTracker:e.input.toolFailureTracker,requestState:s,getEvents:()=>e.store.getRun(e.requestId)?.events??[],emit:e.emit}))}function routeMatches(e,t){if(e.pattern)try{if(new RegExp(e.pattern,"iu").test(t))return!0}catch{return!1}const r=t.toLowerCase();return(e.keywords??[]).some(e=>r.includes(e.toLowerCase()))}
1
+ import{randomUUID as e}from"node:crypto";import{assertExecutionContract as t}from"./execution-contract.js";import{buildAdapterErrorRecoveryPrompt as r,buildExecutionContractRecoveryRequest as a,isRecoverableAdapterError as s}from"./recovery/tool-call.js";import{recoverQualityReview as n,resolveQualityPolicy as o}from"./quality/index.js";import{recoverAdapterResultOutput as i}from"./runtime/recovery/adapter-result.js";import{completeRun as u,failRun as c}from"./runtime/completion.js";import{runDirectToolCall as p}from"./runtime/direct-tool-call.js";import{createApprovalGatedToolGateway as d}from"./runtime/governance/approval-gate.js";import{createSandboxedToolGateway as m}from"./runtime/governance/sandbox.js";import{createRuntimeInspectionMethods as l}from"./runtime/inspection/methods.js";import{createRuntimeCapabilityRegistry as w,normalizeAdapterResult as f}from"./runtime/capabilities.js";import{createMemoryRuntimeCapability as g}from"./runtime/memory.js";import{createInMemoryRuntimeStore as I}from"./runtime/persistence/stores.js";import{createProgressNarrationCapability as y}from"./runtime/progress-narration.js";import{repairRuntimeSelection as q}from"./runtime/selection-repair.js";import{createLangSmithTracingCapability as R}from"./runtime/tracing/langsmith.js";import{createToolFailureTracker as k}from"./runtime/tool-failure.js";import{runWorkflowRequest as v}from"./workflows/runtime.js";export function createStableHarnessRuntime(t){const f=new Set,b=t.store??I(),A=w([g(t),y({options:t.progressNarration,policy:t.workspace.runtime}),R({policy:t.workspace.runtime,store:b,options:t.langSmithTracing}),...t.capabilities??[]]),emitBase=t=>{const r=function enrichRuntimeEvent(t){return{...t,eventId:t.eventId??e(),emittedAt:t.emittedAt??(new Date).toISOString()}}(t);b.appendEvent(r);for(const e of f)e(r)},emit=e=>{emitBase(e),A.emitSideEffects(e,emitBase)},C=m({gateway:d({gateway:t.toolGateway,approvals:t.approvals,workspace:t.workspace,emit:emit}),workspace:t.workspace,sandbox:t.sandbox,emit:emit}),h={...t,toolGateway:C},x=k(function readToolFailurePolicy(e){if("object"!=typeof e||null===e||Array.isArray(e))return;const t=e.failurePolicy;return"object"!=typeof t||null===t||Array.isArray(t)?void 0:t}(t.workspace.runtime.toolGateway));return{request:async t=>async function runRuntimeRequest(t){const d=t.request.requestId??e(),m=t.request.sessionId??e(),l=[],{agent:w,adapter:f}=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 q({id:t,candidates:[...e.agents.values()].map(e=>({id:e.id,description:e.description})),trace:{...r,agentId:t,layer:"agent",owner:"stable_runtime_policy"}});return a.ok?a.id:t}(e.workspace,t.agentId,r):function resolveRoutedAgentId(e,t){for(const r of e.runtime.routes??[])if(routeMatches(r,t))return r.agentId;return e.runtime.defaultAgentId}(e.workspace,t.input),s=e.workspace.agents.get(a);if(!s)throw new Error(`Agent ${a} is not defined in the workspace`);if(t.toolCall||t.workflow)return{agent:s,adapter:void 0};const n=e.adapters.find(e=>e.canRun(s));if(!n)throw new Error(`No runtime adapter can run backend ${s.backend} for agent ${s.id}`);return{agent:s,adapter:n}}(t.input,t.request,{requestId:d,sessionId:m,emit:e=>l.push(e)});t.store.createRun(function createRunRecord(e,t,r,a){return{requestId:t,sessionId:r,agentId:a.id,input:e.input,state:"running",parentRunId:e.parentRunId,metadata:e.metadata,artifacts:[],startedAt:(new Date).toISOString(),events:[]}}(t.request,d,m,w)),l.forEach(t.emit),t.emit({type:"runtime.request.started",requestId:d,sessionId:m,agentId:w.id,input:t.request.input});try{if(t.request.workflow){const e=await v({workspace:t.input.workspace,adapters:t.input.workflowAdapters??[],toolGateway:t.input.toolGateway,request:{input:t.request.input,...t.request.workflow},requestId:d,sessionId:m,agentId:w.id,emit:t.emit});return u({store:t.store,emit:t.emit,requestId:d,sessionId:m,agent:w,result:e,artifacts:t.input.artifacts})}if(t.request.toolCall){const e=await p({gateway:t.input.toolGateway,workspace:t.input.workspace,emit:t.emit,request:t.request,requestId:d,sessionId:m,agent:w,toolFailureTracker:t.toolFailureTracker});return u({store:t.store,emit:t.emit,requestId:d,sessionId:m,agent:w,result:e,artifacts:t.input.artifacts})}return await async function runAdapterRequest(e){if(!e.adapter)throw new Error(`No runtime adapter can run backend ${e.agent.backend} for agent ${e.agent.id}`);const t=e.adapter,c=await e.capabilities.beforeAdapterRun(createCapabilityContext(e)),p=c.memory,d=c.pluginMemories??[],m=e.input.workspace.runtime,l=o(e.input.workspace.runtime,e.agent),w=new Map;let f;try{f=await runAdapterOnce(e,t,e.request,p,d,w)}catch(a){if(!s(a,m))throw a;e.emit(repairStarted(e,"adapter_error",1,errorMessage(a))),f=await runAdapterOnce(e,t,r(e.request,a,m),p,d,w),e.emit(repairCompleted(e,"adapter_error","retried",1,errorMessage(a)))}f=await i({...e,request:e.request,result:f,recoveryPolicy:m,runAdapter:r=>runAdapterOnce(e,t,r,p,d,w)}),f=await n(createQualityRuntimeInput(e,p,d,w),e.request,f,l),await e.capabilities.beforeAdapterResultContract({...createCapabilityContext(e),result:f});try{assertRequestExecutionContract(e)}catch(r){const s=a({request:e.request,events:e.store.getRun(e.requestId)?.events??[],policy:m});if(!s)throw r;e.emit(repairStarted(e,"execution_contract",1,errorMessage(r))),f=await runAdapterOnce(e,t,s,p,d,w),f=await i({...e,request:s,result:f,recoveryPolicy:m,runAdapter:r=>runAdapterOnce(e,t,r,p,d,w)}),f=await n(createQualityRuntimeInput(e,p,d,w),s,f,l),assertRequestExecutionContract(e),e.emit(repairCompleted(e,"execution_contract","retried",1,errorMessage(r)))}const g=u({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,result:f,artifacts:e.input.artifacts});return await e.capabilities.afterAdapterResponse({...createCapabilityContext(e),result:f,response:g}),g}({...t,adapter:f,requestId:d,sessionId:m,agent:w})}catch(e){return c({store:t.store,emit:t.emit,requestId:d,sessionId:m,agent:w,error:e})}}({input:h,capabilities:A,store:b,emit:emit,request:t,toolFailureTracker:x}),subscribe:e=>(f.add(e),()=>f.delete(e)),...l({workspace:t.workspace,store:b,artifacts:t.artifacts,approvals:t.approvals,emit:emit}),cancel(e,t){const r=b.getRun(e);r&&"running"===r.state&&(b.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 A.stop(),f.clear()}}}function createCapabilityContext(e){return{workspace:e.input.workspace,store:e.store,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent}}function createQualityRuntimeInput(e,t,r,a){return{workspace:e.input.workspace,agent:e.agent,request:e.request,requestId:e.requestId,sessionId:e.sessionId,events:e.store.getRun(e.requestId)?.events??[],emit:e.emit,getEvents:()=>e.store.getRun(e.requestId)?.events??[],runAdapter:s=>runAdapterOnce(e,e.adapter,s,t,r,a),reviewModel:e.input.qualityReviewModel,memory:t,pluginMemories:r}}function assertRequestExecutionContract(e){t({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,metadata:e.request.metadata})}async function runAdapterOnce(e,t,r,a,s,n){return f(await t.run({workspace:e.input.workspace,agent:e.agent,request:r,requestId:e.requestId,sessionId:e.sessionId,memory:a,pluginMemories:s,toolGateway:e.input.toolGateway,toolFailureTracker:e.input.toolFailureTracker,requestState:n,getEvents:()=>e.store.getRun(e.requestId)?.events??[],emit: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}}function repairCompleted(e,t,r,a,s){return{type:"runtime.repair.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:t,outcome:r,attempt:a,reason:s}}function errorMessage(e){return e instanceof Error?e.message:String(e)}function routeMatches(e,t){if(e.pattern)try{if(new RegExp(e.pattern,"iu").test(t))return!0}catch{return!1}const r=t.toLowerCase();return(e.keywords??[]).some(e=>r.includes(e.toLowerCase()))}
@@ -1 +1 @@
1
- export function createDelegationTraceProjection(e,t={}){return{traceType:"delegation",traceLabel:e,...t}}export function createPlanTraceProjection(e,t={}){return{traceType:"plan",traceLabel:e,...t}}export function projectRuntimeTrace(e){return e.events.map(projectEvent).filter(isTraceEntry)}export function projectRuntimeTraceSpans(e){const t=function createSpanBuilder(e){const t=`run:${e.requestId}`,r=[],o=new Map;return{ensureRoot(){if(o.has(t))return;const n={spanId:t,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agentId,kind:"run",name:e.agentId,status:(a=e.state,"completed"===a?"completed":"failed"===a?"failed":"cancelled"===a?"blocked":"running"),startedAt:e.startedAt,completedAt:e.completedAt,startEventIndex:0,...e.parentRunId?{parentSpanId:`run:${e.parentRunId}`}:{},events:[]};var a;r.push(n),o.set(t,n)},markRoot(e,r,n,a){const i=o.get(t);i&&(addEvent(i,e,r),i.status=n,i.attributes=merge(i.attributes,a),"running"!==n&&close(i,e,r))},start(e,n,a,i,s,d){const p=createSpan(`${t}/${e}:${s}`,t,n,a,i,s,d);r.push(p),o.set(e,p)},complete(e,n,a,i){const s=o.get(e)??createSpan(`${t}/${e}:${a}`,t,"adapter",e,n,a);return o.has(e)||r.push(s),addEvent(s,n,a),s.attributes=merge(s.attributes,i),close(s,n,a),o.delete(e),s},fail(e,t,r,o){this.complete(e,t,r,o).status="failed"},event(e,o,n,a,i){const s=createSpan(`${t}/event:${a}`,t,e,o,n,a,i);s.status=function readBlockedStatus(e){return e.type.endsWith(".blocked")||e.type.includes(".approval.")?"blocked":void 0}(n)??"event",close(s,n,a),r.push(s)},closeRoot(){const r=o.get(t);r&&e.completedAt&&(r.completedAt=e.completedAt)},spans:()=>r}}(e);return t.ensureRoot(),e.events.forEach((e,r)=>function projectSpanEvent(e,t,r){return t.type.startsWith("runtime.request.")?function projectRequestSpanEvent(e,t,r){return"runtime.request.started"===t.type?e.markRoot(t,r,"running",{input:t.input}):"runtime.request.completed"===t.type?e.markRoot(t,r,"completed",{output:t.output}):"runtime.request.failed"===t.type?e.markRoot(t,r,"failed",{error:t.error}):"runtime.request.cancelled"===t.type?e.markRoot(t,r,"blocked",{reason:t.reason}):"runtime.execution.contract.failed"===t.type?projectSingleSpan(e,t,r,"quality",t.type,{reason:t.reason,missingEvidenceTools:t.missingEvidenceTools}):void 0}(e,t,r):"runtime.tool.direct.started"===t.type?e.start(`tool:${t.toolId}`,"tool",t.toolId,t,r,{toolId:t.toolId}):"runtime.tool.direct.completed"===t.type?e.complete(`tool:${t.toolId}`,t,r,{toolId:t.toolId,output:t.output}):"runtime.workflow.started"===t.type?e.start(`workflow:${t.workflowId}`,"workflow",t.workflowId,t,r,{workflowId:t.workflowId,adapter:t.adapter}):"runtime.workflow.completed"===t.type?e.complete(`workflow:${t.workflowId}`,t,r,{workflowId:t.workflowId,adapter:t.adapter}):t.type.startsWith("runtime.approval.")||t.type.startsWith("runtime.memory.approval.")?projectSingleSpan(e,t,r,"approval",t.type):t.type.startsWith("runtime.specDriven.phase.")?projectSingleSpan(e,t,r,"spec",function readPhaseName(e,t){return"phaseId"in e&&"string"==typeof e.phaseId?e.phaseId:t}(t,"phase")):t.type.startsWith("runtime.memory.")?projectSingleSpan(e,t,r,"memory",t.type):t.type.startsWith("runtime.quality.")?projectSingleSpan(e,t,r,"quality",t.type):"runtime.artifact.created"===t.type?projectSingleSpan(e,t,r,"artifact",t.artifact.id,{artifact:t.artifact}):"runtime.progress.narration"===t.type?projectSingleSpan(e,t,r,"progress",t.message,{provider:t.provider}):"runtime.adapter.event"===t.type?function projectAdapterSpanEvent(e,t,r){const o=isRecord(t.event)?t.event:void 0,n=readString(o?.phase)??"runtime.adapter.event",a=readTraceType(o?.traceType),i=readString(o?.traceLabel);return"delegation"===a&&i?.endsWith(".start")?e.start(delegationKey(o),"delegation",readString(o?.subagentType)??i,t,r,o):"delegation"===a&&i?.endsWith(".completed")?e.complete(delegationKey(o),t,r,o):"plan"===a&&i?projectSingleSpan(e,t,r,"plan",i,o):function isToolStartEvent(e){return"deepagents.tool_execution.start"===e?.eventType||"agent.tool.start"===e?.phase}(o)?e.start(`agent-tool:${readString(o?.toolId)??"unknown"}`,"tool",readString(o?.toolId)??n,t,r,o):function isToolResultEvent(e){return"deepagents.tool_execution.result"===e?.eventType||"agent.tool.result"===e?.phase}(o)?e.complete(`agent-tool:${readString(o?.toolId)??"unknown"}`,t,r,o):projectSingleSpan(e,t,r,"adapter",n,o)}(e,t,r):"runtime.inventory.repair"===t.type?projectSingleSpan(e,t,r,"adapter","runtime.inventory.repair",{status:t.status,...t.diagnostic}):"runtime.sandbox.decision"===t.type?projectSingleSpan(e,t,r,"tool",`sandbox:${t.toolId}`,{toolId:t.toolId,...t.decision}):"runtime.tool.failure"===t.type?e.fail(`tool:${t.toolId}`,t,r,{toolId:t.toolId,...t.failure}):"runtime.tool.circuit.opened"===t.type?projectSingleSpan(e,t,r,"tool",`circuit:${t.toolId}`,{toolId:t.toolId,reason:t.reason}):void 0}(t,e,r)),t.closeRoot(),t.spans()}export function projectEvent(e){return"runtime.request.started"===e.type||"runtime.request.completed"===e.type||"runtime.request.failed"===e.type?base(e,"request",e.type):"runtime.request.cancelled"===e.type?base(e,"request",e.type,{reason:e.reason}):"runtime.execution.contract.failed"===e.type?base(e,"request",e.type,{reason:e.reason,missingEvidenceTools:e.missingEvidenceTools}):"runtime.inventory.repair"===e.type?base(e,"adapter","runtime.inventory.repair",{status:e.status,...e.diagnostic}):"runtime.tool.direct.started"===e.type?base(e,"tool","runtime.tool.direct.started",{toolId:e.toolId}):"runtime.tool.direct.completed"===e.type?base(e,"tool","runtime.tool.direct.completed",{toolId:e.toolId}):"runtime.sandbox.decision"===e.type?base(e,"tool","runtime.sandbox.decision",{toolId:e.toolId,...e.decision}):"runtime.tool.failure"===e.type?base(e,"tool","runtime.tool.failure",{toolId:e.toolId,...e.failure}):"runtime.tool.circuit.opened"===e.type?base(e,"tool","runtime.tool.circuit.opened",{toolId:e.toolId,reason:e.reason}):"runtime.workflow.started"===e.type||"runtime.workflow.completed"===e.type?base(e,"workflow",e.type,{workflowId:e.workflowId,adapter:e.adapter}):function isSpecDrivenPhaseEvent(e){return e.type.startsWith("runtime.specDriven.phase.")}(e)?base(e,"spec",e.type,{phaseId:e.phaseId,..."workflowId"in e&&e.workflowId?{workflowId:e.workflowId}:{},..."reason"in e?{reason:e.reason}:{},..."artifact"in e&&e.artifact?{artifact:e.artifact}:{}}):"runtime.adapter.event"===e.type?function adapterTrace(e){const t=e.event;if(isRecord(t)&&"string"==typeof t.phase){const r=function semanticAdapterTrace(e,t){if("inventory.repair"===t.phase)return base(e,"adapter","runtime.inventory.repair",{status:t.status,...isRecord(t.diagnostic)?t.diagnostic:{}});const r=readTraceType(t.traceType),o=readString(t.traceLabel);return r&&o?base(e,r,o,t):void 0}(e,t);return r||base(e,"adapter",t.phase.startsWith("agent.")?t.phase:`adapter.${t.phase}`,t)}return base(e,"adapter","runtime.adapter.event",{event:t})}(e):"runtime.artifact.created"===e.type?base(e,"artifact","runtime.artifact.created",{artifact:e.artifact}):e.type.startsWith("runtime.memory.")?base(e,"memory",e.type):"runtime.progress.narration"===e.type?base(e,"progress",e.type,{message:e.message,provider:e.provider,sourceEventTypes:e.sourceEventTypes}):void 0}export function readPlanTodos(e){const t=function readPlanRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e),r=function readTodosArray(e){const t=isRecord(e?.args)?e.args:void 0;return Array.isArray(e?.todos)?e.todos:Array.isArray(t?.todos)?t.todos:[]}(t);return r.map(readTodo).filter(isPlanTodoItem)}function readTodo(e){if(isRecord(e)&&"string"==typeof e.content)return{content:e.content,status:"string"==typeof e.status?e.status:"pending"}}function isPlanTodoItem(e){return void 0!==e}function base(e,t,r,o){return{type:t,label:r,agentId:e.agentId,requestId:e.requestId,detail:o}}function isTraceEntry(e){return void 0!==e}function projectSingleSpan(e,t,r,o,n,a){return e.event(o,n,t,r,a)}function delegationKey(e){return`delegation:${readString(e?.subagentType)??readString(e?.toolId)??"task"}`}function createSpan(e,t,r,o,n,a,i){const s={spanId:e,parentSpanId:t,requestId:n.requestId,sessionId:n.sessionId,agentId:n.agentId,kind:r,name:o,status:"running",startedAt:n.emittedAt,startEventIndex:a,attributes:i,events:[]};return addEvent(s,n,a),s}function addEvent(e,t,r){e.events.push({index:r,eventId:t.eventId??`${t.requestId}:${r}`,type:t.type,emittedAt:t.emittedAt})}function close(e,t,r){e.status="failed"===e.status||"blocked"===e.status?e.status:"completed",e.completedAt=t.emittedAt,e.endEventIndex=r,e.durationMs=function durationMs(e,t){if(!e||!t)return;const r=Date.parse(t)-Date.parse(e);return Number.isFinite(r)&&r>=0?r:void 0}(e.startedAt,e.completedAt)}function merge(e,t){return t?{...e,...t}:e}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readTraceType(e){const t=readString(e);return"request"===t||"tool"===t||"workflow"===t||"spec"===t||"adapter"===t||"memory"===t||"artifact"===t||"progress"===t||"plan"===t||"delegation"===t?t:void 0}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}
1
+ export function createDelegationTraceProjection(e,t={}){return{traceType:"delegation",traceLabel:e,...t}}export function createPlanTraceProjection(e,t={}){return{traceType:"plan",traceLabel:e,...t}}export function projectRuntimeTrace(e){return e.events.map(projectEvent).filter(isTraceEntry)}export function projectRuntimeTraceSpans(e){const t=function createSpanBuilder(e){const t=`run:${e.requestId}`,r=[],o=new Map;return{ensureRoot(){if(o.has(t))return;const n={spanId:t,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agentId,kind:"run",name:e.agentId,status:(a=e.state,"completed"===a?"completed":"failed"===a?"failed":"cancelled"===a?"blocked":"running"),startedAt:e.startedAt,completedAt:e.completedAt,startEventIndex:0,...e.parentRunId?{parentSpanId:`run:${e.parentRunId}`}:{},events:[]};var a;r.push(n),o.set(t,n)},markRoot(e,r,n,a){const i=o.get(t);i&&(addEvent(i,e,r),i.status=n,i.attributes=merge(i.attributes,a),"running"!==n&&close(i,e,r))},start(e,n,a,i,s,d){const p=createSpan(`${t}/${e}:${s}`,t,n,a,i,s,d);r.push(p),o.set(e,p)},complete(e,n,a,i){const s=o.get(e)??createSpan(`${t}/${e}:${a}`,t,"adapter",e,n,a);return o.has(e)||r.push(s),addEvent(s,n,a),s.attributes=merge(s.attributes,i),close(s,n,a),o.delete(e),s},fail(e,t,r,o){this.complete(e,t,r,o).status="failed"},event(e,o,n,a,i){const s=createSpan(`${t}/event:${a}`,t,e,o,n,a,i);s.status=function readBlockedStatus(e){return e.type.endsWith(".blocked")||e.type.includes(".approval.")?"blocked":void 0}(n)??"event",close(s,n,a),r.push(s)},closeRoot(){const r=o.get(t);r&&e.completedAt&&(r.completedAt=e.completedAt)},spans:()=>r}}(e);return t.ensureRoot(),e.events.forEach((e,r)=>function projectSpanEvent(e,t,r){return t.type.startsWith("runtime.request.")?function projectRequestSpanEvent(e,t,r){return"runtime.request.started"===t.type?e.markRoot(t,r,"running",{input:t.input}):"runtime.request.completed"===t.type?e.markRoot(t,r,"completed",{output:t.output}):"runtime.request.failed"===t.type?e.markRoot(t,r,"failed",{error:t.error}):"runtime.request.cancelled"===t.type?e.markRoot(t,r,"blocked",{reason:t.reason}):"runtime.execution.contract.failed"===t.type?projectSingleSpan(e,t,r,"quality",t.type,{reason:t.reason,missingEvidenceTools:t.missingEvidenceTools}):void 0}(e,t,r):"runtime.tool.direct.started"===t.type?e.start(`tool:${t.toolId}`,"tool",t.toolId,t,r,{toolId:t.toolId}):"runtime.tool.direct.completed"===t.type?e.complete(`tool:${t.toolId}`,t,r,{toolId:t.toolId,output:t.output}):"runtime.workflow.started"===t.type?e.start(`workflow:${t.workflowId}`,"workflow",t.workflowId,t,r,{workflowId:t.workflowId,adapter:t.adapter}):"runtime.workflow.completed"===t.type?e.complete(`workflow:${t.workflowId}`,t,r,{workflowId:t.workflowId,adapter:t.adapter}):t.type.startsWith("runtime.approval.")||t.type.startsWith("runtime.memory.approval.")?projectSingleSpan(e,t,r,"approval",t.type):t.type.startsWith("runtime.specDriven.phase.")?projectSingleSpan(e,t,r,"spec",function readPhaseName(e,t){return"phaseId"in e&&"string"==typeof e.phaseId?e.phaseId:t}(t,"phase")):t.type.startsWith("runtime.memory.")?projectSingleSpan(e,t,r,"memory",t.type):t.type.startsWith("runtime.quality.")?projectSingleSpan(e,t,r,"quality",t.type):t.type.startsWith("runtime.repair.")?projectSingleSpan(e,t,r,"adapter",t.type):"runtime.artifact.created"===t.type?projectSingleSpan(e,t,r,"artifact",t.artifact.id,{artifact:t.artifact}):"runtime.progress.narration"===t.type?projectSingleSpan(e,t,r,"progress",t.message,{provider:t.provider}):"runtime.adapter.event"===t.type?function projectAdapterSpanEvent(e,t,r){const o=isRecord(t.event)?t.event:void 0,n=readString(o?.phase)??"runtime.adapter.event",a=readTraceType(o?.traceType),i=readString(o?.traceLabel);return"delegation"===a&&i?.endsWith(".start")?e.start(delegationKey(o),"delegation",readString(o?.subagentType)??i,t,r,o):"delegation"===a&&i?.endsWith(".completed")?e.complete(delegationKey(o),t,r,o):"plan"===a&&i?projectSingleSpan(e,t,r,"plan",i,o):function isToolStartEvent(e){return"deepagents.tool_execution.start"===e?.eventType||"agent.tool.start"===e?.phase}(o)?e.start(`agent-tool:${readString(o?.toolId)??"unknown"}`,"tool",readString(o?.toolId)??n,t,r,o):function isToolResultEvent(e){return"deepagents.tool_execution.result"===e?.eventType||"agent.tool.result"===e?.phase}(o)?e.complete(`agent-tool:${readString(o?.toolId)??"unknown"}`,t,r,o):projectSingleSpan(e,t,r,"adapter",n,o)}(e,t,r):"runtime.inventory.repair"===t.type?projectSingleSpan(e,t,r,"adapter","runtime.inventory.repair",{status:t.status,...t.diagnostic}):"runtime.sandbox.decision"===t.type?projectSingleSpan(e,t,r,"tool",`sandbox:${t.toolId}`,{toolId:t.toolId,...t.decision}):"runtime.tool.failure"===t.type?e.fail(`tool:${t.toolId}`,t,r,{toolId:t.toolId,...t.failure}):"runtime.tool.circuit.opened"===t.type?projectSingleSpan(e,t,r,"tool",`circuit:${t.toolId}`,{toolId:t.toolId,reason:t.reason}):void 0}(t,e,r)),t.closeRoot(),t.spans()}export function projectEvent(e){return"runtime.request.started"===e.type||"runtime.request.completed"===e.type||"runtime.request.failed"===e.type?base(e,"request",e.type):"runtime.request.cancelled"===e.type?base(e,"request",e.type,{reason:e.reason}):"runtime.execution.contract.failed"===e.type?base(e,"request",e.type,{reason:e.reason,missingEvidenceTools:e.missingEvidenceTools}):"runtime.inventory.repair"===e.type?base(e,"adapter","runtime.inventory.repair",{status:e.status,...e.diagnostic}):"runtime.repair.started"===e.type||"runtime.repair.completed"===e.type?base(e,"adapter",e.type,{layer:e.layer,..."outcome"in e?{outcome:e.outcome}:{},..."attempt"in e?{attempt:e.attempt}:{},..."reason"in e?{reason:e.reason}:{}}):"runtime.tool.direct.started"===e.type?base(e,"tool","runtime.tool.direct.started",{toolId:e.toolId}):"runtime.tool.direct.completed"===e.type?base(e,"tool","runtime.tool.direct.completed",{toolId:e.toolId}):"runtime.sandbox.decision"===e.type?base(e,"tool","runtime.sandbox.decision",{toolId:e.toolId,...e.decision}):"runtime.tool.failure"===e.type?base(e,"tool","runtime.tool.failure",{toolId:e.toolId,...e.failure}):"runtime.tool.circuit.opened"===e.type?base(e,"tool","runtime.tool.circuit.opened",{toolId:e.toolId,reason:e.reason}):"runtime.workflow.started"===e.type||"runtime.workflow.completed"===e.type?base(e,"workflow",e.type,{workflowId:e.workflowId,adapter:e.adapter}):function isSpecDrivenPhaseEvent(e){return e.type.startsWith("runtime.specDriven.phase.")}(e)?base(e,"spec",e.type,{phaseId:e.phaseId,..."workflowId"in e&&e.workflowId?{workflowId:e.workflowId}:{},..."reason"in e?{reason:e.reason}:{},..."artifact"in e&&e.artifact?{artifact:e.artifact}:{}}):"runtime.adapter.event"===e.type?function adapterTrace(e){const t=e.event;if(isRecord(t)&&"string"==typeof t.phase){const r=function semanticAdapterTrace(e,t){if("inventory.repair"===t.phase)return base(e,"adapter","runtime.inventory.repair",{status:t.status,...isRecord(t.diagnostic)?t.diagnostic:{}});const r=readTraceType(t.traceType),o=readString(t.traceLabel);return r&&o?base(e,r,o,t):void 0}(e,t);return r||base(e,"adapter",t.phase.startsWith("agent.")?t.phase:`adapter.${t.phase}`,t)}return base(e,"adapter","runtime.adapter.event",{event:t})}(e):"runtime.artifact.created"===e.type?base(e,"artifact","runtime.artifact.created",{artifact:e.artifact}):e.type.startsWith("runtime.memory.")?base(e,"memory",e.type):"runtime.progress.narration"===e.type?base(e,"progress",e.type,{message:e.message,provider:e.provider,sourceEventTypes:e.sourceEventTypes}):void 0}export function readPlanTodos(e){const t=function readPlanRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e),r=function readTodosArray(e){const t=isRecord(e?.args)?e.args:void 0;return Array.isArray(e?.todos)?e.todos:Array.isArray(t?.todos)?t.todos:[]}(t);return r.map(readTodo).filter(isPlanTodoItem)}function readTodo(e){if(isRecord(e)&&"string"==typeof e.content)return{content:e.content,status:"string"==typeof e.status?e.status:"pending"}}function isPlanTodoItem(e){return void 0!==e}function base(e,t,r,o){return{type:t,label:r,agentId:e.agentId,requestId:e.requestId,detail:o}}function isTraceEntry(e){return void 0!==e}function projectSingleSpan(e,t,r,o,n,a){return e.event(o,n,t,r,a)}function delegationKey(e){return`delegation:${readString(e?.subagentType)??readString(e?.toolId)??"task"}`}function createSpan(e,t,r,o,n,a,i){const s={spanId:e,parentSpanId:t,requestId:n.requestId,sessionId:n.sessionId,agentId:n.agentId,kind:r,name:o,status:"running",startedAt:n.emittedAt,startEventIndex:a,attributes:i,events:[]};return addEvent(s,n,a),s}function addEvent(e,t,r){e.events.push({index:r,eventId:t.eventId??`${t.requestId}:${r}`,type:t.type,emittedAt:t.emittedAt})}function close(e,t,r){e.status="failed"===e.status||"blocked"===e.status?e.status:"completed",e.completedAt=t.emittedAt,e.endEventIndex=r,e.durationMs=function durationMs(e,t){if(!e||!t)return;const r=Date.parse(t)-Date.parse(e);return Number.isFinite(r)&&r>=0?r:void 0}(e.startedAt,e.completedAt)}function merge(e,t){return t?{...e,...t}:e}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readTraceType(e){const t=readString(e);return"request"===t||"tool"===t||"workflow"===t||"spec"===t||"adapter"===t||"memory"===t||"artifact"===t||"progress"===t||"plan"===t||"delegation"===t?t:void 0}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stable-harness",
3
- "version": "0.0.49",
3
+ "version": "0.0.51",
4
4
  "type": "module",
5
5
  "description": "Stable application runtime and operator control plane for agent workspaces.",
6
6
  "license": "Apache-2.0",
@@ -1 +1 @@
1
- import{realpathSync as e}from"node:fs";import t from"node:path";import{buildRuntimeSystemPrompt as r}from"@stable-harness/core";import{createBuiltinToolPolicyMiddleware as n,createObserverMiddleware as o}from"./internal/builtin-tool-policy.js";import{resolveFilesystemPermissions as s}from"./internal/builtin/permissions.js";import{createToolRepeatState as a}from"@stable-harness/core";import{buildGatewayTools as i,stringifyDeepAgentResult as p}from"./internal/gateway-tools.js";import{resolveDeepAgentsNativeMemories as d}from"./memory.js";import{buildDeepAgentRequest as c}from"./internal/messages.js";import{createRawToolCallParserMiddleware as l}from"./internal/raw-tool-call-parser.js";import{createBackendModel as u}from"./model-providers.js";import{createDeepAgentsRetryMiddleware as m}from"./retry-policy.js";import{streamDeepAgentResult as g}from"./internal/stream-events.js";export function createDeepAgentsAdapter(e={}){return{name:"deepagents",canRun:e=>"deepagents"===e.backend,async run(t){if(t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",phase:"agent.handoff",modelRef:t.agent.modelRef,tools:t.agent.tools,subagents:t.agent.subagents}}),e.runner)return e.runner(t);const r=e.createDeepAgent?void 0:await async function loadDeepAgentsModule(){try{return await async function importOptionalPackage(e){return import(e)}("deepagents")}catch(e){throw new Error(`DeepAgents package is required for the default adapter path: ${function formatError(e){return e instanceof Error?e.message:String(e)}(e)}`)}}(),n=e.createDeepAgent??function readCreateDeepAgent(e){const t=e?.createDeepAgent;if("function"==typeof t)return t;throw new Error("DeepAgents package does not export createDeepAgent.")}(r),o=n(function buildDeepAgentParams(e,t,r){const n={...readDeepAgentsConfig(t),...readDeepAgentsConfig(e.agent.config.deepagents)},o=resolveDeepAgentsSkills(e,e.agent),a=n.permissions??s(e,e.agent),p=requestScopedRepeatState(e,e.agent.id);return pruneUndefined({name:e.agent.id,model:n.model??resolveAgentModel(e,e.agent),systemPrompt:buildSystemPrompt(e,e.agent),backend:n.backend??resolveDeepAgentsBackend(e,r,o),checkpointer:n.checkpointer,store:n.store,middleware:mergeMiddleware(e,e.agent,n.middleware,p),responseFormat:n.responseFormat,contextSchema:n.contextSchema,interruptOn:n.interruptOn,generalPurposeAgent:readBoolean(n.generalPurposeAgent),taskDescription:readString(n.taskDescription),permissions:a,tools:i(e,e.agent.id,e.agent.tools,resolveAgentRepairModel(e,e.agent,n),p),subagents:e.agent.subagents.map(t=>{const r=e.workspace.agents.get(t),n=readDeepAgentsConfig(r?.config.deepagents),o=n.permissions??s(e,r),a=scopedInput(e,r),p=requestScopedRepeatState(e,t);return pruneUndefined({name:t,description:r?.description??readString(r?.config.description)??r?.id,systemPrompt:buildSystemPrompt(e,r),model:n.model??(r?resolveAgentModel(e,r):void 0),middleware:mergeMiddleware(a,r,n.middleware,p),interruptOn:n.interruptOn,generalPurposeAgent:readBoolean(n.generalPurposeAgent),taskDescription:readString(n.taskDescription),permissions:o,responseFormat:n.responseFormat,tools:i(e,t,r?.tools??[],resolveAgentRepairModel(a,r,n),p),memory:resolveDeepAgentsMemory(e,r),skills:resolveDeepAgentsSkills(e,r)})}),memory:resolveDeepAgentsMemory(e,e.agent),skills:o})}(t,e.config,r)),a=c(t),d=function buildDeepAgentInvokeConfig(e){return pruneUndefined({recursionLimit:readNumber(readDeepAgentsConfig(e.config.deepagents).recursionLimit)??readNumber(e.config.recursionLimit)})}(t.agent);if(!0===t.request.metadata?.openaiStream&&o.streamEvents){const e=await o.streamEvents(a,{version:"v3",...d});return g(t,e,p)}const l=await o.invoke(a,d);return p(l)}}}function buildSystemPrompt(e,t){const n=t?.systemPrompt??readString(t?.config.systemPrompt);return r({workspace:e.workspace,request:e.request,agent:t},n)}function resolveDeepAgentsMemory(e,t){const r=readDeepAgentsStringArray(t?.config,"memory");if(r)return r;const n=[...readAgentMemorySources(e.workspace.root,t),...d(e.workspace).map(e=>`/memories/${e.id}.md`)],o=[...new Set(n)];return o.length>0?o:void 0}function readAgentMemorySources(e,t){return(t?.memory??[]).flatMap(t=>"string"==typeof t&&t.trim()?[backendMemorySourcePath(e,t.trim())]:isRecord(t)&&"string"==typeof t.path&&t.path.trim()?[backendMemorySourcePath(e,t.path.trim())]:[])}function backendMemorySourcePath(e,r){if(r.startsWith("/"))return r;if(t.isAbsolute(r)){const n=t.relative(e,r);return n&&!n.startsWith("..")?`/${n.split(t.sep).join("/")}`:canonicalPath(r)}const n=r.split(t.sep).join("/");return n.startsWith("/")?n:`/${n}`}function resolveDeepAgentsSkills(e,r){const n=readDeepAgentsStringArray(r?.config,"skills");if(n)return n;const o=[...new Set((r?.skills??[]).map(t=>e.workspace.skills.get(t)?.path).filter(e=>"string"==typeof e&&e.trim().length>0).map(r=>function backendSkillSourcePath(e,r){const n=t.dirname(t.dirname(r)),o=t.relative(e,n);return!o||o.startsWith("..")||t.isAbsolute(o)?""===o?"/":canonicalPath(n):`/${o.split(t.sep).join("/")}`}(e.workspace.root,r)))];return o.length>0?o:void 0}function resolveDeepAgentsBackend(e,t,r){if(t?.FilesystemBackend&&r&&0!==r.length)return()=>new t.FilesystemBackend({rootDir:e.workspace.root})}function mergeMiddleware(e,t,r,s=a(e.workspace.runtime.toolGateway)){const i=Array.isArray(r)?r:[],p=scopedInput(e,t),d=new Set,c=readDeepAgentsConfig(t?.config.deepagents);return[o(p,{observedToolIds:d,repeatState:s,repairModel:resolveAgentRepairModel(p,t,c)}),n(p,{repeatState:s}),...m(e.workspace.runtime.retry),...i,l(p)]}function requestScopedRepeatState(e,t){const r=`deepagents.repeat.${t}`,n=e.requestState?.get(r);if(n)return n;const o=a(e.workspace.runtime.toolGateway);return e.requestState&&o&&e.requestState.set(r,o),o}function scopedInput(e,t){return t?{...e,agent:t}:e}function resolveAgentModel(e,t){const r=t.modelRef?e.workspace.models.get(t.modelRef):void 0;return r?u(r):void 0}function resolveAgentRepairModel(e,t,r){const n=r.model;if(isRepairModel(n))return n;if(!t)return;const o=resolveAgentModel(e,t);return isRepairModel(o)?o:void 0}function readDeepAgentsConfig(e){return isRecord(e)?e:{}}function readDeepAgentsStringArray(e,t){const r=isRecord(e)?e:{},n=readDeepAgentsConfig(r.deepagents),o="memory"===t?["memory","memorySources"]:["skills","skillSources"];for(const e of o){const t=readStringArray(n[e]);if(t)return t}return readStringArray(r[t])}function pruneUndefined(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>void 0!==e))}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readNumber(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function readBoolean(e){return"boolean"==typeof e?e:void 0}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e):void 0}function canonicalPath(t){try{return e.native(t)}catch{return t}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function isRepairModel(e){return"object"==typeof e&&null!==e&&"invoke"in e&&"function"==typeof e.invoke}
1
+ import{realpathSync as e}from"node:fs";import t from"node:path";import{buildRuntimeSystemPrompt as r}from"@stable-harness/core";import{createBuiltinToolPolicyMiddleware as n,createObserverMiddleware as o}from"./internal/builtin-tool-policy.js";import{resolveFilesystemPermissions as s}from"./internal/builtin/permissions.js";import{createToolRepeatState as a}from"@stable-harness/core";import{buildGatewayTools as i,stringifyDeepAgentResult as p}from"./internal/gateway-tools.js";import{resolveDeepAgentsNativeMemories as d}from"./memory.js";import{buildDeepAgentRequest as c}from"./internal/messages.js";import{createRawToolCallParserMiddleware as l}from"./internal/raw-tool-call-parser.js";import{createBackendModel as u}from"./model-providers.js";import{createDeepAgentsRetryMiddleware as m}from"./retry-policy.js";import{streamDeepAgentResult as g}from"./internal/stream-events.js";export function createDeepAgentsAdapter(e={}){return{name:"deepagents",canRun:e=>"deepagents"===e.backend,async run(t){if(t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",phase:"agent.handoff",modelRef:t.agent.modelRef,tools:t.agent.tools,skills:t.agent.skills,subagents:t.agent.subagents}}),e.runner)return e.runner(t);const r=e.createDeepAgent?void 0:await async function loadDeepAgentsModule(){try{return await async function importOptionalPackage(e){return import(e)}("deepagents")}catch(e){throw new Error(`DeepAgents package is required for the default adapter path: ${function formatError(e){return e instanceof Error?e.message:String(e)}(e)}`)}}(),n=e.createDeepAgent??function readCreateDeepAgent(e){const t=e?.createDeepAgent;if("function"==typeof t)return t;throw new Error("DeepAgents package does not export createDeepAgent.")}(r),o=n(function buildDeepAgentParams(e,t,r){const n={...readDeepAgentsConfig(t),...readDeepAgentsConfig(e.agent.config.deepagents)},o=resolveDeepAgentsSkills(e,e.agent),a=n.permissions??s(e,e.agent),p=requestScopedRepeatState(e,e.agent.id);return pruneUndefined({name:e.agent.id,model:n.model??resolveAgentModel(e,e.agent),systemPrompt:buildSystemPrompt(e,e.agent),backend:n.backend??resolveDeepAgentsBackend(e,r,o),checkpointer:n.checkpointer,store:n.store,middleware:mergeMiddleware(e,e.agent,n.middleware,p),responseFormat:n.responseFormat,contextSchema:n.contextSchema,interruptOn:n.interruptOn,generalPurposeAgent:readBoolean(n.generalPurposeAgent),taskDescription:readString(n.taskDescription),permissions:a,tools:i(e,e.agent.id,e.agent.tools,resolveAgentRepairModel(e,e.agent,n),p),subagents:e.agent.subagents.map(t=>{const r=e.workspace.agents.get(t),n=readDeepAgentsConfig(r?.config.deepagents),o=n.permissions??s(e,r),a=scopedInput(e,r),p=requestScopedRepeatState(e,t);return pruneUndefined({name:t,description:r?.description??readString(r?.config.description)??r?.id,systemPrompt:buildSystemPrompt(e,r),model:n.model??(r?resolveAgentModel(e,r):void 0),middleware:mergeMiddleware(a,r,n.middleware,p),interruptOn:n.interruptOn,generalPurposeAgent:readBoolean(n.generalPurposeAgent),taskDescription:readString(n.taskDescription),permissions:o,responseFormat:n.responseFormat,tools:i(e,t,r?.tools??[],resolveAgentRepairModel(a,r,n),p),memory:resolveDeepAgentsMemory(e,r),skills:resolveDeepAgentsSkills(e,r)})}),memory:resolveDeepAgentsMemory(e,e.agent),skills:o})}(t,e.config,r)),a=c(t),d=function buildDeepAgentInvokeConfig(e){return pruneUndefined({recursionLimit:readNumber(readDeepAgentsConfig(e.config.deepagents).recursionLimit)??readNumber(e.config.recursionLimit)})}(t.agent);if(!0===t.request.metadata?.openaiStream&&o.streamEvents){const e=await o.streamEvents(a,{version:"v3",...d});return g(t,e,p)}const l=await o.invoke(a,d);return p(l)}}}function buildSystemPrompt(e,t){const n=t?.systemPrompt??readString(t?.config.systemPrompt);return r({workspace:e.workspace,request:e.request,agent:t},n)}function resolveDeepAgentsMemory(e,t){const r=readDeepAgentsStringArray(t?.config,"memory");if(r)return r;const n=[...readAgentMemorySources(e.workspace.root,t),...d(e.workspace).map(e=>`/memories/${e.id}.md`)],o=[...new Set(n)];return o.length>0?o:void 0}function readAgentMemorySources(e,t){return(t?.memory??[]).flatMap(t=>"string"==typeof t&&t.trim()?[backendMemorySourcePath(e,t.trim())]:isRecord(t)&&"string"==typeof t.path&&t.path.trim()?[backendMemorySourcePath(e,t.path.trim())]:[])}function backendMemorySourcePath(e,r){if(r.startsWith("/"))return r;if(t.isAbsolute(r)){const n=t.relative(e,r);return n&&!n.startsWith("..")?`/${n.split(t.sep).join("/")}`:canonicalPath(r)}const n=r.split(t.sep).join("/");return n.startsWith("/")?n:`/${n}`}function resolveDeepAgentsSkills(e,r){const n=readDeepAgentsStringArray(r?.config,"skills");if(n)return n;const o=[...new Set((r?.skills??[]).map(t=>e.workspace.skills.get(t)?.path).filter(e=>"string"==typeof e&&e.trim().length>0).map(r=>function backendSkillSourcePath(e,r){const n=t.dirname(t.dirname(r)),o=t.relative(e,n);return!o||o.startsWith("..")||t.isAbsolute(o)?""===o?"/":canonicalPath(n):`/${o.split(t.sep).join("/")}`}(e.workspace.root,r)))];return o.length>0?o:void 0}function resolveDeepAgentsBackend(e,t,r){if(t?.FilesystemBackend&&r&&0!==r.length)return()=>new t.FilesystemBackend({rootDir:e.workspace.root})}function mergeMiddleware(e,t,r,s=a(e.workspace.runtime.toolGateway)){const i=Array.isArray(r)?r:[],p=scopedInput(e,t),d=new Set,c=readDeepAgentsConfig(t?.config.deepagents);return[o(p,{observedToolIds:d,repeatState:s,repairModel:resolveAgentRepairModel(p,t,c)}),n(p,{repeatState:s}),...m(e.workspace.runtime.retry),...i,l(p)]}function requestScopedRepeatState(e,t){const r=`deepagents.repeat.${t}`,n=e.requestState?.get(r);if(n)return n;const o=a(e.workspace.runtime.toolGateway);return e.requestState&&o&&e.requestState.set(r,o),o}function scopedInput(e,t){return t?{...e,agent:t}:e}function resolveAgentModel(e,t){const r=t.modelRef?e.workspace.models.get(t.modelRef):void 0;return r?u(r):void 0}function resolveAgentRepairModel(e,t,r){const n=r.model;if(isRepairModel(n))return n;if(!t)return;const o=resolveAgentModel(e,t);return isRepairModel(o)?o:void 0}function readDeepAgentsConfig(e){return isRecord(e)?e:{}}function readDeepAgentsStringArray(e,t){const r=isRecord(e)?e:{},n=readDeepAgentsConfig(r.deepagents),o="memory"===t?["memory","memorySources"]:["skills","skillSources"];for(const e of o){const t=readStringArray(n[e]);if(t)return t}return readStringArray(r[t])}function pruneUndefined(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>void 0!==e))}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readNumber(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function readBoolean(e){return"boolean"==typeof e?e:void 0}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e):void 0}function canonicalPath(t){try{return e.native(t)}catch{return t}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function isRepairModel(e){return"object"==typeof e&&null!==e&&"invoke"in e&&"function"==typeof e.invoke}
@@ -1 +1 @@
1
- import{ToolMessage as t}from"@langchain/core/messages";import{afterToolInvoke as e,beforeToolInvoke as o,createToolRepeatState as r}from"@stable-harness/core";import{filesystemBuiltinToolIds as i,isFilesystemDisabled as n,isFilesystemTool as s,validateFilesystemBuiltinCall as a}from"./builtin/permissions.js";import{repairTaskCall as l}from"./builtin/task-inventory.js";import{repairBuiltinToolRequest as u}from"./builtin-call-repair.js";import{stringifyDeepAgentResult as c,toolControlProjection as d}from"./gateway-tools.js";import{isSuccessfulEvidenceOutput as p,observedToolEvidence as m,recordObservedToolEvidence as g}from"./gateway/tool-evidence.js";import{validateSkillFileBuiltinCall as f}from"./skill-file-policy.js";import{filterRepeatLimitedTools as v}from"./tool-repeat-visibility.js";import{traceProjectionForBuiltinTool as b}from"./trace-projection.js";const T=new Set(["write_todos","read_todos","task","execute",...i]);export function createBuiltinToolPolicyMiddleware(t,e={}){return{name:"StableHarnessBuiltinToolPolicy",async wrapModelCall(o,r){const i=Array.isArray(o.tools)?v(o.tools.filter(e=>!function hasHiddenBuiltins(t){return n(t)||!isTaskVisible(t)}(t)||isModelVisibleBuiltin(t,e.name)),e.repeatState):o.tools,s=function normalizeToolChoice(t,e,o){return"required"===e?o&&o.length>0?e:"auto":function isForcedHiddenTool(t,e){return"string"==typeof e?.function?.name&&!isModelVisibleBuiltin(t,e.function.name)}(t,e)?"auto":e}(t,o.toolChoice,i);return r({...o,tools:i,toolChoice:s})}}}export function createObserverMiddleware(i,n={}){const s=n.repeatState??r(i.workspace.runtime.toolGateway);return{name:"StableHarnessObserver",async wrapToolCall(r,d){const g=r.toolCall?.name;if(!g||!T.has(g))return d(r);const v=await u({toolId:g,request:r,workspaceRoot:i.workspace.root});emitToolEvent(i,g,"agent.tool.start",v.toolCall?.args);const b="task"===g?await l(i,v,{repairModel:n.repairModel}):{request:v},h=b.request,y=b.blocked;if(y)return emitToolEvent(i,g,"agent.tool.result",h.toolCall?.args,{output:y.content}),y;const k=a(i,g,h);if(k)return emitToolEvent(i,g,"agent.tool.result",h.toolCall?.args,{output:k.content}),k;const C=f(i,g,h);if(C)return emitToolEvent(i,g,"agent.tool.result",h.toolCall?.args,{output:C.content}),C;try{const a=s?o(g,h.toolCall?.args,s):void 0;if(a)return emitToolEvent(i,g,"agent.tool.result",h.toolCall?.args,{output:a.eventOutput}),builtinToolMessage(r,g,function modelOutputForRepeatedBuiltin(t,e){return"task"!==t?e:function readPreviousOutput(t){try{const e=JSON.parse(t);if(!isRecord(e)||"repeated_tool_call_limit"!==e.status||"string"!=typeof e.previousOutput)return;const o=e.previousOutput.trim();return o.length>0?o:void 0}catch{return}}(e)??e}(g,a.modelOutput));const l=await d(h),u=function observedToolOutput(t,e,o){return"write_todos"===t?JSON.stringify({status:"recorded",args:e.toolCall?.args}):c(o)}(g,h,l),m=s?e({toolId:g,args:h.toolCall?.args,output:u,successful:!(l instanceof t&&"error"===l.status)&&p(u),state:s}):{};return emitToolEvent(i,g,"agent.tool.result",h.toolCall?.args,{output:m.eventOutput??u}),n.observedToolIds?.add(g),void 0===m.modelOutput?l:builtinToolMessage(r,g,m.modelOutput)}catch(e){const o=function recoverableBuiltinToolError(e,o,r,i){const n=formatError(i);if("task"===o&&/repeat limit reached for tool/iu.test(n)){const o=function formatObservedEvidence(t){const e=m(t);if(0===e.length)return"";const o=e.map(t=>[`Agent: ${t.agentId}`,`Tool: ${t.toolId}`,t.output].join("\n")).join("\n\n---\n\n");return o.length>12e3?`${o.slice(0,12e3)}\n[truncated]`:o}(e);return new t({tool_call_id:r.toolCall?.id??"stable-harness-task-repeat-limit",name:"task",content:JSON.stringify({status:"delegated_task_repeat_limit",finalizationRequired:!0,instruction:"The delegated agent reached a configured tool repeat limit. Stop delegating this evidence need and do not send a synthesis task to another subagent for the same need. Finalize only from observedEvidence and other evidence that is already visible in this run. If the visible evidence is insufficient for a requested claim, report an explicit blocker or evidence gap instead of estimating, inventing, or using generic knowledge.",...o?{observedEvidence:o}:{},error:previewError(n)})})}if(/Received tool input did not match expected schema|Invalid input:/iu.test(n))return new t({tool_call_id:r.toolCall?.id??`stable-harness-${o}-argument-error`,name:o,status:"error",content:JSON.stringify({status:"tool_argument_error",toolId:o,instruction:"The upstream builtin tool rejected these arguments. Fix the tool arguments according to the tool schema, or choose a more appropriate available tool.",error:previewError(n)})})}(i,g,r,e);if(o)return emitToolEvent(i,g,"agent.tool.result",v.toolCall?.args,{output:o.content}),o;throw emitToolEvent(i,g,"agent.tool.result",v.toolCall?.args,{error:formatError(e)}),e}}}}function builtinToolMessage(e,o,r){return new t({tool_call_id:e.toolCall?.id??`stable-harness-${o}-repeat-guard`,name:o,content:r})}function emitToolEvent(t,e,o,r,i={}){"string"==typeof i.output&&g(t,t.agent.id,e,i.output),t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",eventGroup:"tool_execution",eventType:"agent.tool.start"===o?"deepagents.tool_execution.start":"deepagents.tool_execution.result",phase:o,toolId:e,..."agent.tool.start"===o?{args:r}:{},...i,..."string"==typeof i.output?d(i.output):{},...b(e,o,r)}})}function isTaskVisible(t){const e=function readConfigRecord(t,e){const o=isRecord(t)?t:{};return isRecord(o[e])?o[e]:void 0}(t.agent.config,"builtinTools")?.modelExposed;return!1!==e&&(!Array.isArray(e)||e.includes("task"))}function isModelVisibleBuiltin(t,e){return(!n(t)||!s(e))&&("task"!==e||isTaskVisible(t))}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function formatError(t){return t instanceof Error?t.message:String(t)}function previewError(t){const e=t.replace(/\s+/gu," ").trim();return e.length>800?`${e.slice(0,797)}...`:e}
1
+ import{ToolMessage as t}from"@langchain/core/messages";import{afterToolInvoke as e,beforeToolInvoke as o,createToolRepeatState as r}from"@stable-harness/core";import{filesystemBuiltinToolIds as n,isFilesystemDisabled as i,isFilesystemTool as s,validateFilesystemBuiltinCall as a}from"./builtin/permissions.js";import{repairTaskCall as l}from"./builtin/task-inventory.js";import{repairBuiltinToolRequest as u}from"./builtin-call-repair.js";import{stringifyDeepAgentResult as c,toolControlProjection as d}from"./gateway-tools.js";import{isSuccessfulEvidenceOutput as p,observedToolEvidence as g,recordObservedToolEvidence as m}from"./gateway/tool-evidence.js";import{filterRepeatLimitedTools as f}from"./tool-repeat-visibility.js";import{traceProjectionForBuiltinTool as v}from"./trace-projection.js";const b=new Set(["write_todos","read_todos","task","execute",...n]);export function createBuiltinToolPolicyMiddleware(t,e={}){return{name:"StableHarnessBuiltinToolPolicy",async wrapModelCall(o,r){const n=Array.isArray(o.tools)?f(o.tools.filter(e=>!function hasHiddenBuiltins(t){return i(t)||!isTaskVisible(t)}(t)||isModelVisibleBuiltin(t,e.name)),e.repeatState):o.tools,s=function normalizeToolChoice(t,e,o){return"required"===e?o&&o.length>0?e:"auto":function isForcedHiddenTool(t,e){return"string"==typeof e?.function?.name&&!isModelVisibleBuiltin(t,e.function.name)}(t,e)?"auto":e}(t,o.toolChoice,n);return r({...o,tools:n,toolChoice:s})}}}export function createObserverMiddleware(n,i={}){const s=i.repeatState??r(n.workspace.runtime.toolGateway);return{name:"StableHarnessObserver",async wrapToolCall(r,d){const m=r.toolCall?.name;if(!m||!b.has(m))return d(r);const f=await u({toolId:m,request:r,workspaceRoot:n.workspace.root});emitToolEvent(n,m,"agent.tool.start",f.toolCall?.args);const v="task"===m?await l(n,f,{repairModel:i.repairModel}):{request:f},T=v.request,h=v.blocked;if(h)return emitToolEvent(n,m,"agent.tool.result",T.toolCall?.args,{output:h.content}),h;const y=a(n,m,T);if(y)return emitToolEvent(n,m,"agent.tool.result",T.toolCall?.args,{output:y.content}),y;try{const a=s?o(m,T.toolCall?.args,s):void 0;if(a)return emitToolEvent(n,m,"agent.tool.result",T.toolCall?.args,{output:a.eventOutput}),builtinToolMessage(r,m,function modelOutputForRepeatedBuiltin(t,e){return"task"!==t?e:function readPreviousOutput(t){try{const e=JSON.parse(t);if(!isRecord(e)||"repeated_tool_call_limit"!==e.status||"string"!=typeof e.previousOutput)return;const o=e.previousOutput.trim();return o.length>0?o:void 0}catch{return}}(e)??e}(m,a.modelOutput));const l=await d(T),u=function observedToolOutput(t,e,o){return"write_todos"===t?JSON.stringify({status:"recorded",args:e.toolCall?.args}):c(o)}(m,T,l),g=s?e({toolId:m,args:T.toolCall?.args,output:u,successful:!(l instanceof t&&"error"===l.status)&&p(u),state:s}):{};return emitToolEvent(n,m,"agent.tool.result",T.toolCall?.args,{output:g.eventOutput??u}),i.observedToolIds?.add(m),void 0===g.modelOutput?l:builtinToolMessage(r,m,g.modelOutput)}catch(e){const o=function recoverableBuiltinToolError(e,o,r,n){const i=formatError(n);if("task"===o&&/repeat limit reached for tool/iu.test(i)){const o=function formatObservedEvidence(t){const e=g(t);if(0===e.length)return"";const o=e.map(t=>[`Agent: ${t.agentId}`,`Tool: ${t.toolId}`,t.output].join("\n")).join("\n\n---\n\n");return o.length>12e3?`${o.slice(0,12e3)}\n[truncated]`:o}(e);return new t({tool_call_id:r.toolCall?.id??"stable-harness-task-repeat-limit",name:"task",content:JSON.stringify({status:"delegated_task_repeat_limit",finalizationRequired:!0,instruction:"The delegated agent reached a configured tool repeat limit. Stop delegating this evidence need and do not send a synthesis task to another subagent for the same need. Finalize only from observedEvidence and other evidence that is already visible in this run. If the visible evidence is insufficient for a requested claim, report an explicit blocker or evidence gap instead of estimating, inventing, or using generic knowledge.",...o?{observedEvidence:o}:{},error:previewError(i)})})}if(/Received tool input did not match expected schema|Invalid input:/iu.test(i))return new t({tool_call_id:r.toolCall?.id??`stable-harness-${o}-argument-error`,name:o,status:"error",content:JSON.stringify({status:"tool_argument_error",toolId:o,instruction:"The upstream builtin tool rejected these arguments. Fix the tool arguments according to the tool schema, or choose a more appropriate available tool.",error:previewError(i)})})}(n,m,r,e);if(o)return emitToolEvent(n,m,"agent.tool.result",f.toolCall?.args,{output:o.content}),o;throw emitToolEvent(n,m,"agent.tool.result",f.toolCall?.args,{error:formatError(e)}),e}}}}function builtinToolMessage(e,o,r){return new t({tool_call_id:e.toolCall?.id??`stable-harness-${o}-repeat-guard`,name:o,content:r})}function emitToolEvent(t,e,o,r,n={}){"string"==typeof n.output&&m(t,t.agent.id,e,n.output),t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,event:{adapter:"deepagents",eventGroup:"tool_execution",eventType:"agent.tool.start"===o?"deepagents.tool_execution.start":"deepagents.tool_execution.result",phase:o,toolId:e,..."agent.tool.start"===o?{args:r}:{},...n,..."string"==typeof n.output?d(n.output):{},...v(e,o,r)}})}function isTaskVisible(t){const e=function readConfigRecord(t,e){const o=isRecord(t)?t:{};return isRecord(o[e])?o[e]:void 0}(t.agent.config,"builtinTools")?.modelExposed;return!1!==e&&(!Array.isArray(e)||e.includes("task"))}function isModelVisibleBuiltin(t,e){return(!i(t)||!s(e))&&("task"!==e||isTaskVisible(t))}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function formatError(t){return t instanceof Error?t.message:String(t)}function previewError(t){const e=t.replace(/\s+/gu," ").trim();return e.length>800?`${e.slice(0,797)}...`:e}
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{realpathSync as e}from"node:fs";import{fileURLToPath as t}from"node:url";import{createBackendModel as r,createDeepAgentsAdapter as o}from"@stable-harness/adapter-deepagents";import{createLangGraphWorkflowAdapter as s}from"@stable-harness/adapter-langgraph";import{createStableHarnessRuntime as a}from"@stable-harness/core";import{projectEvent as i,projectRuntimeTrace as n}from"@stable-harness/core";import{createInMemoryApprovalQueue as u}from"@stable-harness/governance";import{createModuleToolGateway as d}from"@stable-harness/tool-gateway";import{loadWorkspaceFromYaml as l}from"@stable-harness/workspace-yaml";import{helpText as p,parseArgs as c}from"./args.js";import{buildWorkspaceArtifact as f}from"./build.js";import{formatCliRuntimeEvent as m,readCliEventViewConfig as w,shouldEnableCliProgressNarration as v}from"./event-view.js";import{initWorkspace as g}from"./init.js";import{ensureCliMemoryServices as y}from"./memory/lifecycle.js";import{createCliMemoryProviders as I}from"./memory/providers.js";import{formatDetail as k,inspectWorkflow as R,renderAgent as h,renderWorkflow as b,workspaceStatus as q}from"./output.js";import{serveProtocol as A,stopProtocol as C}from"./server.js";export async function runCli(e=process.argv.slice(2)){const t=c(e);if(t.help)return void process.stdout.write(p());const r=setTimeout(()=>{process.stderr.write(`stable-harness request timed out after ${t.timeoutMs}ms\n`),process.exit(124)},t.timeoutMs),s=t.workspaceRoot;try{if("init"===t.command)return void process.stdout.write(await g(t.prompt||s));const e=await l(s);if(t.workflowRenderId)return void process.stdout.write(b(e,t.workflowRenderId));if(t.workflowInspectId)return void process.stdout.write(R(e,t.workflowInspectId));if(t.agentRenderId)return void process.stdout.write(h(e,t.agentRenderId));if("build"===t.command)return void process.stdout.write(await f({workspace:e,workspaceRoot:s,outputDir:t.buildOutput,target:t.buildTarget}));if("stop"===t.command)return clearTimeout(r),void await C(e,t);const p=await d({tools:e.tools.values(),options:{betterCall:{mode:"repair"}}});await y(e);const c=I(e),M=u(),j=w(e.runtime);let $;if($=a({workspace:e,toolGateway:p,approvals:M,memoryProviders:c,adapters:[o()],workflowAdapters:[createCliWorkflowAdapter(p,()=>$)],progressNarration:v(j,e.runtime)?{enabled:!0,style:"cli"}:void 0,qualityReviewModel:createQualityReviewModel(e)}),t.serveOpenAi)return clearTimeout(r),void await A($,t);if(!t.shouldRunRequest)return void process.stdout.write(q(e,s));t.trace&&$.subscribe(e=>{const t=i(e);t&&process.stdout.write(`trace:${t.agentId}:${t.label}${k(t.detail)}\n`)}),$.subscribe(e=>{const t=m(e,j);t&&process.stdout.write(`${t}\n`)});const S=await $.request({input:t.prompt,agentId:t.agentId,sessionId:t.sessionId,toolCall:t.toolId?{toolId:t.toolId,args:t.toolArgs}:void 0,workflow:t.workflowRunId?{workflowId:t.workflowRunId,input:t.prompt}:void 0});if(t.trace||t.traceJson){const e=$.getRun(S.requestId),r=e?n(e):[];t.traceJson&&process.stdout.write(`${JSON.stringify({trace:r})}\n`)}process.stdout.write(`${S.output}\n`)}finally{clearTimeout(r)}}function createQualityReviewModel(e){const t=function readQualityModelRef(e){const t=isRecord(e)?e:{},r=isRecord(t.reviewer)?t.reviewer:t;return"string"==typeof r.modelRef&&r.modelRef.trim()?r.modelRef.trim():void 0}(e.runtime.quality),o=t?e.models.get(t):void 0,s=o?r(o):void 0;return function isQualityReviewModel(e){return isRecord(e)&&"function"==typeof e.invoke}(s)?s:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function createCliWorkflowAdapter(e,t){return s({nodeResolvers:{tools:async({id:t,node:r,request:o,requestId:s,sessionId:a,state:i,workspace:n})=>{return(await e.invoke({toolId:t,args:(u=r.config,d=o.input,l=i.outputs,!0===u?.inputFromState?{...u,requestInput:d,outputs:l}:u&&"requiredInput"in u?u.requiredInput:u&&("args"in u||"cwd"in u||"timeoutMs"in u)?u:"object"==typeof d&&null!==d?d:{}),context:{workspaceRoot:n.root,requestId:s,sessionId:a,agentId:`workflow:${r.id}`,approvalIds:readApprovalIds(o.metadata)}})).output;var u,d,l},agents:async({id:e,node:r,request:o,sessionId:s,state:a})=>{var i,n,u,d;return(await t().request({input:(i=e,n=o.input,u=a.outputs,d=r.config,[`Workflow node agents.${i}: synthesize the workflow evidence into the requested final output.`,`Original request: ${"string"==typeof n?n:JSON.stringify(n)}`,"Requirements:","- Produce the final answer now; do not ask follow-up questions.","- Match the original request language unless workflow config explicitly says otherwise.","- Use only the workflow outputs as evidence; call out uncertainty directly.",...d?[`Workflow node config: ${JSON.stringify(d)}`]:[],"Prior workflow outputs:",JSON.stringify(u)].join("\n")),agentId:e,sessionId:s,metadata:o.metadata})).output}}})}function readApprovalIds(e){const t=e?.approvalIds??e?.approvalId;return"string"==typeof t&&t.trim()?[t.trim()]:Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.trim().length>0):void 0}(function isCliEntrypoint(){const r=process.argv[1];if(!r)return!1;try{return e(t(import.meta.url))===e(r)}catch{return!1}})()&&runCli().catch(e=>{process.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1});
2
+ import{realpathSync as e}from"node:fs";import{fileURLToPath as t}from"node:url";import{createBackendModel as r,createDeepAgentsAdapter as o}from"@stable-harness/adapter-deepagents";import{createLangGraphWorkflowAdapter as s}from"@stable-harness/adapter-langgraph";import{createStableHarnessRuntime as a}from"@stable-harness/core";import{projectEvent as i,projectRuntimeTrace as n}from"@stable-harness/core";import{createInMemoryApprovalQueue as u}from"@stable-harness/governance";import{createModuleToolGateway as d}from"@stable-harness/tool-gateway";import{loadWorkspaceFromYaml as l}from"@stable-harness/workspace-yaml";import{helpText as p,parseArgs as c}from"./args.js";import{buildWorkspaceArtifact as m}from"./build.js";import{formatCliRuntimeEvent as f,readCliEventViewConfig as w,shouldEnableCliProgressNarration as v}from"./event-view.js";import{initWorkspace as g}from"./init.js";import{ensureCliMemoryServices as y}from"./memory/lifecycle.js";import{createCliMemoryProviders as I}from"./memory/providers.js";import{formatDetail as k,inspectWorkflow as R,renderAgent as h,renderWorkflow as b,workspaceStatus as q}from"./output.js";import{serveProtocol as A,stopProtocol as C}from"./server.js";export async function runCli(e=process.argv.slice(2)){const t=c(e);if(t.help)return void process.stdout.write(p());const r=setTimeout(()=>{process.stderr.write(`stable-harness request timed out after ${t.timeoutMs}ms\n`),process.exit(124)},t.timeoutMs),s=t.workspaceRoot;try{if("init"===t.command)return void process.stdout.write(await g(t.prompt||s));const e=await l(s);if(t.workflowRenderId)return void process.stdout.write(b(e,t.workflowRenderId));if(t.workflowInspectId)return void process.stdout.write(R(e,t.workflowInspectId));if(t.agentRenderId)return void process.stdout.write(h(e,t.agentRenderId));if("build"===t.command)return void process.stdout.write(await m({workspace:e,workspaceRoot:s,outputDir:t.buildOutput,target:t.buildTarget}));if("stop"===t.command)return clearTimeout(r),void await C(e,t);const p=await d({tools:e.tools.values(),options:{betterCall:{mode:"repair"}}}),c=u(),M=w(e.runtime),j=await async function createCliMemoryProvidersForCommand(e,t){return t.serveOpenAi||t.shouldRunRequest&&!t.toolId?(await y(e),I(e)):[]}(e,t);let $;if($=a({workspace:e,toolGateway:p,approvals:c,memoryProviders:j,adapters:[o()],workflowAdapters:[createCliWorkflowAdapter(p,()=>$)],progressNarration:v(M,e.runtime)?{enabled:!0,style:"cli"}:void 0,qualityReviewModel:createQualityReviewModel(e)}),t.serveOpenAi)return clearTimeout(r),void await A($,t);if(!t.shouldRunRequest)return void process.stdout.write(q(e,s));t.trace&&$.subscribe(e=>{const t=i(e);t&&process.stdout.write(`trace:${t.agentId}:${t.label}${k(t.detail)}\n`)}),$.subscribe(e=>{const t=f(e,M);t&&process.stdout.write(`${t}\n`)});const S=await $.request({input:t.prompt,agentId:t.agentId,sessionId:t.sessionId,toolCall:t.toolId?{toolId:t.toolId,args:t.toolArgs}:void 0,workflow:t.workflowRunId?{workflowId:t.workflowRunId,input:t.prompt}:void 0});if(t.trace||t.traceJson){const e=$.getRun(S.requestId),r=e?n(e):[];t.traceJson&&process.stdout.write(`${JSON.stringify({trace:r})}\n`)}process.stdout.write(`${S.output}\n`)}finally{clearTimeout(r)}}function createQualityReviewModel(e){const t=function readQualityModelRef(e){const t=isRecord(e)?e:{},r=isRecord(t.reviewer)?t.reviewer:t;return"string"==typeof r.modelRef&&r.modelRef.trim()?r.modelRef.trim():void 0}(e.runtime.quality),o=t?e.models.get(t):void 0,s=o?r(o):void 0;return function isQualityReviewModel(e){return isRecord(e)&&"function"==typeof e.invoke}(s)?s:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function createCliWorkflowAdapter(e,t){return s({nodeResolvers:{tools:async({id:t,node:r,request:o,requestId:s,sessionId:a,state:i,workspace:n})=>{return(await e.invoke({toolId:t,args:(u=r.config,d=o.input,l=i.outputs,!0===u?.inputFromState?{...u,requestInput:d,outputs:l}:u&&"requiredInput"in u?u.requiredInput:u&&("args"in u||"cwd"in u||"timeoutMs"in u)?u:"object"==typeof d&&null!==d?d:{}),context:{workspaceRoot:n.root,requestId:s,sessionId:a,agentId:`workflow:${r.id}`,approvalIds:readApprovalIds(o.metadata)}})).output;var u,d,l},agents:async({id:e,node:r,request:o,sessionId:s,state:a})=>{var i,n,u,d;return(await t().request({input:(i=e,n=o.input,u=a.outputs,d=r.config,[`Workflow node agents.${i}: synthesize the workflow evidence into the requested final output.`,`Original request: ${"string"==typeof n?n:JSON.stringify(n)}`,"Requirements:","- Produce the final answer now; do not ask follow-up questions.","- Match the original request language unless workflow config explicitly says otherwise.","- Use only the workflow outputs as evidence; call out uncertainty directly.",...d?[`Workflow node config: ${JSON.stringify(d)}`]:[],"Prior workflow outputs:",JSON.stringify(u)].join("\n")),agentId:e,sessionId:s,metadata:o.metadata})).output}}})}function readApprovalIds(e){const t=e?.approvalIds??e?.approvalId;return"string"==typeof t&&t.trim()?[t.trim()]:Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.trim().length>0):void 0}(function isCliEntrypoint(){const r=process.argv[1];if(!r)return!1;try{return e(t(import.meta.url))===e(r)}catch{return!1}})()&&runCli().catch(e=>{process.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1});
@@ -1 +1 @@
1
- export function readCliEventViewConfig(e){const t=readRecord(e.cli),r=readRecord(t?.events);return{enabled:readBoolean(r?.enabled)??!0,include:readStringList(r?.include)??["runtime.progress.narration"],exclude:readStringList(r?.exclude)??[]}}export function shouldEnableCliProgressNarration(e,t){if(!e.enabled)return!1;const r=readRecord(readRecord(t.progress)?.narration);return!1!==readBoolean(r?.enabled)&&e.include.some(e=>matchesEventPattern("runtime.progress.narration",e))}export function formatCliRuntimeEvent(e,t){if(!t.enabled||!function isIncluded(e,t){const r=function eventKeys(e){return"runtime.adapter.event"===e.type&&isRecord(e.event)&&"string"==typeof e.event.phase?[e.type,e.event.phase]:[e.type]}(e),n=t.include.some(e=>r.some(t=>matchesEventPattern(t,e))),i=t.exclude.some(e=>r.some(t=>matchesEventPattern(t,e)));return n&&!i}(e,t))return;const r=function projectCliEventView(e){return"runtime.progress.narration"===e.type?{group:"Progress",title:e.message}:e.type.startsWith("runtime.request.")?{group:"Run",title:e.type}:"runtime.tool.direct.started"===e.type||"runtime.tool.direct.completed"===e.type?{group:"Tool",title:e.type,detail:e.toolId}:"runtime.workflow.started"===e.type||"runtime.workflow.completed"===e.type?{group:"Workflow",title:e.type,detail:e.workflowId}:"runtime.approval.requested"===e.type||"runtime.approval.resolved"===e.type?{group:"Approval",title:e.type,detail:`${e.approval.kind}:${e.approval.status}`}:e.type.startsWith("runtime.memory.")?{group:"Memory",title:e.type,detail:memoryDetail(e)}:"runtime.skill.candidate.created"===e.type?{group:"Skill",title:e.type,detail:e.name}:"runtime.artifact.created"===e.type?{group:"Artifact",title:e.type}:"runtime.execution.contract.failed"===e.type?{group:"Contract",title:e.type,detail:e.reason}:"runtime.adapter.event"===e.type?function adapterEventView(e){if(!isRecord(e))return{group:"Adapter",title:"runtime.adapter.event"};const t="string"==typeof e.phase?e.phase:"runtime.adapter.event";return t.startsWith("agent.tool.")?{group:"Agent Tool",title:t,detail:readString(e.toolId)}:t.startsWith("agent.output.")?{group:"Agent Output",title:t,detail:readString(e.text)}:t.startsWith("agent.")?{group:"Agent",title:t,detail:readString(e.adapter)}:{group:"Adapter",title:t,detail:readString(e.adapter)}}(e.event):{group:"event",title:e.type}}(e);return`[${r.group}] ${e.agentId} | ${r.title}${r.detail?` | ${r.detail}`:""}`}function matchesEventPattern(e,t){return"*"===t||(t.endsWith(".*")?e===t.slice(0,-2)||e.startsWith(t.slice(0,-1)):e===t)}function memoryDetail(e){return"runtime.memory.recall.completed"===e.type?`${e.recordIds.length} records`:"provider"in e?e.provider:"target"in e?e.target:void 0}function readRecord(e){return isRecord(e)?e:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readBoolean(e){return"boolean"==typeof e?e:void 0}function readStringList(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.trim().length>0):void 0}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}
1
+ export function readCliEventViewConfig(e){const t=readRecord(e.cli),r=readRecord(t?.events);return{enabled:readBoolean(r?.enabled)??!0,include:readStringList(r?.include)??["runtime.progress.narration"],exclude:readStringList(r?.exclude)??[]}}export function shouldEnableCliProgressNarration(e,t){if(!e.enabled)return!1;const r=readRecord(readRecord(t.progress)?.narration);return!1!==readBoolean(r?.enabled)&&e.include.some(e=>matchesEventPattern("runtime.progress.narration",e))}export function formatCliRuntimeEvent(e,t){if(!t.enabled||!function isIncluded(e,t){const r=function eventKeys(e){return"runtime.adapter.event"===e.type&&isRecord(e.event)&&"string"==typeof e.event.phase?[e.type,e.event.phase]:[e.type]}(e),n=t.include.some(e=>r.some(t=>matchesEventPattern(t,e))),i=t.exclude.some(e=>r.some(t=>matchesEventPattern(t,e)));return n&&!i}(e,t))return;const r=function projectCliEventView(e){return"runtime.progress.narration"===e.type?{group:"Progress",title:e.message}:e.type.startsWith("runtime.request.")?{group:"Run",title:e.type}:"runtime.tool.direct.started"===e.type||"runtime.tool.direct.completed"===e.type?{group:"Tool",title:e.type,detail:e.toolId}:"runtime.workflow.started"===e.type||"runtime.workflow.completed"===e.type?{group:"Workflow",title:e.type,detail:e.workflowId}:"runtime.approval.requested"===e.type||"runtime.approval.resolved"===e.type?{group:"Approval",title:e.type,detail:`${e.approval.kind}:${e.approval.status}`}:e.type.startsWith("runtime.memory.")?{group:"Memory",title:e.type,detail:memoryDetail(e)}:"runtime.skill.candidate.created"===e.type?{group:"Skill",title:e.type,detail:e.name}:"runtime.artifact.created"===e.type?{group:"Artifact",title:e.type}:"runtime.execution.contract.failed"===e.type?{group:"Contract",title:e.type,detail:e.reason}:"runtime.repair.started"===e.type?{group:"Repair",title:e.type,detail:`${e.layer}${e.attempt?`#${e.attempt}`:""}`}:"runtime.repair.completed"===e.type?{group:"Repair",title:e.type,detail:`${e.layer}:${e.outcome}`}:"runtime.adapter.event"===e.type?function adapterEventView(e){if(!isRecord(e))return{group:"Adapter",title:"runtime.adapter.event"};const t="string"==typeof e.phase?e.phase:"runtime.adapter.event";return t.startsWith("agent.tool.")?{group:"Agent Tool",title:t,detail:readString(e.toolId)}:t.startsWith("agent.output.")?{group:"Agent Output",title:t,detail:readString(e.text)}:t.startsWith("agent.")?{group:"Agent",title:t,detail:readString(e.adapter)}:{group:"Adapter",title:t,detail:readString(e.adapter)}}(e.event):{group:"event",title:e.type}}(e);return`[${r.group}] ${e.agentId} | ${r.title}${r.detail?` | ${r.detail}`:""}`}function matchesEventPattern(e,t){return"*"===t||(t.endsWith(".*")?e===t.slice(0,-2)||e.startsWith(t.slice(0,-1)):e===t)}function memoryDetail(e){return"runtime.memory.recall.completed"===e.type?`${e.recordIds.length} records`:"provider"in e?e.provider:"target"in e?e.target:void 0}function readRecord(e){return isRecord(e)?e:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readBoolean(e){return"boolean"==typeof e?e:void 0}function readStringList(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.trim().length>0):void 0}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}
@@ -1 +1 @@
1
- import{mkdir as e,writeFile as o}from"node:fs/promises";import a from"node:path";export async function initWorkspace(o){const t=a.resolve(o||".");return await e(a.join(t,"config","agents"),{recursive:!0}),await e(a.join(t,"config","catalogs"),{recursive:!0}),await e(a.join(t,"config","runtime"),{recursive:!0}),await e(a.join(t,"resources","tools"),{recursive:!0}),await Promise.all([writeScaffoldFile(a.join(t,"config","runtime","workspace.yaml"),["apiVersion: stable-harness.dev/v1","kind: Runtime","metadata:"," name: app-runtime","spec:"," routing:"," defaultAgentId: orchestra"," protocols:"," inProcess: true"," openaiCompatible:"," host: 127.0.0.1"," port: 8642",""].join("\n")),writeScaffoldFile(a.join(t,"config","agents","orchestra.yaml"),["apiVersion: stable-harness.dev/v1","kind: Agent","metadata:"," name: orchestra","spec:"," backend: deepagents"," modelRef: local-dev"," systemPrompt: You are a concise workspace agent."," tools:"," - echo_tool"," subagents: []",""].join("\n")),writeScaffoldFile(a.join(t,"config","catalogs","models.yaml"),["apiVersion: stable-harness.dev/v1","kind: Model","metadata:"," name: local-dev","spec:"," provider: openai-compatible"," model: ${env:STABLE_HARNESS_MODEL:-gpt-4.1-mini}"," baseUrl: ${env:STABLE_HARNESS_OPENAI_BASE_URL:-https://api.openai.com/v1}"," apiKey: ${env:OPENAI_API_KEY}",""].join("\n")),writeScaffoldFile(a.join(t,"resources","tools","echo_tool.mjs"),["export const echo_tool = {"," description: 'Echo input through the Stable Harness tool gateway.',"," schema: {"," type: 'object',"," properties: { value: { type: 'string' } },"," required: ['value'],"," },"," async invoke(args) {"," return JSON.stringify({ echoed: args.value });"," },","};",""].join("\n"))]),[`Initialized Stable Harness workspace at ${t}`,"","Try:",` stable-harness -w ${shellPath(t)}`,` stable-harness -w ${shellPath(t)} --agent orchestra --tool echo_tool --tool-args-json '{"value":"hello"}'`,""].join("\n")}async function writeScaffoldFile(e,a){try{await o(e,a,{flag:"wx"})}catch(o){if(function isFileExists(e){return e instanceof Error&&"code"in e&&"EEXIST"===e.code}(o))throw new Error(`Refusing to overwrite existing scaffold file: ${e}`);throw o}}function shellPath(e){return JSON.stringify(e)}
1
+ import{mkdir as e,writeFile as o}from"node:fs/promises";import a from"node:path";export async function initWorkspace(o){const r=a.resolve(o||".");return await e(a.join(r,"config","agents"),{recursive:!0}),await e(a.join(r,"config","catalogs"),{recursive:!0}),await e(a.join(r,"config","memory"),{recursive:!0}),await e(a.join(r,"config","runtime"),{recursive:!0}),await e(a.join(r,"resources","tools"),{recursive:!0}),await Promise.all([writeScaffoldFile(a.join(r,"config","runtime","workspace.yaml"),["apiVersion: stable-harness.dev/v1","kind: Runtime","metadata:"," name: app-runtime","spec:"," routing:"," defaultAgentId: orchestra"," protocols:"," inProcess: true"," openaiCompatible:"," host: 127.0.0.1"," port: 8642"," memory:"," enabled: true"," LangMem:"," read: true"," write: true"," refs:"," - workspace",""].join("\n")),writeScaffoldFile(a.join(r,"config","agents","orchestra.yaml"),["apiVersion: stable-harness.dev/v1","kind: Agent","metadata:"," name: orchestra","spec:"," backend: deepagents"," modelRef: local-dev"," systemPrompt: You are a concise workspace agent."," tools:"," - echo_tool"," subagents: []",""].join("\n")),writeScaffoldFile(a.join(r,"config","catalogs","models.yaml"),["apiVersion: stable-harness.dev/v1","kind: Model","metadata:"," name: local-dev","spec:"," provider: openai-compatible"," model: ${env:STABLE_HARNESS_MODEL:-gpt-4.1-mini}"," baseUrl: ${env:STABLE_HARNESS_OPENAI_BASE_URL:-https://api.openai.com/v1}"," apiKey: ${env:OPENAI_API_KEY}",""].join("\n")),writeScaffoldFile(a.join(r,"config","memory","workspace.yaml"),["apiVersion: stable-harness.dev/v1","kind: Memory","metadata:"," name: workspace"," description: Workspace-level long-term memory managed by LangMem.","spec:"," provider: langmem"," profile: workspace"," enabled: true"," mode: background"," prompts:"," semantic: Remember durable workspace facts, architecture decisions, validation commands, and project constraints."," episodic: Remember important workspace events, validation results, incidents, migrations, and fixes."," procedural: Remember reusable operating procedures, recovery steps, release steps, and engineering rules.",""].join("\n")),writeScaffoldFile(a.join(r,"resources","tools","echo_tool.mjs"),["export const echo_tool = {"," description: 'Echo input through the Stable Harness tool gateway.',"," schema: {"," type: 'object',"," properties: { value: { type: 'string' } },"," required: ['value'],"," },"," async invoke(args) {"," return JSON.stringify({ echoed: args.value });"," },","};",""].join("\n"))]),[`Initialized Stable Harness workspace at ${r}`,"","Try:",` stable-harness -w ${shellPath(r)}`,` stable-harness -w ${shellPath(r)} --agent orchestra --tool echo_tool --tool-args-json '{"value":"hello"}'`,""].join("\n")}async function writeScaffoldFile(e,a){try{await o(e,a,{flag:"wx"})}catch(o){if(function isFileExists(e){return e instanceof Error&&"code"in e&&"EEXIST"===e.code}(o))throw new Error(`Refusing to overwrite existing scaffold file: ${e}`);throw o}}function shellPath(e){return JSON.stringify(e)}
@@ -0,0 +1 @@
1
+ export declare const DEFAULT_LANGMEM_BASE_URL = "http://127.0.0.1:8878";
@@ -0,0 +1 @@
1
+ export const DEFAULT_LANGMEM_BASE_URL="http://127.0.0.1:8878";
@@ -1 +1 @@
1
- import{spawn as e}from"node:child_process";import{existsSync as r}from"node:fs";import t from"node:path";import{fileURLToPath as n}from"node:url";export async function ensureCliMemoryServices(r){const t=function readLangMemServiceConfig(e){const r=readRecord(e.runtime.memory?.LangMem)??readRecord(e.runtime.memory?.langmem);if(!function shouldAutoStart(e,r){return!1!==(e.runtime.memory??{}).enabled&&!1!==r?.enabled&&(!1!==r?.read||!1!==r?.write)&&[...e.memories.values()].some(e=>e.enabled&&"langmem"===e.provider)}(e,r))return;const t=readString(r?.baseUrl)??readString(r?.url)??process.env.STABLE_HARNESS_LANGMEM_URL;var n;return t?{baseUrl:t,autoStart:!1!==r?.autoStart,command:readString(r?.command)??"python3",args:(n=r?.args,(Array.isArray(n)?n.filter(e=>"string"==typeof e&&e.trim().length>0):void 0)??["-m","stable_harness_langmem_service"]),env:{...defaultLangMemEnv(e,t),...readStringRecord(r?.env)}}:void 0}(r);if(!t||!t.autoStart||!function isLocalBaseUrl(e){const r=new URL(e);return["localhost","127.0.0.1","::1"].includes(r.hostname)}(t.baseUrl)||await isHealthy(t.baseUrl))return;const n=e(t.command,t.args,{cwd:r.root,detached:!0,env:{...process.env,...t.env},stdio:"ignore"});n.unref(),await async function waitForStartedService(e,r){await Promise.race([waitForHealth(r.baseUrl),new Promise((r,t)=>e.once("error",t)),new Promise((t,n)=>{e.once("exit",(e,t)=>{n(new Error(`LangMem service exited before becoming healthy: ${r.command} code=${e??"null"} signal=${t??"null"}`))})})])}(n,t)}function defaultLangMemEnv(e,o){const a=new URL(o),i=readString(e.runtime.dataRoot)??".stable-harness",s=t.resolve(function packageRoot(){return t.resolve(t.dirname(n(import.meta.url)),"../../../../..")}(),"services/langmem-python/src");return{HOST:"localhost"===a.hostname?"127.0.0.1":a.hostname,PORT:a.port||("https:"===a.protocol?"443":"80"),LANGMEM_SQLITE_PATH:t.join(t.resolve(e.root,i),"memory/langmem/langmem.sqlite"),...r(s)?{PYTHONPATH:mergePythonPath(s)}:{}}}async function waitForHealth(e){for(let r=0;r<60;r+=1){if(await isHealthy(e))return;await new Promise(e=>setTimeout(e,500))}throw new Error(`LangMem service did not become healthy at ${e}`)}async function isHealthy(e){try{const r=await fetch(`${e.replace(/\/+$/u,"")}/health`,{signal:AbortSignal.timeout(1e3)}),t=await r.json();return r.ok&&!0===t.ok}catch{return!1}}function mergePythonPath(e){return process.env.PYTHONPATH?`${e}${t.delimiter}${process.env.PYTHONPATH}`:e}function readRecord(e){return"object"!=typeof e||null===e||Array.isArray(e)?void 0:e}function readString(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function readStringRecord(e){const r=readRecord(e);return Object.fromEntries(Object.entries(r??{}).filter(e=>"string"==typeof e[1]))}
1
+ import{spawn as e}from"node:child_process";import{existsSync as r}from"node:fs";import t from"node:path";import{fileURLToPath as n}from"node:url";import{DEFAULT_LANGMEM_BASE_URL as o}from"./defaults.js";export async function ensureCliMemoryServices(r){const t=function readLangMemServiceConfig(e){const r=readRecord(e.runtime.memory?.LangMem)??readRecord(e.runtime.memory?.langmem);if(!function shouldAutoStart(e,r){return!1!==(e.runtime.memory??{}).enabled&&!1!==r?.enabled&&(!1!==r?.read||!1!==r?.write)&&[...e.memories.values()].some(e=>e.enabled&&"langmem"===e.provider)}(e,r))return;const t=readString(r?.baseUrl)??readString(r?.url)??process.env.STABLE_HARNESS_LANGMEM_URL??o;return{baseUrl:t,autoStart:!1!==r?.autoStart,command:readString(r?.command)??"python3",args:(n=r?.args,(Array.isArray(n)?n.filter(e=>"string"==typeof e&&e.trim().length>0):void 0)??["-m","stable_harness_langmem_service"]),env:{...defaultLangMemEnv(e,t),...readStringRecord(r?.env)}};var n}(r);if(!t||!t.autoStart||!function isLocalBaseUrl(e){const r=new URL(e);return["localhost","127.0.0.1","::1"].includes(r.hostname)}(t.baseUrl)||await isHealthy(t.baseUrl))return;const n=e(t.command,t.args,{cwd:r.root,detached:!0,env:{...process.env,...t.env},stdio:"ignore"});n.unref(),await async function waitForStartedService(e,r){await Promise.race([waitForHealth(r.baseUrl),new Promise((r,t)=>e.once("error",t)),new Promise((t,n)=>{e.once("exit",(e,t)=>{n(new Error(`LangMem service exited before becoming healthy: ${r.command} code=${e??"null"} signal=${t??"null"}`))})})])}(n,t)}function defaultLangMemEnv(e,o){const a=new URL(o),i=readString(e.runtime.dataRoot)??".stable-harness",s=t.resolve(function packageRoot(){return t.resolve(t.dirname(n(import.meta.url)),"../../../../..")}(),"services/langmem-python/src");return{HOST:"localhost"===a.hostname?"127.0.0.1":a.hostname,PORT:a.port||("https:"===a.protocol?"443":"80"),LANGMEM_SQLITE_PATH:t.join(t.resolve(e.root,i),"memory/langmem/langmem.sqlite"),...r(s)?{PYTHONPATH:mergePythonPath(s)}:{}}}async function waitForHealth(e){for(let r=0;r<60;r+=1){if(await isHealthy(e))return;await new Promise(e=>setTimeout(e,500))}throw new Error(`LangMem service did not become healthy at ${e}`)}async function isHealthy(e){try{const r=await fetch(`${e.replace(/\/+$/u,"")}/health`,{signal:AbortSignal.timeout(1e3)}),t=await r.json();return r.ok&&!0===t.ok}catch{return!1}}function mergePythonPath(e){return process.env.PYTHONPATH?`${e}${t.delimiter}${process.env.PYTHONPATH}`:e}function readRecord(e){return"object"!=typeof e||null===e||Array.isArray(e)?void 0:e}function readString(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function readStringRecord(e){const r=readRecord(e);return Object.fromEntries(Object.entries(r??{}).filter(e=>"string"==typeof e[1]))}
@@ -1 +1 @@
1
- import{createLangMemServiceProvider as e}from"@stable-harness/memory";export function createCliMemoryProviders(r){const o=readRecord(r.runtime.memory?.LangMem)??readRecord(r.runtime.memory?.langmem);if(!function shouldEnableLangMemProvider(e,r){return!1!==(e.runtime.memory??{}).enabled&&!1!==r?.enabled&&(!1!==r?.read||!1!==r?.write)&&[...e.memories.values()].some(e=>e.enabled&&"langmem"===e.provider)}(r,o))return[];const d=readString(o?.baseUrl)??readString(o?.url)??process.env.STABLE_HARNESS_LANGMEM_URL;return d?[e({baseUrl:d,timeoutMs:(n=o?.timeoutMs,("number"==typeof n&&Number.isFinite(n)?n:void 0)??readEnvNumber("STABLE_HARNESS_LANGMEM_TIMEOUT_MS")),config:readProviderConfig(o)})]:[];var n}function readProviderConfig(e){return{provider:"langmem-service",...readRecord(e?.mode)?{mode:readRecord(e?.mode)}:{},...readRecord(e?.types)?{types:readRecord(e?.types)}:{},...readRecord(e?.approval)?{approval:readRecord(e?.approval)}:{},...readRecord(e?.defaults)?{defaults:readRecord(e?.defaults)}:{}}}function readRecord(e){return"object"!=typeof e||null===e||Array.isArray(e)?void 0:e}function readString(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function readEnvNumber(e){const r=process.env[e];return r?Number(r):void 0}
1
+ import{createLangMemServiceProvider as e}from"@stable-harness/memory";import{DEFAULT_LANGMEM_BASE_URL as r}from"./defaults.js";export function createCliMemoryProviders(o){const d=readRecord(o.runtime.memory?.LangMem)??readRecord(o.runtime.memory?.langmem);if(!function shouldEnableLangMemProvider(e,r){return!1!==(e.runtime.memory??{}).enabled&&!1!==r?.enabled&&(!1!==r?.read||!1!==r?.write)&&[...e.memories.values()].some(e=>e.enabled&&"langmem"===e.provider)}(o,d))return[];const a=readString(d?.baseUrl)??readString(d?.url)??process.env.STABLE_HARNESS_LANGMEM_URL??r;return[e({baseUrl:a,timeoutMs:(n=d?.timeoutMs,("number"==typeof n&&Number.isFinite(n)?n:void 0)??readEnvNumber("STABLE_HARNESS_LANGMEM_TIMEOUT_MS")),config:readProviderConfig(d)})];var n}function readProviderConfig(e){return{provider:"langmem-service",...readRecord(e?.mode)?{mode:readRecord(e?.mode)}:{},...readRecord(e?.types)?{types:readRecord(e?.types)}:{},...readRecord(e?.approval)?{approval:readRecord(e?.approval)}:{},...readRecord(e?.defaults)?{defaults:readRecord(e?.defaults)}:{}}}function readRecord(e){return"object"!=typeof e||null===e||Array.isArray(e)?void 0:e}function readString(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function readEnvNumber(e){const r=process.env[e];return r?Number(r):void 0}
@@ -15,6 +15,9 @@ export declare function runMemoryPlugins(input: {
15
15
  }): Promise<void>;
16
16
  export declare function recallMemoryPlugins(input: {
17
17
  providers: MemoryProvider[] | undefined;
18
+ emit?: RuntimeEmit;
19
+ requestId?: string;
20
+ sessionId?: string;
18
21
  request: RuntimeRequest;
19
22
  agent: WorkspaceAgent;
20
23
  workspace: CompiledWorkspace;
@@ -1 +1 @@
1
- import{formatError as e,readRecord as r,readWorkspaceId as t,resolveEnabledMemories as n,resolveMemoryProvider as o,resolvePluginNamespace as a}from"./memory-plugins/shared.js";export{resolveEnabledMemories,resolvePluginNamespace}from"./memory-plugins/shared.js";export{createLangMemMaintenanceTarget,createMemoryMaintenanceDaemon,createSkillCandidateMinerTarget}from"./memory-plugins/maintenance.js";export async function runMemoryPlugins(e){const r=n(e.workspace,"write");if(e.providers?.length&&0!==r.length&&!1!==e.request.metadata?.memoryWrite)for(const t of r)await runMemoryPlugin(e,t)}export async function recallMemoryPlugins(e){const r=n(e.workspace,"recall");if(!e.providers?.length||0===r.length)return[];const t=await Promise.all(r.map(async r=>{try{return await async function recallMemoryPlugin(e,r){const t=o(e.providers??[],r.provider);if(!t)return;const n=a(e.workspace,e.agent,e.request,r),s=await t.search({namespace:n,query:buildRecallQuery(e),limit:readRecallLimit(e.workspace)});return{namespace:n,records:s,context:formatRecallContext(e.workspace,s)}}(e,r)}catch{return}}));return t.filter(e=>Boolean(e?.context))}async function runMemoryPlugin(r,t){const n=o(r.providers??[],t.provider);if(!n)return;const s=a(r.workspace,r.agent,r.request,t);r.emit({type:"runtime.memory.plugin.started",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s});try{const e=await n.propose(function createPluginProposeInput(e,r,t){return{namespace:t,content:[`User input:\n${e.request.input}`,`Agent output:\n${e.result.text}`].join("\n\n"),sourceType:"runtime-run",sourceRef:e.requestId,metadata:{memoryId:r.id,provider:r.provider,profile:r.profile,mode:r.mode,prompts:r.prompts,workspaceRoot:e.workspace.root,agentId:e.agent.id,sessionId:e.sessionId,requestMetadata:e.request.metadata}}}(r,t,s));r.emit({type:"runtime.memory.plugin.completed",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s,candidateCount:e.length})}catch(o){r.emit({type:"runtime.memory.plugin.failed",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s,error:e(o)})}}function buildRecallQuery(e){const r=[`task: ${e.request.input}`,`workspace: ${t(e.workspace)}`,`agent: ${e.agent.id}`,"memory_needed: durable preferences, workspace facts, reusable procedures, prior corrections"],n=function readRecentContext(e){return"string"==typeof e?.recentContext?e.recentContext.slice(0,3e3):Array.isArray(e?.recentTurns)?e.recentTurns.filter(e=>"string"==typeof e).slice(-6).join("\n").slice(0,3e3):void 0}(e.request.metadata);return n?[...r,`recent_context: ${n}`].join("\n"):r.join("\n")}function readRecallLimit(e){const t=r(e.runtime.memory?.LangMem),n=r(t?.recall),o=n?.topK??n?.limit;return"number"==typeof o&&Number.isFinite(o)?o:10}function formatRecallContext(e,t){const n=function readRecallContextLimits(e){const t=r(e.runtime.memory?.LangMem),n=r(t?.recall);return{maxContextChars:readPositiveNumber(n?.maxContextChars)??4e3,maxRecordChars:readPositiveNumber(n?.maxRecordChars)??1e3}}(e),o=[];let a=n.maxContextChars;for(const e of t){if(a<=0)break;const r=truncateText(formatRecallRecord(e),Math.min(n.maxRecordChars,a));r.trim()&&(o.push(r),a-=r.length+1)}return o.join("\n")}function formatRecallRecord(e){return`- ${e.summary??e.content}\n ${e.content}`}function readPositiveNumber(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?Math.floor(e):void 0}function truncateText(e,r){return e.length>r?`${e.slice(0,Math.max(0,r-13))}\n [truncated]`:e}
1
+ import{formatError as e,readRecord as r,readWorkspaceId as t,resolveEnabledMemories as n,resolveMemoryProvider as o,resolvePluginNamespace as a}from"./memory-plugins/shared.js";export{resolveEnabledMemories,resolvePluginNamespace}from"./memory-plugins/shared.js";export{createLangMemMaintenanceTarget,createMemoryMaintenanceDaemon,createSkillCandidateMinerTarget}from"./memory-plugins/maintenance.js";export async function runMemoryPlugins(e){const r=n(e.workspace,"write");if(e.providers?.length&&0!==r.length&&!1!==e.request.metadata?.memoryWrite)for(const t of r)await runMemoryPlugin(e,t)}export async function recallMemoryPlugins(e){const r=n(e.workspace,"recall");if(!e.providers?.length||0===r.length)return[];const t=await Promise.all(r.map(async r=>{try{return await async function recallMemoryPlugin(e,r){const t=o(e.providers??[],r.provider);if(!t)return;const n=a(e.workspace,e.agent,e.request,r),s=await t.search({namespace:n,query:buildRecallQuery(e),limit:readRecallLimit(e.workspace)});return e.emit&&e.requestId&&e.sessionId&&e.emit({type:"runtime.memory.recall.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,namespace:n,recordIds:s.map(e=>e.id),context:formatRecallContext(e.workspace,s)}),{namespace:n,records:s,context:formatRecallContext(e.workspace,s)}}(e,r)}catch{return}}));return t.filter(e=>Boolean(e?.context))}async function runMemoryPlugin(r,t){const n=o(r.providers??[],t.provider);if(!n)return;const s=a(r.workspace,r.agent,r.request,t);r.emit({type:"runtime.memory.plugin.started",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s});try{const e=await n.propose(function createPluginProposeInput(e,r,t){return{namespace:t,content:[`User input:\n${e.request.input}`,`Agent output:\n${e.result.text}`].join("\n\n"),sourceType:"runtime-run",sourceRef:e.requestId,metadata:{memoryId:r.id,provider:r.provider,profile:r.profile,mode:r.mode,prompts:r.prompts,workspaceRoot:e.workspace.root,agentId:e.agent.id,sessionId:e.sessionId,requestMetadata:e.request.metadata}}}(r,t,s));r.emit({type:"runtime.memory.plugin.completed",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s,candidateCount:e.length})}catch(o){r.emit({type:"runtime.memory.plugin.failed",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s,error:e(o)})}}function buildRecallQuery(e){const r=[`task: ${e.request.input}`,`workspace: ${t(e.workspace)}`,`agent: ${e.agent.id}`,"memory_needed: durable preferences, workspace facts, reusable procedures, prior corrections"],n=function readRecentContext(e){return"string"==typeof e?.recentContext?e.recentContext.slice(0,3e3):Array.isArray(e?.recentTurns)?e.recentTurns.filter(e=>"string"==typeof e).slice(-6).join("\n").slice(0,3e3):void 0}(e.request.metadata);return n?[...r,`recent_context: ${n}`].join("\n"):r.join("\n")}function readRecallLimit(e){const t=r(e.runtime.memory?.LangMem),n=r(t?.recall),o=n?.topK??n?.limit;return"number"==typeof o&&Number.isFinite(o)?o:10}function formatRecallContext(e,t){const n=function readRecallContextLimits(e){const t=r(e.runtime.memory?.LangMem),n=r(t?.recall);return{maxContextChars:readPositiveNumber(n?.maxContextChars)??4e3,maxRecordChars:readPositiveNumber(n?.maxRecordChars)??1e3}}(e),o=[];let a=n.maxContextChars;for(const e of t){if(a<=0)break;const r=truncateText(formatRecallRecord(e),Math.min(n.maxRecordChars,a));r.trim()&&(o.push(r),a-=r.length+1)}return o.join("\n")}function formatRecallRecord(e){return`- ${e.summary??e.content}\n ${e.content}`}function readPositiveNumber(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?Math.floor(e):void 0}function truncateText(e,r){return e.length>r?`${e.slice(0,Math.max(0,r-13))}\n [truncated]`:e}
@@ -5,6 +5,8 @@ import type { RuntimeSandboxDecision } from "./tool-gateway.js";
5
5
  import type { RuntimeToolFailureClassification, RuntimeToolFailureReason } from "./tool-failure.js";
6
6
  export type RuntimeInventoryRepairLayer = "agent" | "workflow_route" | "workflow" | "tool" | "task" | "skill";
7
7
  export type RuntimeInventoryRepairStatus = "repaired" | "blocked";
8
+ export type RuntimeRepairLayer = "adapter_error" | "result_output" | "execution_contract" | "evidence_synthesis";
9
+ export type RuntimeRepairOutcome = "retried" | "synthesized" | "blocked";
8
10
  export type RuntimeInventoryRepairDiagnostic = {
9
11
  layer: RuntimeInventoryRepairLayer;
10
12
  owner: "stable_runtime_policy" | "protocol_adapter" | "upstream_backend" | "workspace_config";
@@ -56,6 +58,23 @@ export type RuntimeEvent = RuntimeEventMetadata & ({
56
58
  agentId: string;
57
59
  reason: string;
58
60
  missingEvidenceTools?: string[];
61
+ } | {
62
+ type: "runtime.repair.started";
63
+ requestId: string;
64
+ sessionId: string;
65
+ agentId: string;
66
+ layer: RuntimeRepairLayer;
67
+ attempt?: number;
68
+ reason?: string;
69
+ } | {
70
+ type: "runtime.repair.completed";
71
+ requestId: string;
72
+ sessionId: string;
73
+ agentId: string;
74
+ layer: RuntimeRepairLayer;
75
+ outcome: RuntimeRepairOutcome;
76
+ attempt?: number;
77
+ reason?: string;
59
78
  } | {
60
79
  type: "runtime.inventory.repair";
61
80
  requestId: string;
@@ -1 +1 @@
1
- import{recallMemoryPlugins as e,runMemoryPlugins as r}from"../memory-plugins.js";export function emitMemoryLifecycle(e,r,s,t,o,a){e&&r({type:"runtime.memory.lifecycle",requestId:s,sessionId:t,agentId:o,hook:a})}export async function runMemoryRecall(e){if(!e.memory)return;if(emitMemoryLifecycle(e.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"read-before-plan"),!1===e.request.memory?.recall)return;const r=resolveMemoryNamespace(e.workspace,e.agent,e.request),s=e.request.memory?.recall?.query??e.request.input,t=await e.memory.recall({namespace:r,query:s,limit:e.request.memory?.recall?.limit});return e.emit({type:"runtime.memory.recall.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,namespace:r,recordIds:t.records.map(e=>e.id),context:t.context}),{namespace:r,records:t.records,context:t.context}}export async function submitMemoryCandidates(e){if(!e.memory||!e.request.memory?.candidates?.length)return;emitMemoryLifecycle(e.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"write-after-run");const r=resolveMemoryNamespace(e.workspace,e.agent,e.request);for(const s of e.request.memory.candidates){const t={...s,namespace:s.namespace??r},o=await e.memory.submitCandidate(t);if(e.emit({type:"runtime.memory.candidate.submitted",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,candidate:o.candidate,decision:o.decision,record:o.record}),"review"===o.decision.action&&e.approvals){const r=await e.approvals.create({kind:"memory_write",reason:o.decision.reason,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,subject:{candidate:o.candidate,decision:o.decision}});e.emit({type:"runtime.memory.approval.requested",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,approval:r})}}}export function createMemoryRuntimeCapability(s){return{id:"runtime.memory",beforeAdapterRun:async r=>({memory:await runMemoryRecall({memory:s.memory,emit:r.emit,request:r.request,requestId:r.requestId,sessionId:r.sessionId,agent:r.agent,workspace:r.workspace}),pluginMemories:await e({providers:s.memoryProviders,request:r.request,agent:r.agent,workspace:r.workspace})}),async beforeAdapterResultContract(e){emitMemoryLifecycle(s.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"read-before-finalize"),await submitMemoryCandidates({memory:s.memory,approvals:s.approvals,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,workspace:e.workspace})},async afterAdapterResponse(e){await r({providers:s.memoryProviders,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,workspace:e.workspace,result:e.result})}}}function resolveMemoryNamespace(e,r,s){return s.memory?.namespace??`${e.root}:${r.id}`}
1
+ import{recallMemoryPlugins as e,runMemoryPlugins as r}from"../memory-plugins.js";export function emitMemoryLifecycle(e,r,s,t,o,a){e&&r({type:"runtime.memory.lifecycle",requestId:s,sessionId:t,agentId:o,hook:a})}export async function runMemoryRecall(e){if(!e.memory)return;if(emitMemoryLifecycle(e.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"read-before-plan"),!1===e.request.memory?.recall)return;const r=resolveMemoryNamespace(e.workspace,e.agent,e.request),s=e.request.memory?.recall?.query??e.request.input,t=await e.memory.recall({namespace:r,query:s,limit:e.request.memory?.recall?.limit});return e.emit({type:"runtime.memory.recall.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,namespace:r,recordIds:t.records.map(e=>e.id),context:t.context}),{namespace:r,records:t.records,context:t.context}}export async function submitMemoryCandidates(e){if(!e.memory||!e.request.memory?.candidates?.length)return;emitMemoryLifecycle(e.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"write-after-run");const r=resolveMemoryNamespace(e.workspace,e.agent,e.request);for(const s of e.request.memory.candidates){const t={...s,namespace:s.namespace??r},o=await e.memory.submitCandidate(t);if(e.emit({type:"runtime.memory.candidate.submitted",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,candidate:o.candidate,decision:o.decision,record:o.record}),"review"===o.decision.action&&e.approvals){const r=await e.approvals.create({kind:"memory_write",reason:o.decision.reason,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,subject:{candidate:o.candidate,decision:o.decision}});e.emit({type:"runtime.memory.approval.requested",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,approval:r})}}}export function createMemoryRuntimeCapability(s){return{id:"runtime.memory",beforeAdapterRun:async r=>({memory:await runMemoryRecall({memory:s.memory,emit:r.emit,request:r.request,requestId:r.requestId,sessionId:r.sessionId,agent:r.agent,workspace:r.workspace}),pluginMemories:await e({providers:s.memoryProviders,emit:r.emit,requestId:r.requestId,sessionId:r.sessionId,request:r.request,agent:r.agent,workspace:r.workspace})}),async beforeAdapterResultContract(e){emitMemoryLifecycle(s.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"read-before-finalize"),await submitMemoryCandidates({memory:s.memory,approvals:s.approvals,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,workspace:e.workspace})},async afterAdapterResponse(e){await r({providers:s.memoryProviders,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,workspace:e.workspace,result:e.result})}}}function resolveMemoryNamespace(e,r,s){return s.memory?.namespace??`${e.root}:${r.id}`}
@@ -1 +1 @@
1
- export function projectRuntimePolicies(e){return{systemPromptSections:[skillInventoryPolicy(e),responseLanguagePolicy(e),responsePresentationPolicy(e)].filter(e=>Boolean(e))}}export function buildRuntimeSystemPrompt(e,t){const n=[t,...projectRuntimePolicies(e).systemPromptSections].filter(e=>Boolean(e));return n.length>0?n.join("\n\n"):void 0}function skillInventoryPolicy(e){const t=(e.agent?.skills??[]).map(t=>e.workspace.skills.get(t)).filter(e=>Boolean(e));if(0!==t.length)return["## Stable Harness Skill Inventory","Use only the skills listed in this workspace inventory. Do not infer or invent skill names, skill directories, or SKILL.md paths from generic examples.","Skill files are already registered with the backend. Do not read local SKILL.md files or skill directories through filesystem tools.","If none of these skills match the task, continue with the configured tools and collected evidence instead of reading an unlisted skill path.",t.map(e=>{const t=e.allowedTools.length>0?`; allowed tools: ${e.allowedTools.join(", ")}`:"",n=e.description?`: ${e.description}${t}`:t;return`- ${e.id}${n}`}).join("\n")].join("\n")}function responseLanguagePolicy(e){const t=readRecord(e.workspace.runtime.responseLanguage);if("matchUser"!==(readString(t.mode)??readString(t.strategy)))return;const n=function detectRequestLanguage(e){return/\p{Script=Han}/u.test(e)?"Chinese":/[\p{Script=Hiragana}\p{Script=Katakana}]/u.test(e)?"Japanese":/\p{Script=Hangul}/u.test(e)?"Korean":/\p{Script=Arabic}/u.test(e)?"Arabic":/\p{Script=Hebrew}/u.test(e)?"Hebrew":/\p{Script=Thai}/u.test(e)?"Thai":/\p{Script=Cyrillic}/u.test(e)?"Cyrillic-script language":void 0}(e.request.input);return["Stable runtime response language policy:",...n?[`- Detected request language: ${n}.`]:[],"- Match the final answer language to the original user request unless the user explicitly asks for another language.","- If tool or subagent evidence is in a different language, translate the final user-facing answer into the detected request language.","- When delegating to subagents, include the same response-language requirement in delegated instructions.","- Do not call another tool or subagent only to translate, rewrite, format, or synthesize a completed answer.",`Original user request:\n${e.request.input}`].join("\n")}function responsePresentationPolicy(e){const t=readRecord(e.workspace.runtime.responsePresentation);if(!0===t.enabled&&!function hasStructuredResponseFormat(e){return void 0!==e?.config.responseFormat||isRecord(e?.config.deepagents)&&void 0!==e.config.deepagents.responseFormat}(e.agent))return"markdown"===(readString(t.style)??"markdown")?["Stable runtime final-answer presentation policy:","- For user-facing natural-language final answers, use GitHub-flavored Markdown.","- Prefer clear section headings, short paragraphs, and concise bullets over dense prose.","- Use tables only when they make comparison or planning details easier to scan.","- For detailed investigations, plans, or reports, include assumptions, findings, recommendations, and concrete next steps.","- Preserve exact plain text, JSON, code, or other structured output when the user or response format asks for it.","- Do not end with generic follow-up offers; deliver the requested answer directly."].join("\n"):void 0}function readRecord(e){return isRecord(e)?e:{}}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
1
+ export function projectRuntimePolicies(e){return{systemPromptSections:[skillInventoryPolicy(e),responseLanguagePolicy(e),responsePresentationPolicy(e)].filter(e=>Boolean(e))}}export function buildRuntimeSystemPrompt(e,t){const n=[t,...projectRuntimePolicies(e).systemPromptSections].filter(e=>Boolean(e));return n.length>0?n.join("\n\n"):void 0}function skillInventoryPolicy(e){const t=(e.agent?.skills??[]).map(t=>e.workspace.skills.get(t)).filter(e=>Boolean(e));if(0!==t.length)return["## Stable Harness Skill Inventory","Use only the skills listed in this workspace inventory. Do not infer or invent skill names, skill directories, or SKILL.md paths from generic examples.","When a listed skill matches the task, use DeepAgents progressive disclosure: read that registered SKILL.md path through builtin filesystem tools before applying the detailed workflow.","If none of these skills match the task, continue with the configured tools and collected evidence instead of reading an unlisted skill path.",t.map(e=>{const t=e.allowedTools.length>0?`; allowed tools: ${e.allowedTools.join(", ")}`:"",n=e.description?`: ${e.description}${t}`:t;return`- ${e.id}${n}`}).join("\n")].join("\n")}function responseLanguagePolicy(e){const t=readRecord(e.workspace.runtime.responseLanguage);if("matchUser"!==(readString(t.mode)??readString(t.strategy)))return;const n=function detectRequestLanguage(e){return/\p{Script=Han}/u.test(e)?"Chinese":/[\p{Script=Hiragana}\p{Script=Katakana}]/u.test(e)?"Japanese":/\p{Script=Hangul}/u.test(e)?"Korean":/\p{Script=Arabic}/u.test(e)?"Arabic":/\p{Script=Hebrew}/u.test(e)?"Hebrew":/\p{Script=Thai}/u.test(e)?"Thai":/\p{Script=Cyrillic}/u.test(e)?"Cyrillic-script language":void 0}(e.request.input);return["Stable runtime response language policy:",...n?[`- Detected request language: ${n}.`]:[],"- Match the final answer language to the original user request unless the user explicitly asks for another language.","- If tool or subagent evidence is in a different language, translate the final user-facing answer into the detected request language.","- When delegating to subagents, include the same response-language requirement in delegated instructions.","- Do not call another tool or subagent only to translate, rewrite, format, or synthesize a completed answer.",`Original user request:\n${e.request.input}`].join("\n")}function responsePresentationPolicy(e){const t=readRecord(e.workspace.runtime.responsePresentation);if(!0===t.enabled&&!function hasStructuredResponseFormat(e){return void 0!==e?.config.responseFormat||isRecord(e?.config.deepagents)&&void 0!==e.config.deepagents.responseFormat}(e.agent))return"markdown"===(readString(t.style)??"markdown")?["Stable runtime final-answer presentation policy:","- For user-facing natural-language final answers, use GitHub-flavored Markdown.","- Prefer clear section headings, short paragraphs, and concise bullets over dense prose.","- Use tables only when they make comparison or planning details easier to scan.","- For detailed investigations, plans, or reports, include assumptions, findings, recommendations, and concrete next steps.","- Preserve exact plain text, JSON, code, or other structured output when the user or response format asks for it.","- Do not end with generic follow-up offers; deliver the requested answer directly."].join("\n"):void 0}function readRecord(e){return isRecord(e)?e:{}}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
@@ -1 +1 @@
1
- export function resolveProgressNarrator(e){if(!1===e.options)return;const t=readProgressPolicy(e.policy);return e.options?.enabled??t.enabled?e.options?.provider??function createTemplateProgressNarrator(){const e=new Map,t=new Map;return{name:"template",narrate(r,n){var o;"runtime.request.started"===r.type&&(e.set(r.requestId,{language:(o=r.input??"",/\p{Script=Han}/u.test(o)?"zh":void 0),input:r.input}),t.delete(r.requestId));const i=function templateMessage(e,t){const r="zh"===t?.language;return"runtime.request.started"===e.type?r?`我开始处理这个请求:${summarizeText(e.input)}`:`I'm starting on this request: ${summarizeText(e.input)}`:"runtime.request.completed"===e.type?r?"我已经完成执行链,正在交付最终结果。":"I've finished the execution chain and am returning the final result.":"runtime.request.failed"===e.type?r?"执行链失败了,我会保留具体错误方便定位。":"The execution chain failed; I'm keeping the concrete error visible for diagnosis.":"runtime.request.cancelled"===e.type?r?"这个请求已取消,后续执行会停止。":"The request was cancelled, so the remaining execution will stop.":"runtime.tool.direct.started"===e.type?r?`我正在运行 ${e.toolId}。`:`I'm running ${e.toolId}.`:"runtime.tool.direct.completed"===e.type?r?`${e.toolId} 已返回结果,我会继续使用这份证据。`:`${e.toolId} returned; I'll keep using that evidence.`:"runtime.workflow.started"===e.type?r?`我正在启动 workflow ${e.workflowId}。`:`I'm starting workflow ${e.workflowId}.`:"runtime.workflow.completed"===e.type?r?`workflow ${e.workflowId} 已完成。`:`Workflow ${e.workflowId} is complete.`:"runtime.specDriven.phase.started"===e.type?r?`我正在进入 spec-driven 阶段 ${e.phaseId}。`:`I'm starting spec-driven phase ${e.phaseId}.`:"runtime.specDriven.phase.blocked"===e.type?r?`spec-driven 阶段 ${e.phaseId} 被 gate 阻塞。`:`Spec-driven phase ${e.phaseId} is blocked by a gate.`:"runtime.specDriven.phase.completed"===e.type?r?`spec-driven 阶段 ${e.phaseId} 已完成。`:`Spec-driven phase ${e.phaseId} is complete.`:"runtime.specDriven.phase.verified"===e.type?r?`spec-driven 阶段 ${e.phaseId} 已验证。`:`Spec-driven phase ${e.phaseId} is verified.`:"runtime.artifact.created"===e.type?r?"我已经保存一份运行产物。":"I've saved a runtime artifact.":"runtime.execution.contract.failed"===e.type?r?"运行证据没有满足执行契约,我会进入恢复或失败路径。":"The run evidence did not satisfy the execution contract, so I'll recover or fail explicitly.":"runtime.inventory.repair"===e.type?inventoryRepairMessage(e.status,e.diagnostic.layer,r):"runtime.skill.candidate.created"===e.type?r?`我发现一个可沉淀的 skill 候选:${e.name}。`:`I found a reusable skill candidate: ${e.name}.`:e.type.startsWith("runtime.memory.")?function memoryMessage(e,t){return"runtime.memory.lifecycle"===e.type?t?`我进入记忆阶段:${e.hook}。`:`I'm in the memory lifecycle phase: ${e.hook}.`:"runtime.memory.recall.completed"===e.type?t?`我召回了 ${e.recordIds.length} 条相关记忆。`:`I recalled ${e.recordIds.length} relevant memory records.`:"runtime.memory.candidate.submitted"===e.type?t?"我提交了一条候选记忆。":"I submitted a memory candidate.":"runtime.memory.approval.requested"===e.type?t?"我提交了记忆审批请求。":"I requested memory approval.":"runtime.memory.plugin.started"===e.type?t?`我正在运行记忆插件 ${e.provider}。`:`I'm running memory plugin ${e.provider}.`:"runtime.memory.plugin.completed"===e.type?t?`记忆插件 ${e.provider} 已完成。`:`Memory plugin ${e.provider} completed.`:"runtime.memory.plugin.failed"===e.type?t?`记忆插件 ${e.provider} 失败了;主任务会继续,不把它当成执行结果。`:`Memory plugin ${e.provider} failed; the main task will continue without treating it as the result.`:"runtime.memory.maintenance.started"===e.type?t?`我正在维护 ${e.target} 记忆。`:`I'm maintaining ${e.target} memory.`:"runtime.memory.maintenance.completed"===e.type?t?`${e.target} 记忆维护完成。`:`${e.target} memory maintenance completed.`:"runtime.memory.maintenance.failed"===e.type?t?`${e.target} 记忆维护失败。`:`${e.target} memory maintenance failed.`:void 0}(e,r):"runtime.adapter.event"===e.type?function adapterMessage(e,t){if(isRecord(e)){if("agent.handoff"===e.phase)return t?"我把请求交给上游 agent backend,让它负责规划和执行。":"I'm handing the request to the upstream agent backend for planning and execution.";if(function isToolStartEvent(e){return"deepagents.tool_execution.start"===e.eventType||"agent.tool.start"===e.phase}(e)&&"string"==typeof e.toolId)return function toolStartMessage(e,t,r){if("task"===e){const e=function readTaskTarget(e){const t=isRecord(e)?e:{};return readString(t.subagent_type)??readString(t.subagentType)}(t),n=function readDescription(e){const t=isRecord(e)?e:{};return summarizeText(readString(t.description)??readString(t.task))}(t);if(e&&n)return r?`我正在请求 task 工具委派给 ${e}:${n}`:`I'm asking the task tool to delegate to ${e}: ${n}`;if(e)return r?`我正在请求 task 工具委派给 ${e}。`:`I'm asking the task tool to delegate to ${e}.`}return r?`我正在运行 ${e} 收集证据。`:`I'm running ${e} to gather evidence.`}(e.toolId,e.args,t);if(function isToolResultEvent(e){return"deepagents.tool_execution.result"===e.eventType||"agent.tool.result"===e.phase}(e)&&"string"==typeof e.toolId)return function toolResultMessage(e,t,r,n,o){if(r)return o?`${e} 返回错误:${summarizeText(String(r))}`:`${e} returned an error: ${summarizeText(String(r))}`;const i="string"==typeof n?n:function readToolControlStatus(e){const t=function parseToolOutputRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e);return"string"==typeof t?.status?t.status:"string"==typeof t?.error?t.error:"string"==typeof e&&e.startsWith("Task delegation target is not in the workspace inventory")?"task_inventory_blocked":void 0}(t);if(i)return function toolControlMessage(e,t,r){return"duplicate_tool_call"===t?r?`${e} 重复调用已复用已有证据。`:`${e} repeated an equivalent call, so the existing evidence was reused.`:"repeated_tool_call_limit"===t?r?`${e} 出现重复调用循环,我会基于已有证据继续收敛。`:`${e} entered a repeated-call loop, so I'll continue from the evidence already collected.`:"tool_argument_error"===t||"tool_argument_validation_failed"===t?r?`${e} 参数被工具 schema 拒绝,我会让 agent 修正参数或改用合适工具。`:`${e} arguments were rejected by the tool schema; I'll have the agent repair them or choose a suitable tool.`:"task_inventory_blocked"===t?r?"task 委派目标不在当前 workspace inventory 中,已被运行时策略阻止。":"The task delegation target is not in the current workspace inventory and was blocked by runtime policy.":r?`${e} 返回运行时控制状态:${t}。`:`${e} returned runtime control status: ${t}.`}(e,i,o);if("task"===e)return o?"委派任务已返回结果,我会基于这些证据继续推进。":"The delegated task returned; I'll keep going with that evidence.";const a=function summarizeToolOutput(e){if("string"==typeof e)return summarizeText(e);if(isRecord(e)){if("string"==typeof e.status)return summarizeText(e.status);if("string"==typeof e.summary)return summarizeText(e.summary)}}(t);return o?`${e} 已返回${a?`:${a}`:",我会继续判断下一步。"}`:`${e} returned${a?`: ${a}`:"; I'll decide the next step from here."}`}(e.toolId,e.output,e.error,e.controlStatus,t);if("agent.langgraph.invoke"===e.phase)return t?"我正在调用 workflow backend。":"I'm invoking the workflow backend.";if("agent.node.completed"===e.phase&&"string"==typeof e.nodeId)return t?`节点 ${e.nodeId} 已完成。`:`Node ${e.nodeId} is complete.`;if("inventory.repair"===e.phase&&"string"==typeof e.status){const r=isRecord(e.diagnostic)?e.diagnostic:{};return inventoryRepairMessage(e.status,readString(r.layer)??"selection",t)}}}(e.event,r):void 0}(r,e.get(r.requestId));if(i&&i!==t.get(r.requestId))return t.set(r.requestId,i),"runtime.request.failed"!==r.type&&"runtime.request.cancelled"!==r.type||(e.delete(r.requestId),t.delete(r.requestId)),function pruneRequestState(e,t){for(;e.size>200;){const r=e.keys().next().value;if(!r)break;e.delete(r),t.delete(r)}}(e,t),{message:i,style:n.style,model:n.model}}}}():void 0}export function createProgressNarrationEvent(e){if(!e.narrator||"runtime.progress.narration"===e.source.type)return;const t=readProgressPolicy(e.policy),r=!1===e.options?void 0:e.options,n=e.narrator.narrate(e.source,{style:r?.style??t.style,model:r?.model??t.model});return function isPromiseLike(e){return isRecord(e)&&"function"==typeof e.then}(n)?n.then(t=>toNarrationEvent(e.source,e.narrator,t)):toNarrationEvent(e.source,e.narrator,n)}export function createProgressNarrationCapability(e){const t=resolveProgressNarrator(e);if(t)return{id:"runtime.progress.narration",onEvent(r,n){try{const o=createProgressNarrationEvent({source:r,narrator:t,options:e.options,policy:e.policy});!function isRuntimeEventPromise(e){return isRecord(e)&&"function"==typeof e.then}(o)?o&&n(o):o.then(e=>{e&&n(e)}).catch(()=>{})}catch{return}}}}function toNarrationEvent(e,t,r){if(r?.message.trim())return{type:"runtime.progress.narration",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agentId,message:r.message,provider:t.name,sourceEventTypes:r.sourceEventTypes??[e.type],sourceEventIds:r.sourceEventIds??(e.eventId?[e.eventId]:void 0),model:r.model,style:r.style}}function inventoryRepairMessage(e,t,r){return"repaired"===e?r?`${t} 选择已按 workspace inventory 修正。`:`${t} selection was repaired against the workspace inventory.`:r?`${t} 选择不在 workspace inventory 中,已被阻止。`:`${t} selection was blocked because it is outside the workspace inventory.`}function summarizeText(e){const t=e?.replace(/\s+/gu," ").trim();return t?t.length>120?`${t.slice(0,117)}...`:t:""}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readProgressPolicy(e){const t=isRecord(e?.progress)?e.progress:{},r=isRecord(t.narration)?t.narration:{};return{enabled:"boolean"==typeof r.enabled?r.enabled:void 0,style:"string"==typeof r.style?r.style:void 0,model:"string"==typeof r.model?r.model:void 0}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
1
+ export function resolveProgressNarrator(e){if(!1===e.options)return;const t=readProgressPolicy(e.policy);return e.options?.enabled??t.enabled?e.options?.provider??function createTemplateProgressNarrator(){const e=new Map,t=new Map;return{name:"template",narrate(r,n){var o;"runtime.request.started"===r.type&&(e.set(r.requestId,{language:(o=r.input??"",/\p{Script=Han}/u.test(o)?"zh":void 0),input:r.input}),t.delete(r.requestId));const i=function templateMessage(e,t){const r="zh"===t?.language;return"runtime.request.started"===e.type?r?`我开始处理这个请求:${summarizeText(e.input)}`:`I'm starting on this request: ${summarizeText(e.input)}`:"runtime.request.completed"===e.type?r?"我已经完成执行链,正在交付最终结果。":"I've finished the execution chain and am returning the final result.":"runtime.request.failed"===e.type?r?"执行链失败了,我会保留具体错误方便定位。":"The execution chain failed; I'm keeping the concrete error visible for diagnosis.":"runtime.request.cancelled"===e.type?r?"这个请求已取消,后续执行会停止。":"The request was cancelled, so the remaining execution will stop.":"runtime.tool.direct.started"===e.type?r?`我正在运行 ${e.toolId}。`:`I'm running ${e.toolId}.`:"runtime.tool.direct.completed"===e.type?r?`${e.toolId} 已返回结果,我会继续使用这份证据。`:`${e.toolId} returned; I'll keep using that evidence.`:"runtime.workflow.started"===e.type?r?`我正在启动 workflow ${e.workflowId}。`:`I'm starting workflow ${e.workflowId}.`:"runtime.workflow.completed"===e.type?r?`workflow ${e.workflowId} 已完成。`:`Workflow ${e.workflowId} is complete.`:"runtime.specDriven.phase.started"===e.type?r?`我正在进入 spec-driven 阶段 ${e.phaseId}。`:`I'm starting spec-driven phase ${e.phaseId}.`:"runtime.specDriven.phase.blocked"===e.type?r?`spec-driven 阶段 ${e.phaseId} 被 gate 阻塞。`:`Spec-driven phase ${e.phaseId} is blocked by a gate.`:"runtime.specDriven.phase.completed"===e.type?r?`spec-driven 阶段 ${e.phaseId} 已完成。`:`Spec-driven phase ${e.phaseId} is complete.`:"runtime.specDriven.phase.verified"===e.type?r?`spec-driven 阶段 ${e.phaseId} 已验证。`:`Spec-driven phase ${e.phaseId} is verified.`:"runtime.artifact.created"===e.type?r?"我已经保存一份运行产物。":"I've saved a runtime artifact.":"runtime.execution.contract.failed"===e.type?r?"运行证据没有满足执行契约,我会进入恢复或失败路径。":"The run evidence did not satisfy the execution contract, so I'll recover or fail explicitly.":"runtime.repair.started"===e.type?repairMessage(e.layer,"started",r):"runtime.repair.completed"===e.type?repairMessage(e.layer,e.outcome,r):"runtime.inventory.repair"===e.type?inventoryRepairMessage(e.status,e.diagnostic.layer,r):"runtime.skill.candidate.created"===e.type?r?`我发现一个可沉淀的 skill 候选:${e.name}。`:`I found a reusable skill candidate: ${e.name}.`:e.type.startsWith("runtime.memory.")?function memoryMessage(e,t){return"runtime.memory.lifecycle"===e.type?t?`我进入记忆阶段:${e.hook}。`:`I'm in the memory lifecycle phase: ${e.hook}.`:"runtime.memory.recall.completed"===e.type?t?`我召回了 ${e.recordIds.length} 条相关记忆。`:`I recalled ${e.recordIds.length} relevant memory records.`:"runtime.memory.candidate.submitted"===e.type?t?"我提交了一条候选记忆。":"I submitted a memory candidate.":"runtime.memory.approval.requested"===e.type?t?"我提交了记忆审批请求。":"I requested memory approval.":"runtime.memory.plugin.started"===e.type?t?`我正在运行记忆插件 ${e.provider}。`:`I'm running memory plugin ${e.provider}.`:"runtime.memory.plugin.completed"===e.type?t?`记忆插件 ${e.provider} 已完成。`:`Memory plugin ${e.provider} completed.`:"runtime.memory.plugin.failed"===e.type?t?`记忆插件 ${e.provider} 失败了;主任务会继续,不把它当成执行结果。`:`Memory plugin ${e.provider} failed; the main task will continue without treating it as the result.`:"runtime.memory.maintenance.started"===e.type?t?`我正在维护 ${e.target} 记忆。`:`I'm maintaining ${e.target} memory.`:"runtime.memory.maintenance.completed"===e.type?t?`${e.target} 记忆维护完成。`:`${e.target} memory maintenance completed.`:"runtime.memory.maintenance.failed"===e.type?t?`${e.target} 记忆维护失败。`:`${e.target} memory maintenance failed.`:void 0}(e,r):"runtime.adapter.event"===e.type?function adapterMessage(e,t){if(isRecord(e)){if("agent.handoff"===e.phase)return t?"我把请求交给上游 agent backend,让它负责规划和执行。":"I'm handing the request to the upstream agent backend for planning and execution.";if(function isToolStartEvent(e){return"deepagents.tool_execution.start"===e.eventType||"agent.tool.start"===e.phase}(e)&&"string"==typeof e.toolId)return function toolStartMessage(e,t,r){if("task"===e){const e=function readTaskTarget(e){const t=isRecord(e)?e:{};return readString(t.subagent_type)??readString(t.subagentType)}(t),n=function readDescription(e){const t=isRecord(e)?e:{};return summarizeText(readString(t.description)??readString(t.task))}(t);if(e&&n)return r?`我正在请求 task 工具委派给 ${e}:${n}`:`I'm asking the task tool to delegate to ${e}: ${n}`;if(e)return r?`我正在请求 task 工具委派给 ${e}。`:`I'm asking the task tool to delegate to ${e}.`}return r?`我正在运行 ${e} 收集证据。`:`I'm running ${e} to gather evidence.`}(e.toolId,e.args,t);if(function isToolResultEvent(e){return"deepagents.tool_execution.result"===e.eventType||"agent.tool.result"===e.phase}(e)&&"string"==typeof e.toolId)return function toolResultMessage(e,t,r,n,o){if(r)return o?`${e} 返回错误:${summarizeText(String(r))}`:`${e} returned an error: ${summarizeText(String(r))}`;const i="string"==typeof n?n:function readToolControlStatus(e){const t=function parseToolOutputRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e);return"string"==typeof t?.status?t.status:"string"==typeof t?.error?t.error:"string"==typeof e&&e.startsWith("Task delegation target is not in the workspace inventory")?"task_inventory_blocked":void 0}(t);if(i)return function toolControlMessage(e,t,r){return"duplicate_tool_call"===t?r?`${e} 重复调用已复用已有证据。`:`${e} repeated an equivalent call, so the existing evidence was reused.`:"repeated_tool_call_limit"===t?r?`${e} 出现重复调用循环,我会基于已有证据继续收敛。`:`${e} entered a repeated-call loop, so I'll continue from the evidence already collected.`:"tool_argument_error"===t||"tool_argument_validation_failed"===t?r?`${e} 参数被工具 schema 拒绝,我会让 agent 修正参数或改用合适工具。`:`${e} arguments were rejected by the tool schema; I'll have the agent repair them or choose a suitable tool.`:"task_inventory_blocked"===t?r?"task 委派目标不在当前 workspace inventory 中,已被运行时策略阻止。":"The task delegation target is not in the current workspace inventory and was blocked by runtime policy.":r?`${e} 返回运行时控制状态:${t}。`:`${e} returned runtime control status: ${t}.`}(e,i,o);if("task"===e)return o?"委派任务已返回结果,我会基于这些证据继续推进。":"The delegated task returned; I'll keep going with that evidence.";const a=function summarizeToolOutput(e){if("string"==typeof e)return summarizeText(e);if(isRecord(e)){if("string"==typeof e.status)return summarizeText(e.status);if("string"==typeof e.summary)return summarizeText(e.summary)}}(t);return o?`${e} 已返回${a?`:${a}`:",我会继续判断下一步。"}`:`${e} returned${a?`: ${a}`:"; I'll decide the next step from here."}`}(e.toolId,e.output,e.error,e.controlStatus,t);if("agent.langgraph.invoke"===e.phase)return t?"我正在调用 workflow backend。":"I'm invoking the workflow backend.";if("agent.node.completed"===e.phase&&"string"==typeof e.nodeId)return t?`节点 ${e.nodeId} 已完成。`:`Node ${e.nodeId} is complete.`;if("inventory.repair"===e.phase&&"string"==typeof e.status){const r=isRecord(e.diagnostic)?e.diagnostic:{};return inventoryRepairMessage(e.status,readString(r.layer)??"selection",t)}}}(e.event,r):void 0}(r,e.get(r.requestId));if(i&&i!==t.get(r.requestId))return t.set(r.requestId,i),"runtime.request.failed"!==r.type&&"runtime.request.cancelled"!==r.type||(e.delete(r.requestId),t.delete(r.requestId)),function pruneRequestState(e,t){for(;e.size>200;){const r=e.keys().next().value;if(!r)break;e.delete(r),t.delete(r)}}(e,t),{message:i,style:n.style,model:n.model}}}}():void 0}export function createProgressNarrationEvent(e){if(!e.narrator||"runtime.progress.narration"===e.source.type)return;const t=readProgressPolicy(e.policy),r=!1===e.options?void 0:e.options,n=e.narrator.narrate(e.source,{style:r?.style??t.style,model:r?.model??t.model});return function isPromiseLike(e){return isRecord(e)&&"function"==typeof e.then}(n)?n.then(t=>toNarrationEvent(e.source,e.narrator,t)):toNarrationEvent(e.source,e.narrator,n)}export function createProgressNarrationCapability(e){const t=resolveProgressNarrator(e);if(t)return{id:"runtime.progress.narration",onEvent(r,n){try{const o=createProgressNarrationEvent({source:r,narrator:t,options:e.options,policy:e.policy});!function isRuntimeEventPromise(e){return isRecord(e)&&"function"==typeof e.then}(o)?o&&n(o):o.then(e=>{e&&n(e)}).catch(()=>{})}catch{return}}}}function toNarrationEvent(e,t,r){if(r?.message.trim())return{type:"runtime.progress.narration",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agentId,message:r.message,provider:t.name,sourceEventTypes:r.sourceEventTypes??[e.type],sourceEventIds:r.sourceEventIds??(e.eventId?[e.eventId]:void 0),model:r.model,style:r.style}}function inventoryRepairMessage(e,t,r){return"repaired"===e?r?`${t} 选择已按 workspace inventory 修正。`:`${t} selection was repaired against the workspace inventory.`:r?`${t} 选择不在 workspace inventory 中,已被阻止。`:`${t} selection was blocked because it is outside the workspace inventory.`}function repairMessage(e,t,r){return r?"started"===t?`runtime 正在执行 ${e} repair。`:"synthesized"===t?`runtime 已通过 ${e} repair 合成可交付结果。`:"blocked"===t?`runtime 已阻止 ${e} repair 的不可靠输出。`:`runtime 已完成 ${e} repair。`:"started"===t?`Runtime is starting ${e} repair.`:"synthesized"===t?`Runtime synthesized a deliverable result through ${e} repair.`:"blocked"===t?`Runtime blocked unreliable output during ${e} repair.`:`Runtime completed ${e} repair.`}function summarizeText(e){const t=e?.replace(/\s+/gu," ").trim();return t?t.length>120?`${t.slice(0,117)}...`:t:""}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readProgressPolicy(e){const t=isRecord(e?.progress)?e.progress:{},r=isRecord(t.narration)?t.narration:{};return{enabled:"boolean"==typeof r.enabled?r.enabled:void 0,style:"string"==typeof r.style?r.style:void 0,model:"string"==typeof r.model?r.model:void 0}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
@@ -0,0 +1,12 @@
1
+ import type { RuntimeEvent, RuntimeOutput, RuntimeRequest, RuntimeStore, WorkspaceAgent } from "../../types.js";
2
+ export declare function recoverAdapterResultOutput(input: {
3
+ request: RuntimeRequest;
4
+ result: RuntimeOutput;
5
+ recoveryPolicy: unknown;
6
+ store: RuntimeStore;
7
+ emit: (event: RuntimeEvent) => void;
8
+ requestId: string;
9
+ sessionId: string;
10
+ agent: WorkspaceAgent;
11
+ runAdapter: (request: RuntimeRequest) => Promise<RuntimeOutput>;
12
+ }): Promise<RuntimeOutput>;
@@ -0,0 +1 @@
1
+ import{assertNoRawToolCallOutput as e,assertNoToolExecutionErrorOutput as t,buildEvidenceSynthesisOutput as r,buildResultRecoveryRequest as o,containsRawToolCallOutput as l,rawToolCallFailureMessage as a,toolCallRecoveryEnabled as u}from"../../recovery/tool-call.js";export async function recoverAdapterResultOutput(s){let i=s.result,n=s.request;const c=function resultRecoveryAttempts(e){const t="object"!=typeof e||null===e||Array.isArray(e)?void 0:e.recovery,r="object"!=typeof t||null===t||Array.isArray(t)?void 0:t.toolCall,o="object"!=typeof r||null===r||Array.isArray(r)?void 0:r.maxResultRecoveryAttempts;return"number"==typeof o&&Number.isInteger(o)&&o>0?o:3}(s.recoveryPolicy);let y=0;for(let e=0;e<c;e+=1){const t=s.store.getRun(s.requestId)?.events??[],r=o({request:n,output:i.text,events:t.slice(y),availableToolIds:s.agent.tools,policy:s.recoveryPolicy});if(!r)break;n=r,y=s.store.getRun(s.requestId)?.events.length??0,emitRepair(s,"runtime.repair.started","result_output",e+1,"recoverable_result_output"),i=await s.runAdapter(r),emitRepair(s,"runtime.repair.completed","result_output",e+1,"recoverable_result_output","retried")}return function finalizeRecoveredOutput(o,s){if(!u(o.recoveryPolicy))return s;let i=!1;l(s.text,o.recoveryPolicy)&&function rawToolCallFailureReturnsMessage(e){return"message"===("object"!=typeof e?.toolCallRecovery||null===e.toolCallRecovery||Array.isArray(e.toolCallRecovery)?{}:e.toolCallRecovery).onFailure}(o.request.metadata)&&(s={...s,text:a(),metadata:{...s.metadata,toolCallRecovery:{failed:!0,reason:"raw_tool_call_output"}}},emitRepair(o,"runtime.repair.completed","result_output",void 0,"raw_tool_call_output","blocked"));const n=r({request:o.request,output:s.text,events:o.store.getRun(o.requestId)?.events??[],policy:o.recoveryPolicy});return n&&(i=!0,s={...s,text:n,metadata:{...s.metadata,toolCallRecovery:{synthesized:!0,reason:"raw_tool_call_output_with_evidence"}}},emitRepair(o,"runtime.repair.completed","evidence_synthesis",void 0,"raw_tool_call_output_with_evidence","synthesized")),i||(e(s.text,o.recoveryPolicy),t(s.text,o.recoveryPolicy)),s}(s,i)}function emitRepair(e,t,r,o,l,a){const u={requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:r,attempt:o,reason:l};e.emit("runtime.repair.started"===t?{type:t,...u}:{type:t,...u,outcome:a??"retried"})}
@@ -1 +1 @@
1
- import{randomUUID as e}from"node:crypto";import{assertExecutionContract as t}from"./execution-contract.js";import{assertNoRawToolCallOutput as r,assertNoToolExecutionErrorOutput as a,buildAdapterErrorRecoveryPrompt as o,buildEvidenceSynthesisOutput as s,buildExecutionContractRecoveryRequest as n,buildResultRecoveryRequest as i,containsRawToolCallOutput as u,isRecoverableAdapterError as c,rawToolCallFailureMessage as l,toolCallRecoveryEnabled as p}from"./recovery/tool-call.js";import{recoverQualityReview as d,resolveQualityPolicy as m}from"./quality/index.js";import{completeRun as w,failRun as y}from"./runtime/completion.js";import{runDirectToolCall as f}from"./runtime/direct-tool-call.js";import{createApprovalGatedToolGateway as g}from"./runtime/governance/approval-gate.js";import{createSandboxedToolGateway as I}from"./runtime/governance/sandbox.js";import{createRuntimeInspectionMethods as q}from"./runtime/inspection/methods.js";import{createRuntimeCapabilityRegistry as R,normalizeAdapterResult as v}from"./runtime/capabilities.js";import{createMemoryRuntimeCapability as b}from"./runtime/memory.js";import{createInMemoryRuntimeStore as k}from"./runtime/persistence/stores.js";import{createProgressNarrationCapability as A}from"./runtime/progress-narration.js";import{repairRuntimeSelection as C}from"./runtime/selection-repair.js";import{createLangSmithTracingCapability as x}from"./runtime/tracing/langsmith.js";import{createToolFailureTracker as h}from"./runtime/tool-failure.js";import{runWorkflowRequest as j}from"./workflows/runtime.js";export function createStableHarnessRuntime(t){const r=new Set,a=t.store??k(),s=R([b(t),A({options:t.progressNarration,policy:t.workspace.runtime}),x({policy:t.workspace.runtime,store:a,options:t.langSmithTracing}),...t.capabilities??[]]),emitBase=t=>{const o=function enrichRuntimeEvent(t){return{...t,eventId:t.eventId??e(),emittedAt:t.emittedAt??(new Date).toISOString()}}(t);a.appendEvent(o);for(const e of r)e(o)},emit=e=>{emitBase(e),s.emitSideEffects(e,emitBase)},i=I({gateway:g({gateway:t.toolGateway,approvals:t.approvals,workspace:t.workspace,emit:emit}),workspace:t.workspace,sandbox:t.sandbox,emit:emit}),u={...t,toolGateway:i},l=h(function readToolFailurePolicy(e){if("object"!=typeof e||null===e||Array.isArray(e))return;const t=e.failurePolicy;return"object"!=typeof t||null===t||Array.isArray(t)?void 0:t}(t.workspace.runtime.toolGateway));return{request:async t=>async function runRuntimeRequest(t){const r=t.request.requestId??e(),a=t.request.sessionId??e(),s=[],{agent:i,adapter:u}=await async function resolveExecution(e,t,r){const a=t.agentId?await async function resolveRequestedAgentId(e,t,r){if(e.agents.has(t))return t;const a=await C({id:t,candidates:[...e.agents.values()].map(e=>({id:e.id,description:e.description})),trace:{...r,agentId:t,layer:"agent",owner:"stable_runtime_policy"}});return a.ok?a.id:t}(e.workspace,t.agentId,r):function resolveRoutedAgentId(e,t){for(const r of e.runtime.routes??[])if(routeMatches(r,t))return r.agentId;return e.runtime.defaultAgentId}(e.workspace,t.input),o=e.workspace.agents.get(a);if(!o)throw new Error(`Agent ${a} is not defined in the workspace`);if(t.toolCall||t.workflow)return{agent:o,adapter:void 0};const s=e.adapters.find(e=>e.canRun(o));if(!s)throw new Error(`No runtime adapter can run backend ${o.backend} for agent ${o.id}`);return{agent:o,adapter:s}}(t.input,t.request,{requestId:r,sessionId:a,emit:e=>s.push(e)});t.store.createRun(function createRunRecord(e,t,r,a){return{requestId:t,sessionId:r,agentId:a.id,input:e.input,state:"running",parentRunId:e.parentRunId,metadata:e.metadata,artifacts:[],startedAt:(new Date).toISOString(),events:[]}}(t.request,r,a,i)),s.forEach(t.emit),t.emit({type:"runtime.request.started",requestId:r,sessionId:a,agentId:i.id,input:t.request.input});try{if(t.request.workflow){const e=await j({workspace:t.input.workspace,adapters:t.input.workflowAdapters??[],toolGateway:t.input.toolGateway,request:{input:t.request.input,...t.request.workflow},requestId:r,sessionId:a,agentId:i.id,emit:t.emit});return w({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,result:e,artifacts:t.input.artifacts})}if(t.request.toolCall){const e=await f({gateway:t.input.toolGateway,workspace:t.input.workspace,emit:t.emit,request:t.request,requestId:r,sessionId:a,agent:i,toolFailureTracker:t.toolFailureTracker});return w({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,result:e,artifacts:t.input.artifacts})}return await async function runAdapterRequest(e){if(!e.adapter)throw new Error(`No runtime adapter can run backend ${e.agent.backend} for agent ${e.agent.id}`);const t=e.adapter,r=await e.capabilities.beforeAdapterRun(createCapabilityContext(e)),a=r.memory,s=r.pluginMemories??[],i=e.input.workspace.runtime,u=m(e.input.workspace.runtime,e.agent),l=new Map;let p;try{p=await runAdapterOnce(e,t,e.request,a,s,l)}catch(r){if(!c(r,i))throw r;p=await runAdapterOnce(e,t,o(e.request,r,i),a,s,l)}p=await recoverAdapterResultOutput(e,t,e.request,p,a,s,i,l),p=await d(createQualityRuntimeInput(e,a,s,l),e.request,p,u),await e.capabilities.beforeAdapterResultContract({...createCapabilityContext(e),result:p});try{assertRequestExecutionContract(e)}catch(r){const o=n({request:e.request,events:e.store.getRun(e.requestId)?.events??[],policy:i});if(!o)throw r;p=await runAdapterOnce(e,t,o,a,s,l),p=await recoverAdapterResultOutput(e,t,o,p,a,s,i,l),p=await d(createQualityRuntimeInput(e,a,s,l),o,p,u),assertRequestExecutionContract(e)}const y=w({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,result:p,artifacts:e.input.artifacts});return await e.capabilities.afterAdapterResponse({...createCapabilityContext(e),result:p,response:y}),y}({...t,adapter:u,requestId:r,sessionId:a,agent:i})}catch(e){return y({store:t.store,emit:t.emit,requestId:r,sessionId:a,agent:i,error:e})}}({input:u,capabilities:s,store:a,emit:emit,request:t,toolFailureTracker:l}),subscribe:e=>(r.add(e),()=>r.delete(e)),...q({workspace:t.workspace,store:a,artifacts:t.artifacts,approvals:t.approvals,emit:emit}),cancel(e,t){const r=a.getRun(e);r&&"running"===r.state&&(a.updateRun(e,{state:"cancelled",completedAt:(new Date).toISOString()}),emit({type:"runtime.request.cancelled",requestId:e,sessionId:r.sessionId,agentId:r.agentId,reason:t}))},async stop(){await s.stop(),r.clear()}}}function createCapabilityContext(e){return{workspace:e.input.workspace,store:e.store,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent}}function createQualityRuntimeInput(e,t,r,a){return{workspace:e.input.workspace,agent:e.agent,request:e.request,requestId:e.requestId,sessionId:e.sessionId,events:e.store.getRun(e.requestId)?.events??[],emit:e.emit,getEvents:()=>e.store.getRun(e.requestId)?.events??[],runAdapter:o=>runAdapterOnce(e,e.adapter,o,t,r,a),reviewModel:e.input.qualityReviewModel,memory:t,pluginMemories:r}}async function recoverAdapterResultOutput(e,t,o,n,c,d,m,w){let y=o;const f=function resultRecoveryAttempts(e){const t="object"!=typeof e||null===e||Array.isArray(e)?void 0:e.recovery,r="object"!=typeof t||null===t||Array.isArray(t)?void 0:t.toolCall,a="object"!=typeof r||null===r||Array.isArray(r)?void 0:r.maxResultRecoveryAttempts;return"number"==typeof a&&Number.isInteger(a)&&a>0?a:3}(m);let g=0;for(let r=0;r<f;r+=1){const r=e.store.getRun(e.requestId)?.events??[],a=i({request:y,output:n.text,events:r.slice(g),availableToolIds:e.agent.tools,policy:m});if(!a)break;y=a,g=e.store.getRun(e.requestId)?.events.length??0,n=await runAdapterOnce(e,t,a,c,d,w)}if(p(m)){let t=!1;u(n.text,m)&&function rawToolCallFailureReturnsMessage(e){return"message"===("object"!=typeof e?.toolCallRecovery||null===e.toolCallRecovery||Array.isArray(e.toolCallRecovery)?{}:e.toolCallRecovery).onFailure}(o.metadata)&&(n={...n,text:l(),metadata:{...n.metadata,toolCallRecovery:{failed:!0,reason:"raw_tool_call_output"}}});const i=s({request:o,output:n.text,events:e.store.getRun(e.requestId)?.events??[],policy:m});i&&(t=!0,n={...n,text:i,metadata:{...n.metadata,toolCallRecovery:{synthesized:!0,reason:"raw_tool_call_output_with_evidence"}}}),t||(r(n.text,m),a(n.text,m))}return n}function assertRequestExecutionContract(e){t({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,metadata:e.request.metadata})}async function runAdapterOnce(e,t,r,a,o,s){return v(await t.run({workspace:e.input.workspace,agent:e.agent,request:r,requestId:e.requestId,sessionId:e.sessionId,memory:a,pluginMemories:o,toolGateway:e.input.toolGateway,toolFailureTracker:e.input.toolFailureTracker,requestState:s,getEvents:()=>e.store.getRun(e.requestId)?.events??[],emit:e.emit}))}function routeMatches(e,t){if(e.pattern)try{if(new RegExp(e.pattern,"iu").test(t))return!0}catch{return!1}const r=t.toLowerCase();return(e.keywords??[]).some(e=>r.includes(e.toLowerCase()))}
1
+ import{randomUUID as e}from"node:crypto";import{assertExecutionContract as t}from"./execution-contract.js";import{buildAdapterErrorRecoveryPrompt as r,buildExecutionContractRecoveryRequest as a,isRecoverableAdapterError as s}from"./recovery/tool-call.js";import{recoverQualityReview as n,resolveQualityPolicy as o}from"./quality/index.js";import{recoverAdapterResultOutput as i}from"./runtime/recovery/adapter-result.js";import{completeRun as u,failRun as c}from"./runtime/completion.js";import{runDirectToolCall as p}from"./runtime/direct-tool-call.js";import{createApprovalGatedToolGateway as d}from"./runtime/governance/approval-gate.js";import{createSandboxedToolGateway as m}from"./runtime/governance/sandbox.js";import{createRuntimeInspectionMethods as l}from"./runtime/inspection/methods.js";import{createRuntimeCapabilityRegistry as w,normalizeAdapterResult as f}from"./runtime/capabilities.js";import{createMemoryRuntimeCapability as g}from"./runtime/memory.js";import{createInMemoryRuntimeStore as I}from"./runtime/persistence/stores.js";import{createProgressNarrationCapability as y}from"./runtime/progress-narration.js";import{repairRuntimeSelection as q}from"./runtime/selection-repair.js";import{createLangSmithTracingCapability as R}from"./runtime/tracing/langsmith.js";import{createToolFailureTracker as k}from"./runtime/tool-failure.js";import{runWorkflowRequest as v}from"./workflows/runtime.js";export function createStableHarnessRuntime(t){const f=new Set,b=t.store??I(),A=w([g(t),y({options:t.progressNarration,policy:t.workspace.runtime}),R({policy:t.workspace.runtime,store:b,options:t.langSmithTracing}),...t.capabilities??[]]),emitBase=t=>{const r=function enrichRuntimeEvent(t){return{...t,eventId:t.eventId??e(),emittedAt:t.emittedAt??(new Date).toISOString()}}(t);b.appendEvent(r);for(const e of f)e(r)},emit=e=>{emitBase(e),A.emitSideEffects(e,emitBase)},C=m({gateway:d({gateway:t.toolGateway,approvals:t.approvals,workspace:t.workspace,emit:emit}),workspace:t.workspace,sandbox:t.sandbox,emit:emit}),h={...t,toolGateway:C},x=k(function readToolFailurePolicy(e){if("object"!=typeof e||null===e||Array.isArray(e))return;const t=e.failurePolicy;return"object"!=typeof t||null===t||Array.isArray(t)?void 0:t}(t.workspace.runtime.toolGateway));return{request:async t=>async function runRuntimeRequest(t){const d=t.request.requestId??e(),m=t.request.sessionId??e(),l=[],{agent:w,adapter:f}=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 q({id:t,candidates:[...e.agents.values()].map(e=>({id:e.id,description:e.description})),trace:{...r,agentId:t,layer:"agent",owner:"stable_runtime_policy"}});return a.ok?a.id:t}(e.workspace,t.agentId,r):function resolveRoutedAgentId(e,t){for(const r of e.runtime.routes??[])if(routeMatches(r,t))return r.agentId;return e.runtime.defaultAgentId}(e.workspace,t.input),s=e.workspace.agents.get(a);if(!s)throw new Error(`Agent ${a} is not defined in the workspace`);if(t.toolCall||t.workflow)return{agent:s,adapter:void 0};const n=e.adapters.find(e=>e.canRun(s));if(!n)throw new Error(`No runtime adapter can run backend ${s.backend} for agent ${s.id}`);return{agent:s,adapter:n}}(t.input,t.request,{requestId:d,sessionId:m,emit:e=>l.push(e)});t.store.createRun(function createRunRecord(e,t,r,a){return{requestId:t,sessionId:r,agentId:a.id,input:e.input,state:"running",parentRunId:e.parentRunId,metadata:e.metadata,artifacts:[],startedAt:(new Date).toISOString(),events:[]}}(t.request,d,m,w)),l.forEach(t.emit),t.emit({type:"runtime.request.started",requestId:d,sessionId:m,agentId:w.id,input:t.request.input});try{if(t.request.workflow){const e=await v({workspace:t.input.workspace,adapters:t.input.workflowAdapters??[],toolGateway:t.input.toolGateway,request:{input:t.request.input,...t.request.workflow},requestId:d,sessionId:m,agentId:w.id,emit:t.emit});return u({store:t.store,emit:t.emit,requestId:d,sessionId:m,agent:w,result:e,artifacts:t.input.artifacts})}if(t.request.toolCall){const e=await p({gateway:t.input.toolGateway,workspace:t.input.workspace,emit:t.emit,request:t.request,requestId:d,sessionId:m,agent:w,toolFailureTracker:t.toolFailureTracker});return u({store:t.store,emit:t.emit,requestId:d,sessionId:m,agent:w,result:e,artifacts:t.input.artifacts})}return await async function runAdapterRequest(e){if(!e.adapter)throw new Error(`No runtime adapter can run backend ${e.agent.backend} for agent ${e.agent.id}`);const t=e.adapter,c=await e.capabilities.beforeAdapterRun(createCapabilityContext(e)),p=c.memory,d=c.pluginMemories??[],m=e.input.workspace.runtime,l=o(e.input.workspace.runtime,e.agent),w=new Map;let f;try{f=await runAdapterOnce(e,t,e.request,p,d,w)}catch(a){if(!s(a,m))throw a;e.emit(repairStarted(e,"adapter_error",1,errorMessage(a))),f=await runAdapterOnce(e,t,r(e.request,a,m),p,d,w),e.emit(repairCompleted(e,"adapter_error","retried",1,errorMessage(a)))}f=await i({...e,request:e.request,result:f,recoveryPolicy:m,runAdapter:r=>runAdapterOnce(e,t,r,p,d,w)}),f=await n(createQualityRuntimeInput(e,p,d,w),e.request,f,l),await e.capabilities.beforeAdapterResultContract({...createCapabilityContext(e),result:f});try{assertRequestExecutionContract(e)}catch(r){const s=a({request:e.request,events:e.store.getRun(e.requestId)?.events??[],policy:m});if(!s)throw r;e.emit(repairStarted(e,"execution_contract",1,errorMessage(r))),f=await runAdapterOnce(e,t,s,p,d,w),f=await i({...e,request:s,result:f,recoveryPolicy:m,runAdapter:r=>runAdapterOnce(e,t,r,p,d,w)}),f=await n(createQualityRuntimeInput(e,p,d,w),s,f,l),assertRequestExecutionContract(e),e.emit(repairCompleted(e,"execution_contract","retried",1,errorMessage(r)))}const g=u({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,result:f,artifacts:e.input.artifacts});return await e.capabilities.afterAdapterResponse({...createCapabilityContext(e),result:f,response:g}),g}({...t,adapter:f,requestId:d,sessionId:m,agent:w})}catch(e){return c({store:t.store,emit:t.emit,requestId:d,sessionId:m,agent:w,error:e})}}({input:h,capabilities:A,store:b,emit:emit,request:t,toolFailureTracker:x}),subscribe:e=>(f.add(e),()=>f.delete(e)),...l({workspace:t.workspace,store:b,artifacts:t.artifacts,approvals:t.approvals,emit:emit}),cancel(e,t){const r=b.getRun(e);r&&"running"===r.state&&(b.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 A.stop(),f.clear()}}}function createCapabilityContext(e){return{workspace:e.input.workspace,store:e.store,emit:e.emit,request:e.request,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent}}function createQualityRuntimeInput(e,t,r,a){return{workspace:e.input.workspace,agent:e.agent,request:e.request,requestId:e.requestId,sessionId:e.sessionId,events:e.store.getRun(e.requestId)?.events??[],emit:e.emit,getEvents:()=>e.store.getRun(e.requestId)?.events??[],runAdapter:s=>runAdapterOnce(e,e.adapter,s,t,r,a),reviewModel:e.input.qualityReviewModel,memory:t,pluginMemories:r}}function assertRequestExecutionContract(e){t({store:e.store,emit:e.emit,requestId:e.requestId,sessionId:e.sessionId,agent:e.agent,metadata:e.request.metadata})}async function runAdapterOnce(e,t,r,a,s,n){return f(await t.run({workspace:e.input.workspace,agent:e.agent,request:r,requestId:e.requestId,sessionId:e.sessionId,memory:a,pluginMemories:s,toolGateway:e.input.toolGateway,toolFailureTracker:e.input.toolFailureTracker,requestState:n,getEvents:()=>e.store.getRun(e.requestId)?.events??[],emit: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}}function repairCompleted(e,t,r,a,s){return{type:"runtime.repair.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,layer:t,outcome:r,attempt:a,reason:s}}function errorMessage(e){return e instanceof Error?e.message:String(e)}function routeMatches(e,t){if(e.pattern)try{if(new RegExp(e.pattern,"iu").test(t))return!0}catch{return!1}const r=t.toLowerCase();return(e.keywords??[]).some(e=>r.includes(e.toLowerCase()))}
@@ -1 +1 @@
1
- export function createDelegationTraceProjection(e,t={}){return{traceType:"delegation",traceLabel:e,...t}}export function createPlanTraceProjection(e,t={}){return{traceType:"plan",traceLabel:e,...t}}export function projectRuntimeTrace(e){return e.events.map(projectEvent).filter(isTraceEntry)}export function projectRuntimeTraceSpans(e){const t=function createSpanBuilder(e){const t=`run:${e.requestId}`,r=[],o=new Map;return{ensureRoot(){if(o.has(t))return;const n={spanId:t,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agentId,kind:"run",name:e.agentId,status:(a=e.state,"completed"===a?"completed":"failed"===a?"failed":"cancelled"===a?"blocked":"running"),startedAt:e.startedAt,completedAt:e.completedAt,startEventIndex:0,...e.parentRunId?{parentSpanId:`run:${e.parentRunId}`}:{},events:[]};var a;r.push(n),o.set(t,n)},markRoot(e,r,n,a){const i=o.get(t);i&&(addEvent(i,e,r),i.status=n,i.attributes=merge(i.attributes,a),"running"!==n&&close(i,e,r))},start(e,n,a,i,s,d){const p=createSpan(`${t}/${e}:${s}`,t,n,a,i,s,d);r.push(p),o.set(e,p)},complete(e,n,a,i){const s=o.get(e)??createSpan(`${t}/${e}:${a}`,t,"adapter",e,n,a);return o.has(e)||r.push(s),addEvent(s,n,a),s.attributes=merge(s.attributes,i),close(s,n,a),o.delete(e),s},fail(e,t,r,o){this.complete(e,t,r,o).status="failed"},event(e,o,n,a,i){const s=createSpan(`${t}/event:${a}`,t,e,o,n,a,i);s.status=function readBlockedStatus(e){return e.type.endsWith(".blocked")||e.type.includes(".approval.")?"blocked":void 0}(n)??"event",close(s,n,a),r.push(s)},closeRoot(){const r=o.get(t);r&&e.completedAt&&(r.completedAt=e.completedAt)},spans:()=>r}}(e);return t.ensureRoot(),e.events.forEach((e,r)=>function projectSpanEvent(e,t,r){return t.type.startsWith("runtime.request.")?function projectRequestSpanEvent(e,t,r){return"runtime.request.started"===t.type?e.markRoot(t,r,"running",{input:t.input}):"runtime.request.completed"===t.type?e.markRoot(t,r,"completed",{output:t.output}):"runtime.request.failed"===t.type?e.markRoot(t,r,"failed",{error:t.error}):"runtime.request.cancelled"===t.type?e.markRoot(t,r,"blocked",{reason:t.reason}):"runtime.execution.contract.failed"===t.type?projectSingleSpan(e,t,r,"quality",t.type,{reason:t.reason,missingEvidenceTools:t.missingEvidenceTools}):void 0}(e,t,r):"runtime.tool.direct.started"===t.type?e.start(`tool:${t.toolId}`,"tool",t.toolId,t,r,{toolId:t.toolId}):"runtime.tool.direct.completed"===t.type?e.complete(`tool:${t.toolId}`,t,r,{toolId:t.toolId,output:t.output}):"runtime.workflow.started"===t.type?e.start(`workflow:${t.workflowId}`,"workflow",t.workflowId,t,r,{workflowId:t.workflowId,adapter:t.adapter}):"runtime.workflow.completed"===t.type?e.complete(`workflow:${t.workflowId}`,t,r,{workflowId:t.workflowId,adapter:t.adapter}):t.type.startsWith("runtime.approval.")||t.type.startsWith("runtime.memory.approval.")?projectSingleSpan(e,t,r,"approval",t.type):t.type.startsWith("runtime.specDriven.phase.")?projectSingleSpan(e,t,r,"spec",function readPhaseName(e,t){return"phaseId"in e&&"string"==typeof e.phaseId?e.phaseId:t}(t,"phase")):t.type.startsWith("runtime.memory.")?projectSingleSpan(e,t,r,"memory",t.type):t.type.startsWith("runtime.quality.")?projectSingleSpan(e,t,r,"quality",t.type):"runtime.artifact.created"===t.type?projectSingleSpan(e,t,r,"artifact",t.artifact.id,{artifact:t.artifact}):"runtime.progress.narration"===t.type?projectSingleSpan(e,t,r,"progress",t.message,{provider:t.provider}):"runtime.adapter.event"===t.type?function projectAdapterSpanEvent(e,t,r){const o=isRecord(t.event)?t.event:void 0,n=readString(o?.phase)??"runtime.adapter.event",a=readTraceType(o?.traceType),i=readString(o?.traceLabel);return"delegation"===a&&i?.endsWith(".start")?e.start(delegationKey(o),"delegation",readString(o?.subagentType)??i,t,r,o):"delegation"===a&&i?.endsWith(".completed")?e.complete(delegationKey(o),t,r,o):"plan"===a&&i?projectSingleSpan(e,t,r,"plan",i,o):function isToolStartEvent(e){return"deepagents.tool_execution.start"===e?.eventType||"agent.tool.start"===e?.phase}(o)?e.start(`agent-tool:${readString(o?.toolId)??"unknown"}`,"tool",readString(o?.toolId)??n,t,r,o):function isToolResultEvent(e){return"deepagents.tool_execution.result"===e?.eventType||"agent.tool.result"===e?.phase}(o)?e.complete(`agent-tool:${readString(o?.toolId)??"unknown"}`,t,r,o):projectSingleSpan(e,t,r,"adapter",n,o)}(e,t,r):"runtime.inventory.repair"===t.type?projectSingleSpan(e,t,r,"adapter","runtime.inventory.repair",{status:t.status,...t.diagnostic}):"runtime.sandbox.decision"===t.type?projectSingleSpan(e,t,r,"tool",`sandbox:${t.toolId}`,{toolId:t.toolId,...t.decision}):"runtime.tool.failure"===t.type?e.fail(`tool:${t.toolId}`,t,r,{toolId:t.toolId,...t.failure}):"runtime.tool.circuit.opened"===t.type?projectSingleSpan(e,t,r,"tool",`circuit:${t.toolId}`,{toolId:t.toolId,reason:t.reason}):void 0}(t,e,r)),t.closeRoot(),t.spans()}export function projectEvent(e){return"runtime.request.started"===e.type||"runtime.request.completed"===e.type||"runtime.request.failed"===e.type?base(e,"request",e.type):"runtime.request.cancelled"===e.type?base(e,"request",e.type,{reason:e.reason}):"runtime.execution.contract.failed"===e.type?base(e,"request",e.type,{reason:e.reason,missingEvidenceTools:e.missingEvidenceTools}):"runtime.inventory.repair"===e.type?base(e,"adapter","runtime.inventory.repair",{status:e.status,...e.diagnostic}):"runtime.tool.direct.started"===e.type?base(e,"tool","runtime.tool.direct.started",{toolId:e.toolId}):"runtime.tool.direct.completed"===e.type?base(e,"tool","runtime.tool.direct.completed",{toolId:e.toolId}):"runtime.sandbox.decision"===e.type?base(e,"tool","runtime.sandbox.decision",{toolId:e.toolId,...e.decision}):"runtime.tool.failure"===e.type?base(e,"tool","runtime.tool.failure",{toolId:e.toolId,...e.failure}):"runtime.tool.circuit.opened"===e.type?base(e,"tool","runtime.tool.circuit.opened",{toolId:e.toolId,reason:e.reason}):"runtime.workflow.started"===e.type||"runtime.workflow.completed"===e.type?base(e,"workflow",e.type,{workflowId:e.workflowId,adapter:e.adapter}):function isSpecDrivenPhaseEvent(e){return e.type.startsWith("runtime.specDriven.phase.")}(e)?base(e,"spec",e.type,{phaseId:e.phaseId,..."workflowId"in e&&e.workflowId?{workflowId:e.workflowId}:{},..."reason"in e?{reason:e.reason}:{},..."artifact"in e&&e.artifact?{artifact:e.artifact}:{}}):"runtime.adapter.event"===e.type?function adapterTrace(e){const t=e.event;if(isRecord(t)&&"string"==typeof t.phase){const r=function semanticAdapterTrace(e,t){if("inventory.repair"===t.phase)return base(e,"adapter","runtime.inventory.repair",{status:t.status,...isRecord(t.diagnostic)?t.diagnostic:{}});const r=readTraceType(t.traceType),o=readString(t.traceLabel);return r&&o?base(e,r,o,t):void 0}(e,t);return r||base(e,"adapter",t.phase.startsWith("agent.")?t.phase:`adapter.${t.phase}`,t)}return base(e,"adapter","runtime.adapter.event",{event:t})}(e):"runtime.artifact.created"===e.type?base(e,"artifact","runtime.artifact.created",{artifact:e.artifact}):e.type.startsWith("runtime.memory.")?base(e,"memory",e.type):"runtime.progress.narration"===e.type?base(e,"progress",e.type,{message:e.message,provider:e.provider,sourceEventTypes:e.sourceEventTypes}):void 0}export function readPlanTodos(e){const t=function readPlanRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e),r=function readTodosArray(e){const t=isRecord(e?.args)?e.args:void 0;return Array.isArray(e?.todos)?e.todos:Array.isArray(t?.todos)?t.todos:[]}(t);return r.map(readTodo).filter(isPlanTodoItem)}function readTodo(e){if(isRecord(e)&&"string"==typeof e.content)return{content:e.content,status:"string"==typeof e.status?e.status:"pending"}}function isPlanTodoItem(e){return void 0!==e}function base(e,t,r,o){return{type:t,label:r,agentId:e.agentId,requestId:e.requestId,detail:o}}function isTraceEntry(e){return void 0!==e}function projectSingleSpan(e,t,r,o,n,a){return e.event(o,n,t,r,a)}function delegationKey(e){return`delegation:${readString(e?.subagentType)??readString(e?.toolId)??"task"}`}function createSpan(e,t,r,o,n,a,i){const s={spanId:e,parentSpanId:t,requestId:n.requestId,sessionId:n.sessionId,agentId:n.agentId,kind:r,name:o,status:"running",startedAt:n.emittedAt,startEventIndex:a,attributes:i,events:[]};return addEvent(s,n,a),s}function addEvent(e,t,r){e.events.push({index:r,eventId:t.eventId??`${t.requestId}:${r}`,type:t.type,emittedAt:t.emittedAt})}function close(e,t,r){e.status="failed"===e.status||"blocked"===e.status?e.status:"completed",e.completedAt=t.emittedAt,e.endEventIndex=r,e.durationMs=function durationMs(e,t){if(!e||!t)return;const r=Date.parse(t)-Date.parse(e);return Number.isFinite(r)&&r>=0?r:void 0}(e.startedAt,e.completedAt)}function merge(e,t){return t?{...e,...t}:e}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readTraceType(e){const t=readString(e);return"request"===t||"tool"===t||"workflow"===t||"spec"===t||"adapter"===t||"memory"===t||"artifact"===t||"progress"===t||"plan"===t||"delegation"===t?t:void 0}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}
1
+ export function createDelegationTraceProjection(e,t={}){return{traceType:"delegation",traceLabel:e,...t}}export function createPlanTraceProjection(e,t={}){return{traceType:"plan",traceLabel:e,...t}}export function projectRuntimeTrace(e){return e.events.map(projectEvent).filter(isTraceEntry)}export function projectRuntimeTraceSpans(e){const t=function createSpanBuilder(e){const t=`run:${e.requestId}`,r=[],o=new Map;return{ensureRoot(){if(o.has(t))return;const n={spanId:t,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agentId,kind:"run",name:e.agentId,status:(a=e.state,"completed"===a?"completed":"failed"===a?"failed":"cancelled"===a?"blocked":"running"),startedAt:e.startedAt,completedAt:e.completedAt,startEventIndex:0,...e.parentRunId?{parentSpanId:`run:${e.parentRunId}`}:{},events:[]};var a;r.push(n),o.set(t,n)},markRoot(e,r,n,a){const i=o.get(t);i&&(addEvent(i,e,r),i.status=n,i.attributes=merge(i.attributes,a),"running"!==n&&close(i,e,r))},start(e,n,a,i,s,d){const p=createSpan(`${t}/${e}:${s}`,t,n,a,i,s,d);r.push(p),o.set(e,p)},complete(e,n,a,i){const s=o.get(e)??createSpan(`${t}/${e}:${a}`,t,"adapter",e,n,a);return o.has(e)||r.push(s),addEvent(s,n,a),s.attributes=merge(s.attributes,i),close(s,n,a),o.delete(e),s},fail(e,t,r,o){this.complete(e,t,r,o).status="failed"},event(e,o,n,a,i){const s=createSpan(`${t}/event:${a}`,t,e,o,n,a,i);s.status=function readBlockedStatus(e){return e.type.endsWith(".blocked")||e.type.includes(".approval.")?"blocked":void 0}(n)??"event",close(s,n,a),r.push(s)},closeRoot(){const r=o.get(t);r&&e.completedAt&&(r.completedAt=e.completedAt)},spans:()=>r}}(e);return t.ensureRoot(),e.events.forEach((e,r)=>function projectSpanEvent(e,t,r){return t.type.startsWith("runtime.request.")?function projectRequestSpanEvent(e,t,r){return"runtime.request.started"===t.type?e.markRoot(t,r,"running",{input:t.input}):"runtime.request.completed"===t.type?e.markRoot(t,r,"completed",{output:t.output}):"runtime.request.failed"===t.type?e.markRoot(t,r,"failed",{error:t.error}):"runtime.request.cancelled"===t.type?e.markRoot(t,r,"blocked",{reason:t.reason}):"runtime.execution.contract.failed"===t.type?projectSingleSpan(e,t,r,"quality",t.type,{reason:t.reason,missingEvidenceTools:t.missingEvidenceTools}):void 0}(e,t,r):"runtime.tool.direct.started"===t.type?e.start(`tool:${t.toolId}`,"tool",t.toolId,t,r,{toolId:t.toolId}):"runtime.tool.direct.completed"===t.type?e.complete(`tool:${t.toolId}`,t,r,{toolId:t.toolId,output:t.output}):"runtime.workflow.started"===t.type?e.start(`workflow:${t.workflowId}`,"workflow",t.workflowId,t,r,{workflowId:t.workflowId,adapter:t.adapter}):"runtime.workflow.completed"===t.type?e.complete(`workflow:${t.workflowId}`,t,r,{workflowId:t.workflowId,adapter:t.adapter}):t.type.startsWith("runtime.approval.")||t.type.startsWith("runtime.memory.approval.")?projectSingleSpan(e,t,r,"approval",t.type):t.type.startsWith("runtime.specDriven.phase.")?projectSingleSpan(e,t,r,"spec",function readPhaseName(e,t){return"phaseId"in e&&"string"==typeof e.phaseId?e.phaseId:t}(t,"phase")):t.type.startsWith("runtime.memory.")?projectSingleSpan(e,t,r,"memory",t.type):t.type.startsWith("runtime.quality.")?projectSingleSpan(e,t,r,"quality",t.type):t.type.startsWith("runtime.repair.")?projectSingleSpan(e,t,r,"adapter",t.type):"runtime.artifact.created"===t.type?projectSingleSpan(e,t,r,"artifact",t.artifact.id,{artifact:t.artifact}):"runtime.progress.narration"===t.type?projectSingleSpan(e,t,r,"progress",t.message,{provider:t.provider}):"runtime.adapter.event"===t.type?function projectAdapterSpanEvent(e,t,r){const o=isRecord(t.event)?t.event:void 0,n=readString(o?.phase)??"runtime.adapter.event",a=readTraceType(o?.traceType),i=readString(o?.traceLabel);return"delegation"===a&&i?.endsWith(".start")?e.start(delegationKey(o),"delegation",readString(o?.subagentType)??i,t,r,o):"delegation"===a&&i?.endsWith(".completed")?e.complete(delegationKey(o),t,r,o):"plan"===a&&i?projectSingleSpan(e,t,r,"plan",i,o):function isToolStartEvent(e){return"deepagents.tool_execution.start"===e?.eventType||"agent.tool.start"===e?.phase}(o)?e.start(`agent-tool:${readString(o?.toolId)??"unknown"}`,"tool",readString(o?.toolId)??n,t,r,o):function isToolResultEvent(e){return"deepagents.tool_execution.result"===e?.eventType||"agent.tool.result"===e?.phase}(o)?e.complete(`agent-tool:${readString(o?.toolId)??"unknown"}`,t,r,o):projectSingleSpan(e,t,r,"adapter",n,o)}(e,t,r):"runtime.inventory.repair"===t.type?projectSingleSpan(e,t,r,"adapter","runtime.inventory.repair",{status:t.status,...t.diagnostic}):"runtime.sandbox.decision"===t.type?projectSingleSpan(e,t,r,"tool",`sandbox:${t.toolId}`,{toolId:t.toolId,...t.decision}):"runtime.tool.failure"===t.type?e.fail(`tool:${t.toolId}`,t,r,{toolId:t.toolId,...t.failure}):"runtime.tool.circuit.opened"===t.type?projectSingleSpan(e,t,r,"tool",`circuit:${t.toolId}`,{toolId:t.toolId,reason:t.reason}):void 0}(t,e,r)),t.closeRoot(),t.spans()}export function projectEvent(e){return"runtime.request.started"===e.type||"runtime.request.completed"===e.type||"runtime.request.failed"===e.type?base(e,"request",e.type):"runtime.request.cancelled"===e.type?base(e,"request",e.type,{reason:e.reason}):"runtime.execution.contract.failed"===e.type?base(e,"request",e.type,{reason:e.reason,missingEvidenceTools:e.missingEvidenceTools}):"runtime.inventory.repair"===e.type?base(e,"adapter","runtime.inventory.repair",{status:e.status,...e.diagnostic}):"runtime.repair.started"===e.type||"runtime.repair.completed"===e.type?base(e,"adapter",e.type,{layer:e.layer,..."outcome"in e?{outcome:e.outcome}:{},..."attempt"in e?{attempt:e.attempt}:{},..."reason"in e?{reason:e.reason}:{}}):"runtime.tool.direct.started"===e.type?base(e,"tool","runtime.tool.direct.started",{toolId:e.toolId}):"runtime.tool.direct.completed"===e.type?base(e,"tool","runtime.tool.direct.completed",{toolId:e.toolId}):"runtime.sandbox.decision"===e.type?base(e,"tool","runtime.sandbox.decision",{toolId:e.toolId,...e.decision}):"runtime.tool.failure"===e.type?base(e,"tool","runtime.tool.failure",{toolId:e.toolId,...e.failure}):"runtime.tool.circuit.opened"===e.type?base(e,"tool","runtime.tool.circuit.opened",{toolId:e.toolId,reason:e.reason}):"runtime.workflow.started"===e.type||"runtime.workflow.completed"===e.type?base(e,"workflow",e.type,{workflowId:e.workflowId,adapter:e.adapter}):function isSpecDrivenPhaseEvent(e){return e.type.startsWith("runtime.specDriven.phase.")}(e)?base(e,"spec",e.type,{phaseId:e.phaseId,..."workflowId"in e&&e.workflowId?{workflowId:e.workflowId}:{},..."reason"in e?{reason:e.reason}:{},..."artifact"in e&&e.artifact?{artifact:e.artifact}:{}}):"runtime.adapter.event"===e.type?function adapterTrace(e){const t=e.event;if(isRecord(t)&&"string"==typeof t.phase){const r=function semanticAdapterTrace(e,t){if("inventory.repair"===t.phase)return base(e,"adapter","runtime.inventory.repair",{status:t.status,...isRecord(t.diagnostic)?t.diagnostic:{}});const r=readTraceType(t.traceType),o=readString(t.traceLabel);return r&&o?base(e,r,o,t):void 0}(e,t);return r||base(e,"adapter",t.phase.startsWith("agent.")?t.phase:`adapter.${t.phase}`,t)}return base(e,"adapter","runtime.adapter.event",{event:t})}(e):"runtime.artifact.created"===e.type?base(e,"artifact","runtime.artifact.created",{artifact:e.artifact}):e.type.startsWith("runtime.memory.")?base(e,"memory",e.type):"runtime.progress.narration"===e.type?base(e,"progress",e.type,{message:e.message,provider:e.provider,sourceEventTypes:e.sourceEventTypes}):void 0}export function readPlanTodos(e){const t=function readPlanRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e),r=function readTodosArray(e){const t=isRecord(e?.args)?e.args:void 0;return Array.isArray(e?.todos)?e.todos:Array.isArray(t?.todos)?t.todos:[]}(t);return r.map(readTodo).filter(isPlanTodoItem)}function readTodo(e){if(isRecord(e)&&"string"==typeof e.content)return{content:e.content,status:"string"==typeof e.status?e.status:"pending"}}function isPlanTodoItem(e){return void 0!==e}function base(e,t,r,o){return{type:t,label:r,agentId:e.agentId,requestId:e.requestId,detail:o}}function isTraceEntry(e){return void 0!==e}function projectSingleSpan(e,t,r,o,n,a){return e.event(o,n,t,r,a)}function delegationKey(e){return`delegation:${readString(e?.subagentType)??readString(e?.toolId)??"task"}`}function createSpan(e,t,r,o,n,a,i){const s={spanId:e,parentSpanId:t,requestId:n.requestId,sessionId:n.sessionId,agentId:n.agentId,kind:r,name:o,status:"running",startedAt:n.emittedAt,startEventIndex:a,attributes:i,events:[]};return addEvent(s,n,a),s}function addEvent(e,t,r){e.events.push({index:r,eventId:t.eventId??`${t.requestId}:${r}`,type:t.type,emittedAt:t.emittedAt})}function close(e,t,r){e.status="failed"===e.status||"blocked"===e.status?e.status:"completed",e.completedAt=t.emittedAt,e.endEventIndex=r,e.durationMs=function durationMs(e,t){if(!e||!t)return;const r=Date.parse(t)-Date.parse(e);return Number.isFinite(r)&&r>=0?r:void 0}(e.startedAt,e.completedAt)}function merge(e,t){return t?{...e,...t}:e}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readTraceType(e){const t=readString(e);return"request"===t||"tool"===t||"workflow"===t||"spec"===t||"adapter"===t||"memory"===t||"artifact"===t||"progress"===t||"plan"===t||"delegation"===t?t:void 0}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}
@@ -1,10 +0,0 @@
1
- import { ToolMessage } from "@langchain/core/messages";
2
- import type { RuntimeAdapter } from "@stable-harness/core";
3
- type AdapterRunInput = Parameters<RuntimeAdapter["run"]>[0];
4
- export declare function validateSkillFileBuiltinCall(input: AdapterRunInput, toolId: string, request: {
5
- toolCall?: {
6
- id?: string;
7
- args?: unknown;
8
- };
9
- }): ToolMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>> | undefined;
10
- export {};
@@ -1 +0,0 @@
1
- import{ToolMessage as e}from"@langchain/core/messages";export function validateSkillFileBuiltinCall(t,l,r){const i=function readFilesystemTarget(e){const t=function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}(e)?e:{};for(const e of["file_path","path","pattern","query"]){const l=t[e];if("string"==typeof l&&l.trim())return l.trim()}}(r.toolCall?.args);if(i&&function targetsRegisteredSkill(e,t){return[...e.workspace.skills.values()].some(l=>{const r=function virtualSkillDir(e,t){const l=function pathRelative(e,t){const l=e.split("/").filter(Boolean),r=t.split("/").filter(Boolean);if(!(r.length<l.length)){for(let e=0;e<l.length;e+=1)if(l[e]!==r[e])return;return r.slice(l.length).join("/")}}(e,t);if(void 0===l)return;const r=l.split("/").filter(Boolean),i=r.lastIndexOf("skills");return i<0?`/${r.slice(0,-1).join("/")}`:`/${r.slice(0,i+2).join("/")}`}(e.workspace.root,l.path);return!!r&&function pathMatches(e,t){const l=t.replace(/\/+$/u,"");return e===l||e.startsWith(`${l}/`)||e.includes(`${l}/`)||e.includes("SKILL.md")}(t,r)})}(t,i))return new e({tool_call_id:r.toolCall?.id??`stable-harness-${l}-skill-policy`,name:l,status:"error",content:[`Filesystem builtin tool '${l}' targeted registered skill inventory: ${i}.`,"Skills are already registered with the backend and are not evidence files for the user request.","Do not read, list, glob, or grep SKILL.md files or skill directories.","Continue with the declared agent tools, the skill behavior already loaded by the backend, and the evidence already collected."].join(" ")})}
@@ -1,10 +0,0 @@
1
- import { ToolMessage } from "@langchain/core/messages";
2
- import type { RuntimeAdapter } from "@stable-harness/core";
3
- type AdapterRunInput = Parameters<RuntimeAdapter["run"]>[0];
4
- export declare function validateSkillFileBuiltinCall(input: AdapterRunInput, toolId: string, request: {
5
- toolCall?: {
6
- id?: string;
7
- args?: unknown;
8
- };
9
- }): ToolMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>> | undefined;
10
- export {};
@@ -1 +0,0 @@
1
- import{ToolMessage as e}from"@langchain/core/messages";export function validateSkillFileBuiltinCall(t,l,r){const i=function readFilesystemTarget(e){const t=function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}(e)?e:{};for(const e of["file_path","path","pattern","query"]){const l=t[e];if("string"==typeof l&&l.trim())return l.trim()}}(r.toolCall?.args);if(i&&function targetsRegisteredSkill(e,t){return[...e.workspace.skills.values()].some(l=>{const r=function virtualSkillDir(e,t){const l=function pathRelative(e,t){const l=e.split("/").filter(Boolean),r=t.split("/").filter(Boolean);if(!(r.length<l.length)){for(let e=0;e<l.length;e+=1)if(l[e]!==r[e])return;return r.slice(l.length).join("/")}}(e,t);if(void 0===l)return;const r=l.split("/").filter(Boolean),i=r.lastIndexOf("skills");return i<0?`/${r.slice(0,-1).join("/")}`:`/${r.slice(0,i+2).join("/")}`}(e.workspace.root,l.path);return!!r&&function pathMatches(e,t){const l=t.replace(/\/+$/u,"");return e===l||e.startsWith(`${l}/`)||e.includes(`${l}/`)||e.includes("SKILL.md")}(t,r)})}(t,i))return new e({tool_call_id:r.toolCall?.id??`stable-harness-${l}-skill-policy`,name:l,status:"error",content:[`Filesystem builtin tool '${l}' targeted registered skill inventory: ${i}.`,"Skills are already registered with the backend and are not evidence files for the user request.","Do not read, list, glob, or grep SKILL.md files or skill directories.","Continue with the declared agent tools, the skill behavior already loaded by the backend, and the evidence already collected."].join(" ")})}