stable-harness 0.0.38 → 0.0.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/compatibility-matrix.md +11 -0
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/adapter.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin/permissions.d.ts +17 -0
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin/permissions.js +1 -0
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin/task-inventory.d.ts +13 -0
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin/task-inventory.js +1 -0
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-tool-policy.d.ts +2 -13
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-tool-policy.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/gateway-tools.d.ts +1 -23
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/gateway-tools.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/tool-repeat-visibility.d.ts +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/tool-repeat-visibility.js +1 -1
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/trace-projection.d.ts +1 -16
- package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/trace-projection.js +1 -1
- package/node_modules/@stable-harness/core/dist/index.d.ts +2 -0
- package/node_modules/@stable-harness/core/dist/index.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/profile.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/synthesis/fields.d.ts +3 -2
- package/node_modules/@stable-harness/core/dist/quality/synthesis/fields.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/synthesis/observed.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/synthesis.js +1 -1
- package/node_modules/@stable-harness/core/dist/quality/types.d.ts +2 -0
- package/node_modules/@stable-harness/core/dist/runtime/capabilities.d.ts +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/capabilities.js +1 -1
- package/node_modules/@stable-harness/core/dist/runtime/policy/projection.d.ts +11 -0
- package/node_modules/@stable-harness/core/dist/runtime/policy/projection.js +1 -0
- package/node_modules/@stable-harness/core/dist/runtime/policy/tool-invocation.d.ts +45 -0
- package/node_modules/@stable-harness/core/dist/runtime/policy/tool-invocation.js +1 -0
- package/node_modules/@stable-harness/core/dist/runtime.js +1 -1
- package/node_modules/@stable-harness/core/dist/trace.d.ts +6 -0
- package/node_modules/@stable-harness/core/dist/trace.js +1 -1
- package/node_modules/@stable-harness/core/dist/types.d.ts +1 -0
- package/package.json +2 -2
- package/packages/adapter-deepagents/dist/src/adapter.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/builtin/permissions.d.ts +17 -0
- package/packages/adapter-deepagents/dist/src/internal/builtin/permissions.js +1 -0
- package/packages/adapter-deepagents/dist/src/internal/builtin/task-inventory.d.ts +13 -0
- package/packages/adapter-deepagents/dist/src/internal/builtin/task-inventory.js +1 -0
- package/packages/adapter-deepagents/dist/src/internal/builtin-tool-policy.d.ts +2 -13
- package/packages/adapter-deepagents/dist/src/internal/builtin-tool-policy.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/gateway-tools.d.ts +1 -23
- package/packages/adapter-deepagents/dist/src/internal/gateway-tools.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/tool-repeat-visibility.d.ts +1 -1
- package/packages/adapter-deepagents/dist/src/internal/tool-repeat-visibility.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/trace-projection.d.ts +1 -16
- package/packages/adapter-deepagents/dist/src/internal/trace-projection.js +1 -1
- package/packages/core/dist/index.d.ts +2 -0
- package/packages/core/dist/index.js +1 -1
- package/packages/core/dist/quality/profile.js +1 -1
- package/packages/core/dist/quality/synthesis/fields.d.ts +3 -2
- package/packages/core/dist/quality/synthesis/fields.js +1 -1
- package/packages/core/dist/quality/synthesis/observed.js +1 -1
- package/packages/core/dist/quality/synthesis.js +1 -1
- package/packages/core/dist/quality/types.d.ts +2 -0
- package/packages/core/dist/runtime/capabilities.d.ts +1 -0
- package/packages/core/dist/runtime/capabilities.js +1 -1
- package/packages/core/dist/runtime/policy/projection.d.ts +11 -0
- package/packages/core/dist/runtime/policy/projection.js +1 -0
- package/packages/core/dist/runtime/policy/tool-invocation.d.ts +45 -0
- package/packages/core/dist/runtime/policy/tool-invocation.js +1 -0
- package/packages/core/dist/runtime.js +1 -1
- package/packages/core/dist/trace.d.ts +6 -0
- package/packages/core/dist/trace.js +1 -1
- package/packages/core/dist/types.d.ts +1 -0
|
@@ -137,3 +137,14 @@ A compatibility feature is acceptable only when all of these are true:
|
|
|
137
137
|
3. Move remaining CLI trace checks from compat `dataListener` to native `projectRuntimeTrace` where native runtime events exist.
|
|
138
138
|
4. Keep only the explicit `./compat/agent-harness.js` facade until downstream workspaces can use the native stable runtime API directly.
|
|
139
139
|
5. Add tests for each runtime capability boundary before broadening beyond EasyNet.
|
|
140
|
+
|
|
141
|
+
## Retirement Gates
|
|
142
|
+
|
|
143
|
+
Compatibility can shrink only when the replacement is expressed as one of the stable native boundaries below:
|
|
144
|
+
|
|
145
|
+
- upstream passthrough through a backend adapter, with no local replay of execution semantics
|
|
146
|
+
- a typed runtime capability that can be enabled, disabled, replaced, and tested independently
|
|
147
|
+
- a protocol or operator projection over existing runtime events, traces, artifacts, approvals, or run state
|
|
148
|
+
- downstream workspace config, prompt, tool, or test changes for application-owned behavior
|
|
149
|
+
|
|
150
|
+
New work must not import `runtime/compat` or `compat/agent-harness` from native packages. Static architecture tests enforce this and also guard core source from backend imports and downstream domain vocabulary.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{realpathSync as e}from"node:fs";import t from"node:path";import{
|
|
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 l}from"./internal/messages.js";import{createRawToolCallParserMiddleware as c}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=l(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)return g(t,o.streamEvents(a,{version:"v2",...d}),p);const c=await o.invoke(a,d);return p(c)}}}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=d(e.workspace).map(e=>`/memories/${e.id}.md`);return n.length>0?n:void 0}function resolveDeepAgentsSkills(r,n){const o=readDeepAgentsStringArray(n?.config,"skills");if(o)return o;const s=[...new Set((n?.skills??[]).map(e=>r.workspace.skills.get(e)?.path).filter(e=>"string"==typeof e&&e.trim().length>0).map(n=>function backendSkillSourcePath(r,n){const o=t.dirname(t.dirname(n)),s=t.relative(r,o);return!s||s.startsWith("..")||t.isAbsolute(s)?""===s?"/":function canonicalPath(t){try{return e.native(t)}catch{return t}}(o):`/${s.split(t.sep).join("/")}`}(r.workspace.root,n)))];return s.length>0?s: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;return[o(p,{observedToolIds:d,repeatState:s}),n(p,{repeatState:s}),...m(e.workspace.runtime.retry),...i,c(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 isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function isRepairModel(e){return"object"==typeof e&&null!==e&&"invoke"in e&&"function"==typeof e.invoke}
|
package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin/permissions.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ToolMessage } from "@langchain/core/messages";
|
|
2
|
+
import type { RuntimeAdapter, WorkspaceAgent } from "@stable-harness/core";
|
|
3
|
+
type AdapterRunInput = Parameters<RuntimeAdapter["run"]>[0];
|
|
4
|
+
export declare const filesystemBuiltinToolIds: Set<string>;
|
|
5
|
+
export declare function validateFilesystemBuiltinCall(input: AdapterRunInput, toolId: string, request: {
|
|
6
|
+
toolCall?: {
|
|
7
|
+
id?: string;
|
|
8
|
+
};
|
|
9
|
+
}): ToolMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>> | undefined;
|
|
10
|
+
export declare function resolveFilesystemPermissions(input: AdapterRunInput, agent: WorkspaceAgent | undefined): {
|
|
11
|
+
operations: string[];
|
|
12
|
+
paths: string[];
|
|
13
|
+
mode: string;
|
|
14
|
+
}[] | undefined;
|
|
15
|
+
export declare function isFilesystemDisabled(input: AdapterRunInput): boolean;
|
|
16
|
+
export declare function isFilesystemTool(name: unknown): boolean;
|
|
17
|
+
export {};
|
package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin/permissions.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{realpathSync as e}from"node:fs";import{ToolMessage as t}from"@langchain/core/messages";export const filesystemBuiltinToolIds=new Set(["ls","read_file","write_file","edit_file","glob","grep"]);export function validateFilesystemBuiltinCall(e,i,o){if(isFilesystemDisabled(e)&&filesystemBuiltinToolIds.has(i))return new t({tool_call_id:o.toolCall?.id??`stable-harness-${i}-policy`,name:i,content:`Filesystem builtin tool '${i}' is disabled for this agent. Do not retry filesystem tools; use the agent's registered workspace tools and already collected evidence instead.`})}export function resolveFilesystemPermissions(e,t){const i=readConfigRecord(t?.config,"builtinTools"),o=[];if(o.push(...function skillReadPermissions(e,t){const i=[...new Set((t?.skills??[]).flatMap(t=>function skillReadPaths(e,t){return t?[...new Set([t,canonicalPath(t),backendSkillPath(e,t)])].flatMap(e=>function skillReadPathCandidates(e){const t=e.replace(/\/+$/u,""),i=t.endsWith("/SKILL.md")?t.slice(0,-9):t,o=function parentPath(e){const t=e.lastIndexOf("/");return t>0?e.slice(0,t):void 0}(i);return[t,i,`${i}/**`,...o?[o,`${o}/**`]:[]]}(e)):[]}(e.workspace.root,e.workspace.skills.get(t)?.path)).filter(e=>e.startsWith("/")))];return i.length>0?[{operations:["read"],paths:i,mode:"allow"}]:[]}(e,t)),!1!==i?.filesystem){if(deepagentsMemoryWritable(e))return o.length>0?o:void 0}else o.push({operations:["read"],paths:["/memories/**"],mode:"allow"}),o.push({operations:["read","write"],paths:["/**"],mode:"deny"});return deepagentsMemoryWritable(e)||o.push({operations:["write"],paths:["/memories/**"],mode:"deny"}),o.length>0?o:void 0}export function isFilesystemDisabled(e){const t=readConfigRecord(e.agent.config,"builtinTools");return!1===t?.filesystem}export function isFilesystemTool(e){return"string"==typeof e&&filesystemBuiltinToolIds.has(e)}function backendSkillPath(e,t){const i=function pathRelative(e,t){const i=e.split("/").filter(Boolean),o=t.split("/").filter(Boolean);if(!(o.length<i.length)){for(let e=0;e<i.length;e+=1)if(i[e]!==o[e])return;return o.slice(i.length).join("/")}}(e,t);return void 0===i?t:`/${i.split("/").filter(Boolean).join("/")}`}function canonicalPath(t){try{return e.native(t)}catch{return t}}function deepagentsMemoryWritable(e){const t=readConfigRecord(e.workspace.runtime.memory,"deepagentsMem");return!1!==t?.write}function readConfigRecord(e,t){const i=isRecord(e)?e:{};return isRecord(i[t])?i[t]:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|
|
@@ -0,0 +1,13 @@
|
|
|
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 repairTaskCall<T extends {
|
|
5
|
+
toolCall?: {
|
|
6
|
+
id?: string;
|
|
7
|
+
args?: unknown;
|
|
8
|
+
};
|
|
9
|
+
}>(input: AdapterRunInput, request: T): Promise<{
|
|
10
|
+
request: T;
|
|
11
|
+
blocked?: ToolMessage;
|
|
12
|
+
}>;
|
|
13
|
+
export {};
|
package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin/task-inventory.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{repairCallSelection as e}from"@botbotgo/better-call";import{ToolMessage as t}from"@langchain/core/messages";import{normalizeArgsRecord as n}from"../builtin-args.js";export async function repairTaskCall(r,a){const o=function allowedTaskTypes(e){const t=readConfigRecord(e.agent.config,"deepagents");if(!0===t?.generalPurposeAgent)return;const n=readConfigRecord(e.agent.config,"builtinTools")?.modelExposed;return!1===n?[]:Array.isArray(n)?n.includes("task")?e.agent.subagents:[]:0===e.agent.subagents.length?[]:void 0}(r);if(void 0===o)return{request:a};const s=n(a.toolCall?.args),i=function readTaskSubagentType(e){const t=isRecord(e)?e:{};return readString(t.subagent_type)??readString(t.subagentType)}(s);if(i&&o.includes(i))return{request:a};const d=await e({call:{id:i,args:s},candidates:taskCallCandidates(r,o),mode:"repair"});if(d.ok){emitInventoryRepair(r,"repaired",i,d.candidateId,o);const e={...s,...d.args,subagent_type:d.candidateId};return{request:{...a,toolCall:{...a.toolCall,args:e}}}}emitInventoryRepair(r,"blocked",i,void 0,o,d.reason);const l=i?`: ${i}`:"",c=o.length>0?o.join(", "):"none";return{request:a,blocked:new t({tool_call_id:a.toolCall?.id??"stable-harness-task-policy",name:"task",status:"error",content:[`Task delegation target is not in the workspace inventory${l}. Allowed task targets: ${c}.`,"Retry with an allowed target only when that target semantically owns the original user request.","Do not substitute another specialist just to continue the same evidence need; synthesize from already collected evidence when no allowed target is a semantic match."].join(" ")})}}function emitInventoryRepair(e,t,n,r,a,o){e.emit({type:"runtime.adapter.event",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,event:{adapter:"deepagents",phase:"inventory.repair",status:t,diagnostic:{layer:"task",owner:"stable_runtime_policy",originalId:n,repairedId:r,candidateIds:a,reason:o}}})}function taskCallCandidates(e,t){return t.map(t=>({id:t,description:e.workspace.agents.get(t)?.description,schema:{type:"object",properties:{subagent_type:{type:"string"},subagentType:{type:"string"},description:{type:"string"}},required:["description"],additionalProperties:!0}}))}function readConfigRecord(e,t){const n=isRecord(e)?e:{};return isRecord(n[t])?n[t]:void 0}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|
package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-tool-policy.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { type ToolRepeatState } from "./gateway-tools.js";
|
|
1
|
+
import type { RuntimeAdapter } from "@stable-harness/core";
|
|
2
|
+
import { type ToolRepeatState } from "@stable-harness/core";
|
|
4
3
|
type AdapterRunInput = Parameters<RuntimeAdapter["run"]>[0];
|
|
5
4
|
export declare function createBuiltinToolPolicyMiddleware(input: AdapterRunInput, options?: {
|
|
6
5
|
repeatState?: ToolRepeatState;
|
|
@@ -13,11 +12,6 @@ export declare function createBuiltinToolPolicyMiddleware(input: AdapterRunInput
|
|
|
13
12
|
toolChoice?: unknown;
|
|
14
13
|
}, handler: (request: unknown) => Promise<unknown>): Promise<unknown>;
|
|
15
14
|
};
|
|
16
|
-
export declare function validateFilesystemBuiltinCall(input: AdapterRunInput, toolId: string, request: {
|
|
17
|
-
toolCall?: {
|
|
18
|
-
id?: string;
|
|
19
|
-
};
|
|
20
|
-
}): ToolMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>> | undefined;
|
|
21
15
|
export declare function createObserverMiddleware(input: AdapterRunInput, options?: {
|
|
22
16
|
observedToolIds?: Set<string>;
|
|
23
17
|
repeatState?: ToolRepeatState;
|
|
@@ -31,9 +25,4 @@ export declare function createObserverMiddleware(input: AdapterRunInput, options
|
|
|
31
25
|
};
|
|
32
26
|
}, handler: (request: unknown) => Promise<unknown>): Promise<unknown>;
|
|
33
27
|
};
|
|
34
|
-
export declare function resolveFilesystemPermissions(input: AdapterRunInput, agent: WorkspaceAgent | undefined): {
|
|
35
|
-
operations: string[];
|
|
36
|
-
paths: string[];
|
|
37
|
-
mode: string;
|
|
38
|
-
}[] | undefined;
|
|
39
28
|
export {};
|
package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-tool-policy.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
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):{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",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}
|
package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/gateway-tools.d.ts
CHANGED
|
@@ -1,30 +1,8 @@
|
|
|
1
1
|
import { ToolMessage } from "@langchain/core/messages";
|
|
2
2
|
import type { RuntimeAdapter } from "@stable-harness/core";
|
|
3
3
|
import type { RuntimeToolRepairModel } from "@stable-harness/core";
|
|
4
|
-
|
|
5
|
-
successfulCalls: Map<string, string>;
|
|
6
|
-
duplicateCallCounts: Map<string, number>;
|
|
7
|
-
latestSuccessfulOutputByTool: Map<string, string>;
|
|
8
|
-
successfulToolCounts: Map<string, number>;
|
|
9
|
-
toolCallCounts: Map<string, number>;
|
|
10
|
-
maxDuplicateCallsPerTool?: number;
|
|
11
|
-
maxCallsPerTool?: number;
|
|
12
|
-
maxSuccessfulCallsPerTool?: number;
|
|
13
|
-
maxCallsByTool: Map<string, number>;
|
|
14
|
-
maxSuccessfulCallsByTool: Map<string, number>;
|
|
15
|
-
returnPreviousOutputOnRepeatLimit: boolean;
|
|
16
|
-
};
|
|
4
|
+
import { type ToolRepeatState } from "@stable-harness/core";
|
|
17
5
|
export declare function buildGatewayTools(input: Parameters<RuntimeAdapter["run"]>[0], agentId: string, toolIds: string[], repairModel?: RuntimeToolRepairModel, repeatState?: ToolRepeatState | undefined): import("@langchain/core/tools").DynamicTool<string | ToolMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>>, unknown>[];
|
|
18
|
-
export declare function createToolRepeatState(config: unknown): ToolRepeatState | undefined;
|
|
19
|
-
export declare function beforeToolInvoke(toolId: string, args: unknown, state: ToolRepeatState): {
|
|
20
|
-
eventOutput: string;
|
|
21
|
-
modelOutput: string;
|
|
22
|
-
} | undefined;
|
|
23
|
-
export declare function isToolRepeatLimitReached(toolId: string, state: ToolRepeatState | undefined): boolean;
|
|
24
|
-
export declare function afterToolInvoke(toolId: string, args: unknown, output: string, result: unknown, state: ToolRepeatState): {
|
|
25
|
-
eventOutput?: string;
|
|
26
|
-
modelOutput?: string;
|
|
27
|
-
};
|
|
28
6
|
export declare function stringifyDeepAgentResult(result: unknown): string;
|
|
29
7
|
export declare function toolControlProjection(output: string): {
|
|
30
8
|
controlStatus: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ToolMessage as e}from"@langchain/core/messages";import{tool as t}from"@langchain/core/tools";import{isSuccessfulEvidenceOutput as o,observedToolEvidence as r,recordObservedToolEvidence as n}from"./gateway/tool-evidence.js";import{emitStructuredToolFailure as s}from"./gateway/tool-failure-events.js";export function buildGatewayTools(o,n,a,i,l=createToolRepeatState(o.workspace.runtime.toolGateway)){return o.toolGateway?a.flatMap(a=>{const u=o.toolGateway?.get(a);if(!u)return[];const c=o.workspace.tools.get(a),d=c?.schema??u.schema;return[t(async t=>async function invokeGuardedGatewayTool(t){emitToolResult(t.input,t.agentId,t.toolId,void 0);const o=function missingRequiredPlanContent(e,t){const o=readRecord(e.agent.config.executionContract);if(!0!==o?.requiresPlan)return"";const n=readStringArray(o.planEvidenceTools);if(0===n.length||n.includes(t))return"";const s=new Set(r(e).map(e=>e.toolId));return n.some(e=>s.has(e))?"":["Status: plan_required",`Evidence tool: ${t}`,`Blocker: execution contract requires a planning checkpoint from one of: ${n.join(", ")} before evidence tools run.`,"Instruction: call the planning tool first, then retry this atomic evidence tool with repaired arguments."].join("\n")}(t.input,t.toolId);if(o)return emitToolResult(t.input,t.agentId,t.toolId,o),o;const n=function missingToolDependencyContent(e,t){const o=readRecord(e.agent.config.executionContract),n=readStringArray(readRecord(o.toolDependencies)[t]);if(0===n.length)return"";const s=new Set(r(e).map(e=>e.toolId)),a=n.filter(e=>!s.has(e));return 0===a.length?"":["Status: dependency_required",`Evidence tool: ${t}`,`Blocker: this atomic evidence tool requires completed dependency evidence from: ${a.join(", ")}.`,"Instruction: complete the dependency tool first, evaluate it, then retry this atomic evidence tool."].join("\n")}(t.input,t.toolId);if(n)return emitToolResult(t.input,t.agentId,t.toolId,n),n;const a=t.repeatState?beforeToolInvoke(t.toolId,t.args,t.repeatState):void 0;if(a)return emitToolResult(t.input,t.agentId,t.toolId,a.eventOutput),a.modelOutput;const i=await async function invokeGatewayTool(t,o,r,n,a){try{if(t.toolFailureTracker?.isCircuitOpen(r))throw new Error(`Tool circuit is open: ${r}`);const e=await t.toolGateway.invoke({toolId:r,args:n,repairModel:a,context:{workspaceRoot:t.workspace.root,requestId:t.requestId,sessionId:t.sessionId,agentId:o,requestInput:t.request.input,observedEvidence:formatObservedEvidenceForToolContext(t),approvalIds:readApprovalIds(t.request.metadata)}});return t.toolFailureTracker?.recordSuccess(r),e}catch(n){if(s(t,o,r,n),function isToolArgumentValidationError(e){return e instanceof Error&&"ToolArgumentValidationError"===e.name&&"string"==typeof e.toolId&&Array.isArray(e.issues)}(n))return new e({tool_call_id:`stable-harness-${r}-argument-guard`,name:r,status:"error",content:formatToolArgumentError(n)});if(t.workspace.runtime.retry?.tools?.enabled)throw n;return new e({tool_call_id:`stable-harness-${r}-execution-error`,name:r,status:"error",content:JSON.stringify({error:"tool_execution_failed",toolId:r,message:formatError(n),retry:"Use the error as evidence, adjust the tool arguments if possible, or return a final answer with the blocker."})})}}(t.input,t.agentId,t.toolId,t.args,t.repairModel),l=i instanceof e?String(i.content):stringifyDeepAgentResult(i.output),u=t.repeatState?afterToolInvoke(t.toolId,t.args,l,i,t.repeatState):{};return emitToolResult(t.input,t.agentId,t.toolId,u.eventOutput??l),void 0!==u.modelOutput?u.modelOutput:i instanceof e?i:l}({input:o,agentId:n,toolId:a,args:t,repairModel:i,repeatState:l}),{name:a,description:buildToolDescription(c?.description??u.description??a,d,o.workspace.runtime.toolGateway,a),schema:{type:"object",additionalProperties:!0}})]}):[]}export function createToolRepeatState(e){if(function repeatGuardEnabled(e){return!0===repeatGuardConfig(e).enabled}(e))return{successfulCalls:new Map,duplicateCallCounts:new Map,latestSuccessfulOutputByTool:new Map,successfulToolCounts:new Map,toolCallCounts:new Map,maxDuplicateCallsPerTool:readPositiveInteger(repeatGuardConfig(e).maxDuplicateCallsPerTool)??3,maxCallsPerTool:readPositiveInteger(repeatGuardConfig(e).maxCallsPerTool),maxSuccessfulCallsPerTool:readPositiveInteger(repeatGuardConfig(e).maxSuccessfulCallsPerTool),maxCallsByTool:readPositiveIntegerMap(repeatGuardConfig(e).maxCallsByTool),maxSuccessfulCallsByTool:readPositiveIntegerMap(repeatGuardConfig(e).maxSuccessfulCallsByTool),returnPreviousOutputOnRepeatLimit:!0===repeatGuardConfig(e).returnPreviousOutputOnRepeatLimit}}function repeatGuardConfig(e){return isRecord(e)&&isRecord(e.repeatGuard)?e.repeatGuard:{}}function readPositiveInteger(e){return"number"==typeof e&&Number.isInteger(e)&&e>0?e:void 0}function readPositiveIntegerMap(e){return isRecord(e)?new Map(Object.entries(e).map(([e,t])=>[e,readPositiveInteger(t)]).filter(e=>void 0!==e[1])):new Map}export function beforeToolInvoke(e,t,o){const r=o.toolCallCounts.get(e)??0;o.toolCallCounts.set(e,r+1);const n=o.maxCallsByTool.get(e)??o.maxCallsPerTool;if(void 0!==n&&r>=n){const t=o.latestSuccessfulOutputByTool.get(e),r=repeatedToolCallLimitContent(e,t);return{eventOutput:r,modelOutput:repeatLimitModelOutput(r,t,o)}}const s=o.maxSuccessfulCallsByTool.get(e)??o.maxSuccessfulCallsPerTool;if(void 0!==s&&(o.successfulToolCounts.get(e)??0)>=s){const t=o.latestSuccessfulOutputByTool.get(e),r=repeatedToolCallLimitContent(e,t);return{eventOutput:r,modelOutput:repeatLimitModelOutput(r,t,o)}}const a=stableToolCallKey(e,t),i=o.successfulCalls.get(a);if(void 0!==i){const t=o.duplicateCallCounts.get(a)??0;if(o.duplicateCallCounts.set(a,t+1),void 0!==o.maxDuplicateCallsPerTool&&t>=o.maxDuplicateCallsPerTool){const t=repeatedToolCallLimitContent(e);return{eventOutput:t,modelOutput:t}}const r=function duplicateToolCallContent(e,t){return JSON.stringify({status:"duplicate_tool_call",toolId:e,instruction:"This agent already completed an equivalent tool call. Use the prior evidence instead of calling the tool again.",previousOutput:t})}(e,i);return{eventOutput:r,modelOutput:i}}}function repeatLimitModelOutput(e,t,o){return o.returnPreviousOutputOnRepeatLimit&&void 0!==t&&0!==t.trim().length?t:e}export function isToolRepeatLimitReached(e,t){if(!t)return!1;const o=t.maxCallsByTool.get(e)??t.maxCallsPerTool;if(void 0!==o&&(t.toolCallCounts.get(e)??0)>=o)return!0;const r=t.maxSuccessfulCallsByTool.get(e)??t.maxSuccessfulCallsPerTool;return void 0!==r&&(t.successfulToolCounts.get(e)??0)>=r}export function afterToolInvoke(t,r,n,s,a){return s instanceof e&&"error"===s.status?{}:o(n)?(a.successfulCalls.set(stableToolCallKey(t,r),n),a.latestSuccessfulOutputByTool.set(t,n),a.successfulToolCounts.set(t,(a.successfulToolCounts.get(t)??0)+1),{}):{}}function emitToolResult(e,t,o,r){void 0!==r&&n(e,t,o,r),e.emit({type:"runtime.adapter.event",requestId:e.requestId,sessionId:e.sessionId,agentId:t,event:void 0===r?{adapter:"deepagents",phase:"agent.tool.start",toolId:o}:{adapter:"deepagents",phase:"agent.tool.result",toolId:o,output:previewToolOutput(r),evidenceOutput:r,...toolControlProjection(r)}})}function repeatedToolCallLimitContent(e,t){return JSON.stringify({status:"repeated_tool_call_limit",toolId:e,instruction:"This tool reached the configured repeat limit for this request. Do not call this tool or a substitute tool for the same evidence need again. Use previousOutput and the collected evidence to produce the final answer now, or report the remaining gap explicitly.",...void 0!==t?{previousOutput:t}:{}})}export function stringifyDeepAgentResult(t){if(t instanceof e)return function stringifyToolMessageContent(e){return"string"==typeof e?e:JSON.stringify(e)}(t.content);if("string"==typeof t)return t;if(isRecord(t)){const e=t.structuredResponse??t.structured_response;if(void 0!==e)return"string"==typeof e?e:JSON.stringify(e);const o=(Array.isArray(t.messages)?t.messages:[]).at(-1);if(isRecord(o)&&"string"==typeof o.content)return o.content;const r=(isRecord(t.update)&&Array.isArray(t.update.messages)?t.update.messages:[]).at(-1);if(isRecord(r)&&isRecord(r.kwargs)&&"string"==typeof r.kwargs.content)return r.kwargs.content;if(isRecord(r)&&"string"==typeof r.content)return r.content}return JSON.stringify(t)}function buildToolDescription(e,t,o,r){const n=function toolRepeatPolicyDescription(e,t){const o=repeatGuardConfig(e),r=readPositiveIntegerMap(o.maxSuccessfulCallsByTool).get(t)??readPositiveInteger(o.maxSuccessfulCallsPerTool);return void 0===r?"":`Stable runtime repeat policy: call this tool at most ${r} successful time(s) for this request. If more detail is needed, include the dimensions in the first call and synthesize after the result returns.`}(o,r),s=n?`${e}\n\n${n}`:e;return t?`${s}\n\nStable tool input schema:\n${previewToolOutput(JSON.stringify(t))}`:s}function previewToolOutput(e){const t=e.replace(/\s+/gu," ").trim();return t.length>500?`${t.slice(0,497)}...`:t}export function toolControlProjection(e){const t=function parseJsonRecord(e){try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e);if("string"==typeof t?.status)return{controlStatus:t.status};const o=function readTextStatus(e){return String(e).match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}(e);return o?{controlStatus:o}:"string"==typeof t?.error?{controlStatus:t.error}:e.startsWith("Task delegation target is not in the workspace inventory")?{controlStatus:"task_inventory_blocked"}:{}}function stableToolCallKey(e,t){return`${e}:${stableJson(t)}`}function stableJson(e){return Array.isArray(e)?`[${e.map(stableJson).join(",")}]`:isRecord(e)?`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${stableJson(e[t])}`).join(",")}}`:JSON.stringify(e)}function readApprovalIds(e){const t=e?.approvalIds??e?.approvalId;return"string"==typeof t&&t.trim()?[t.trim()]:Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.trim().length>0):void 0}function formatObservedEvidenceForToolContext(e){const t=r(e).map(e=>`Tool: ${e.toolId}\n${e.output}`).join("\n\n---\n\n");return t.length>12e3?`${t.slice(0,12e3)}\n[truncated]`:t}function formatToolArgumentError(e){return JSON.stringify({error:"tool_argument_validation_failed",toolId:e.toolId,issues:e.issues,retry:"Call the same tool again with arguments that satisfy the reported schema and semantic issues."})}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function readRecord(e){return isRecord(e)?e:{}}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}function formatError(e){return e instanceof Error?e.message:String(e)}
|
|
1
|
+
import{ToolMessage as t}from"@langchain/core/messages";import{tool as e}from"@langchain/core/tools";import{afterToolInvoke as o,beforeToolInvoke as r,createToolRepeatState as n,missingRequiredPlanContent as s,missingToolDependencyContent as a,toolInvocationEvents as i}from"@stable-harness/core";import{isSuccessfulEvidenceOutput as u,observedToolEvidence as l,recordObservedToolEvidence as c}from"./gateway/tool-evidence.js";import{emitStructuredToolFailure as d}from"./gateway/tool-failure-events.js";export function buildGatewayTools(l,c,p,f,g=n(l.workspace.runtime.toolGateway)){return l.toolGateway?p.flatMap(n=>{const p=l.toolGateway?.get(n);if(!p)return[];const m=l.workspace.tools.get(n),y=m?.schema??p.schema;return[e(async e=>async function invokeGuardedGatewayTool(e){emitToolResult(e.input,e.agentId,e.toolId,void 0);const n=i({request:e.input.request,getEvents:e.input.getEvents}),l=s({agent:e.input.agent,events:n,toolId:e.toolId});if(l)return emitToolResult(e.input,e.agentId,e.toolId,l),l;const c=a({agent:e.input.agent,events:n,toolId:e.toolId});if(c)return emitToolResult(e.input,e.agentId,e.toolId,c),c;const p=e.repeatState?r(e.toolId,e.args,e.repeatState):void 0;if(p)return emitToolResult(e.input,e.agentId,e.toolId,p.eventOutput),p.modelOutput;const f=await async function invokeGatewayTool(e,o,r,n,s){try{if(e.toolFailureTracker?.isCircuitOpen(r))throw new Error(`Tool circuit is open: ${r}`);const t=await e.toolGateway.invoke({toolId:r,args:n,repairModel:s,context:{workspaceRoot:e.workspace.root,requestId:e.requestId,sessionId:e.sessionId,agentId:o,requestInput:e.request.input,observedEvidence:formatObservedEvidenceForToolContext(e),approvalIds:readApprovalIds(e.request.metadata)}});return e.toolFailureTracker?.recordSuccess(r),t}catch(n){if(d(e,o,r,n),function isToolArgumentValidationError(t){return t instanceof Error&&"ToolArgumentValidationError"===t.name&&"string"==typeof t.toolId&&Array.isArray(t.issues)}(n))return new t({tool_call_id:`stable-harness-${r}-argument-guard`,name:r,status:"error",content:formatToolArgumentError(n)});if(e.workspace.runtime.retry?.tools?.enabled)throw n;return new t({tool_call_id:`stable-harness-${r}-execution-error`,name:r,status:"error",content:JSON.stringify({error:"tool_execution_failed",toolId:r,message:formatError(n),retry:"Use the error as evidence, adjust the tool arguments if possible, or return a final answer with the blocker."})})}}(e.input,e.agentId,e.toolId,e.args,e.repairModel),g=f instanceof t?String(f.content):stringifyDeepAgentResult(f.output),m=e.repeatState?o({toolId:e.toolId,args:e.args,output:g,successful:!(f instanceof t&&"error"===f.status)&&u(g),state:e.repeatState}):{};return emitToolResult(e.input,e.agentId,e.toolId,m.eventOutput??g),void 0!==m.modelOutput?m.modelOutput:f instanceof t?f:g}({input:l,agentId:c,toolId:n,args:e,repairModel:f,repeatState:g}),{name:n,description:buildToolDescription(m?.description??p.description??n,y,l.workspace.runtime.toolGateway,n),schema:{type:"object",additionalProperties:!0}})]}):[]}function emitToolResult(t,e,o,r){void 0!==r&&c(t,e,o,r),t.emit({type:"runtime.adapter.event",requestId:t.requestId,sessionId:t.sessionId,agentId:e,event:void 0===r?{adapter:"deepagents",phase:"agent.tool.start",toolId:o}:{adapter:"deepagents",phase:"agent.tool.result",toolId:o,output:previewToolOutput(r),evidenceOutput:r,...toolControlProjection(r)}})}export function stringifyDeepAgentResult(e){if(e instanceof t)return function stringifyToolMessageContent(t){return"string"==typeof t?t:JSON.stringify(t)}(e.content);if("string"==typeof e)return e;if(isRecord(e)){const t=e.structuredResponse??e.structured_response;if(void 0!==t)return"string"==typeof t?t:JSON.stringify(t);const o=(Array.isArray(e.messages)?e.messages:[]).at(-1);if(isRecord(o)&&"string"==typeof o.content)return o.content;const r=(isRecord(e.update)&&Array.isArray(e.update.messages)?e.update.messages:[]).at(-1);if(isRecord(r)&&isRecord(r.kwargs)&&"string"==typeof r.kwargs.content)return r.kwargs.content;if(isRecord(r)&&"string"==typeof r.content)return r.content}return JSON.stringify(e)}function buildToolDescription(t,e,o,r){const n=function toolRepeatPolicyDescription(t,e){const o=function repeatGuardConfig(t){return isRecord(t)&&isRecord(t.repeatGuard)?t.repeatGuard:{}}(t),r=function readPositiveIntegerMap(t){return isRecord(t)?new Map(Object.entries(t).map(([t,e])=>[t,readPositiveInteger(e)]).filter(t=>void 0!==t[1])):new Map}(o.maxSuccessfulCallsByTool).get(e)??readPositiveInteger(o.maxSuccessfulCallsPerTool);return void 0===r?"":`Stable runtime repeat policy: call this tool at most ${r} successful time(s) for this request. If more detail is needed, include the dimensions in the first call and synthesize after the result returns.`}(o,r),s=n?`${t}\n\n${n}`:t;return e?`${s}\n\nStable tool input schema:\n${previewToolOutput(JSON.stringify(e))}`:s}function readPositiveInteger(t){return"number"==typeof t&&Number.isInteger(t)&&t>0?t:void 0}function previewToolOutput(t){const e=t.replace(/\s+/gu," ").trim();return e.length>500?`${e.slice(0,497)}...`:e}export function toolControlProjection(t){const e=function parseJsonRecord(t){try{const e=JSON.parse(t);return isRecord(e)?e:void 0}catch{return}}(t);if("string"==typeof e?.status)return{controlStatus:e.status};const o=function readTextStatus(t){return String(t).match(/^Status:\s*([A-Za-z0-9_-]+)/imu)?.[1]}(t);return o?{controlStatus:o}:"string"==typeof e?.error?{controlStatus:e.error}:t.startsWith("Task delegation target is not in the workspace inventory")?{controlStatus:"task_inventory_blocked"}:{}}function readApprovalIds(t){const e=t?.approvalIds??t?.approvalId;return"string"==typeof e&&e.trim()?[e.trim()]:Array.isArray(e)?e.filter(t=>"string"==typeof t&&t.trim().length>0):void 0}function formatObservedEvidenceForToolContext(t){const e=l(t).map(t=>`Tool: ${t.toolId}\n${t.output}`).join("\n\n---\n\n");return e.length>12e3?`${e.slice(0,12e3)}\n[truncated]`:e}function formatToolArgumentError(t){return JSON.stringify({error:"tool_argument_validation_failed",toolId:t.toolId,issues:t.issues,retry:"Call the same tool again with arguments that satisfy the reported schema and semantic issues."})}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function formatError(t){return t instanceof Error?t.message:String(t)}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ToolRepeatState } from "@stable-harness/core";
|
|
2
2
|
export declare function filterRepeatLimitedTools<T extends {
|
|
3
3
|
name?: unknown;
|
|
4
4
|
}>(tools: T[] | undefined, repeatState: ToolRepeatState | undefined): T[] | undefined;
|
package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/tool-repeat-visibility.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isToolRepeatLimitReached as e}from"
|
|
1
|
+
import{isToolRepeatLimitReached as e}from"@stable-harness/core";export function filterRepeatLimitedTools(t,i){return t&&i?t.filter(t=>"string"!=typeof t.name||!e(t.name,i)):t}
|
package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/trace-projection.d.ts
CHANGED
|
@@ -1,16 +1 @@
|
|
|
1
|
-
export declare function traceProjectionForBuiltinTool(toolId: string, phase: "agent.tool.start" | "agent.tool.result", args: unknown): {
|
|
2
|
-
traceType: string;
|
|
3
|
-
traceLabel: string;
|
|
4
|
-
subagentType: string | undefined;
|
|
5
|
-
todos?: undefined;
|
|
6
|
-
} | {
|
|
7
|
-
traceType: string;
|
|
8
|
-
traceLabel: string;
|
|
9
|
-
todos: any[];
|
|
10
|
-
subagentType?: undefined;
|
|
11
|
-
} | {
|
|
12
|
-
traceType?: undefined;
|
|
13
|
-
traceLabel?: undefined;
|
|
14
|
-
subagentType?: undefined;
|
|
15
|
-
todos?: undefined;
|
|
16
|
-
};
|
|
1
|
+
export declare function traceProjectionForBuiltinTool(toolId: string, phase: "agent.tool.start" | "agent.tool.result", args: unknown): {};
|
package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/trace-projection.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function traceProjectionForBuiltinTool(
|
|
1
|
+
import{createDelegationTraceProjection as t,createPlanTraceProjection as e}from"@stable-harness/core";export function traceProjectionForBuiltinTool(r,o,n){return"task"===r?t("agent.tool.start"===o?"delegation.start":"delegation.completed",{subagentType:readTaskSubagentType(n)}):"write_todos"===r&&"agent.tool.result"===o?e("plan.updated",{todos:readTodoArgs(n)}):{}}function readTaskSubagentType(t){const e=isRecord(t)?t:{};return readString(e.subagent_type)??readString(e.subagentType)}function readTodoArgs(t){const e=isRecord(t)?t:{};return Array.isArray(e.todos)?e.todos:[]}function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}function readString(t){return"string"==typeof t&&t.trim()?t:void 0}
|
|
@@ -7,9 +7,11 @@ export * from "./runtime/persistence/inspection.js";
|
|
|
7
7
|
export { createWorkspaceSandboxPolicy } from "./runtime/governance/sandbox.js";
|
|
8
8
|
export * from "./memory-plugins.js";
|
|
9
9
|
export * from "./runtime/persistence/queue.js";
|
|
10
|
+
export * from "./runtime/policy/projection.js";
|
|
10
11
|
export * from "./runtime.js";
|
|
11
12
|
export * from "./runtime/selection-repair.js";
|
|
12
13
|
export * from "./runtime/tool-failure.js";
|
|
14
|
+
export * from "./runtime/policy/tool-invocation.js";
|
|
13
15
|
export * from "./runtime/persistence/stores.js";
|
|
14
16
|
export * from "./trace.js";
|
|
15
17
|
export * from "./types.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./runtime/persistence/artifacts.js";export*from"./boundary-scan.js";export*from"./execution-contract.js";export*from"./recovery/tool-call.js";export*from"./runtime/persistence/inspection.js";export{createWorkspaceSandboxPolicy}from"./runtime/governance/sandbox.js";export*from"./memory-plugins.js";export*from"./runtime/persistence/queue.js";export*from"./runtime.js";export*from"./runtime/selection-repair.js";export*from"./runtime/tool-failure.js";export*from"./runtime/persistence/stores.js";export*from"./trace.js";export*from"./types.js";export*from"./workspace/tool-quality.js";export*from"./evaluations/index.js";export*from"./quality/index.js";export*from"./spec-driven/index.js";export*from"./workflows/index.js";
|
|
1
|
+
export*from"./runtime/persistence/artifacts.js";export*from"./boundary-scan.js";export*from"./execution-contract.js";export*from"./recovery/tool-call.js";export*from"./runtime/persistence/inspection.js";export{createWorkspaceSandboxPolicy}from"./runtime/governance/sandbox.js";export*from"./memory-plugins.js";export*from"./runtime/persistence/queue.js";export*from"./runtime/policy/projection.js";export*from"./runtime.js";export*from"./runtime/selection-repair.js";export*from"./runtime/tool-failure.js";export*from"./runtime/policy/tool-invocation.js";export*from"./runtime/persistence/stores.js";export*from"./trace.js";export*from"./types.js";export*from"./workspace/tool-quality.js";export*from"./evaluations/index.js";export*from"./quality/index.js";export*from"./spec-driven/index.js";export*from"./workflows/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function resolveQualityPolicy(e,n){const r=n.config.quality??e.quality,i=function readProfile(e){const n="string"==typeof e?e:isRecord(e)?e.profile:void 0;return"fast"===n||"balanced"===n||"strict"===n?n:"off"}(r),
|
|
1
|
+
export function resolveQualityPolicy(e,n){const r=n.config.quality??e.quality,i=function readProfile(e){const n="string"==typeof e?e:isRecord(e)?e.profile:void 0;return"fast"===n||"balanced"===n||"strict"===n?n:"off"}(r),t=function profileDefaults(e,n){const r=n.tools.length>0||n.subagents.length>0||(n.skills?.length??0)>0;return"off"===e?function disabledPolicy(e){return{enabled:!1,profile:e,reviewer:{mode:"deterministic"},planningReview:{enabled:!1,requirePlan:!1},executionReview:{enabled:!1,requireToolEvidence:!1,rejectEmptyFinal:!1,stopOnBlocker:!1,rejectUngroundedNumbers:!1},synthesis:{enabled:!1,mode:"evidence_only",maxEvidenceItems:5},recovery:{enabled:!1,maxLoops:0}}}(e):{enabled:!0,profile:e,planningReview:{enabled:"fast"!==e,requirePlan:"fast"!==e&&r},executionReview:{enabled:!0,requireToolEvidence:"strict"===e&&r,rejectEmptyFinal:!0,stopOnBlocker:!0,rejectUngroundedNumbers:"strict"===e},synthesis:{enabled:!1,mode:"evidence_only",maxEvidenceItems:5},recovery:{enabled:"fast"!==e,maxLoops:"strict"===e?3:2}}}(i,n),o=isRecord(r)?r:{},a=function readReviewer(e){const n=isRecord(e.reviewer)?e.reviewer:e,r="llm"===n.mode||"string"==typeof n.modelRef?"llm":"deterministic",i=isRecord(n.prompts)?n.prompts:{},t=readString(n.modelRef);return{mode:r,...t?{modelRef:t}:{},...readString(n.planningPrompt)??readString(i.planning)?{planningPrompt:readString(n.planningPrompt)??readString(i.planning)}:{},...readString(n.executionPrompt)??readString(i.execution)?{executionPrompt:readString(n.executionPrompt)??readString(i.execution)}:{}}}(o);return{enabled:t.enabled,profile:i,...a?{reviewer:a}:{},planningReview:{enabled:readBoolean(o.planningReview,"enabled")??t.planningReview.enabled,requirePlan:readBoolean(o.planningReview,"requirePlan")??t.planningReview.requirePlan},executionReview:{enabled:readBoolean(o.executionReview,"enabled")??t.executionReview.enabled,requireToolEvidence:readBoolean(o.executionReview,"requireToolEvidence")??t.executionReview.requireToolEvidence,rejectEmptyFinal:readBoolean(o.executionReview,"rejectEmptyFinal")??t.executionReview.rejectEmptyFinal,stopOnBlocker:readBoolean(o.executionReview,"stopOnBlocker")??t.executionReview.stopOnBlocker,rejectUngroundedNumbers:readBoolean(o.executionReview,"rejectUngroundedNumbers")??t.executionReview.rejectUngroundedNumbers},synthesis:{enabled:readBoolean(o.synthesis,"enabled")??t.synthesis.enabled,mode:(d=o.synthesis,("evidence_only"===(isRecord(d)?d:{}).mode?"evidence_only":void 0)??t.synthesis.mode),maxEvidenceItems:readPositiveInteger(o.synthesis,"maxEvidenceItems")??t.synthesis.maxEvidenceItems,...readFieldKinds(o.synthesis)?{fieldKinds:readFieldKinds(o.synthesis)}:{}},recovery:{enabled:readBoolean(o.recovery,"enabled")??t.recovery.enabled,maxLoops:readPositiveInteger(o.recovery,"maxLoops")??t.recovery.maxLoops}};var d}function readString(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function readBoolean(e,n){const r=isRecord(e)?e:{};return"boolean"==typeof r[n]?r[n]:void 0}function readPositiveInteger(e,n){const r=(isRecord(e)?e:{})[n];return"number"==typeof r&&Number.isInteger(r)&&r>0?r:void 0}function readFieldKinds(e){const n=isRecord(e)?e:{},r=isRecord(n.fieldKinds)?n.fieldKinds:void 0;if(r)return{...readStringArray(r.context).length>0?{context:readStringArray(r.context)}:{},...readStringArray(r.data).length>0?{data:readStringArray(r.data)}:{},...readStringArray(r.timeBound).length>0?{timeBound:readStringArray(r.timeBound)}:{},...readStringArray(r.limit).length>0?{limit:readStringArray(r.limit)}:{},...readStringArray(r.other).length>0?{other:readStringArray(r.other)}:{}}}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.trim().length>0):[]}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|
|
@@ -11,9 +11,10 @@ export type EvidenceField = {
|
|
|
11
11
|
value: string;
|
|
12
12
|
kind: FactKind;
|
|
13
13
|
};
|
|
14
|
-
export
|
|
14
|
+
export type EvidenceClassificationHints = Partial<Record<FactKind, string[]>>;
|
|
15
|
+
export declare function evidenceFields(facts: EvidenceFact[], hints?: EvidenceClassificationHints): EvidenceField[];
|
|
15
16
|
export declare function selectSectionFields(fields: EvidenceField[], kind: FactKind, limit: number): EvidenceField[];
|
|
16
17
|
export declare function fieldTableLines(fields: EvidenceField[], language: SynthesisLanguage): string[];
|
|
17
18
|
export declare function hasExtractableFields(text: string): boolean;
|
|
18
|
-
export declare function classifyFact(text: string): FactKind;
|
|
19
|
+
export declare function classifyFact(text: string, hints?: EvidenceClassificationHints): FactKind;
|
|
19
20
|
export declare function normalizeFieldLabel(label: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function evidenceFields(e){const
|
|
1
|
+
export function evidenceFields(e,t={}){const l=new Set,i=[];for(const n of e)for(const e of parseEvidenceFields(n,t)){const t=`${normalizeFieldLabel(e.label)}\0${e.value.toLowerCase()}`;l.has(t)||(l.add(t),i.push(e))}return i}export function selectSectionFields(e,t,l){return function withSourceCoverage(e,t){const l=[...e].sort((e,t)=>scoreField(t)-scoreField(e)),i=new Map;for(const e of[...new Set(l.map(e=>e.source))]){const t=l.find(t=>t.source===e);t&&i.set(fieldKey(t),t)}for(const e of l)if(i.set(fieldKey(e),e),i.size>=t)break;return[...i.values()].slice(0,t)}(e.filter(e=>e.kind===t),l).sort((e,t)=>scoreField(t)-scoreField(e)||e.label.localeCompare(t.label))}export function fieldTableLines(e,t){return 0===e.length?[]:[..."zh"===t?["| 项目 | 数值 | 来源 |","|---|---:|---|"]:["| Field | Value | Source |","|---|---:|---|"],...e.map(e=>`| ${escapeTableCell(e.label)} | ${escapeTableCell(e.value)} | ${escapeTableCell(function humanSourceLabel(e){const t=e.replace(/([a-z])([A-Z])/gu,"$1 $2").split(/[_:.\-\s]+/u).map(e=>e.trim()).filter(Boolean);return 0===t.length?e:t.map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}(e.source))} |`)]}export function hasExtractableFields(e){return extractKeyValueFields(e).some(e=>!isBoilerplateField(e.label)&&e.value.length>0)}export function classifyFact(e,t={}){const l=function classifyByHints(e,t){const l=normalizeFieldLabel(e);for(const e of["limit","timeBound","data","context","other"])if((t[e]??[]).some(e=>l.includes(normalizeFieldLabel(e))))return e}(e,t);return l||(/(?:gap|blocked|missing|unavailable|unsupported|缺口|阻塞|缺失|不支持|无法|未提供)/iu.test(e)?"limit":/(?:date|time|published|updated|timestamp|deadline|日期|时间|发布|更新|\b20\d{2}[-/年])/iu.test(e)?"timeBound":/(?:[$€£¥%]|\b\d[\d,]*(?:\.\d+)?\b)/u.test(e)?"data":/(?:name|title|identifier|entity|subject|query|名称|标题|标识|识别)/iu.test(e)?"context":"other")}function parseEvidenceFields(e,t){return extractKeyValueFields(e.text,t).filter(e=>e.value.length>0&&!isBoilerplateField(e.label)).filter(e=>!function isLowValueField(e,t){return!!/(?:snapshot for|source type|loaded sources)/iu.test(e)||!!/^\d{1,2}\s+(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b/iu.test(e)||scoreField({source:"",label:e,value:t,kind:"other"})<0}(e.label,e.value)).map(l=>{const i=classifyFact(`${l.label}: ${l.value}`,t);return{source:e.source,label:titleCaseLabel(l.label),value:formatEvidence(l.value),kind:"other"===i?e.kind:i}})}function scoreField(e){const t=normalizeFieldLabel(e.label);let l=e.value.length>0?10:0;return/(?:value|amount|total|ratio|rate|range|estimate|date|status|count|metric|数量|日期|范围|比率)/iu.test(t)&&(l+=8),/(?:name|title|summary|identifier|entity|subject|名称|标题|摘要|标识)/iu.test(t)&&(l+=6),/(?:unix|epoch|timestamp|raw|html|url|href|source|id|identifier|internal|debug)/iu.test(t)&&(l-=20),/^(?:date|time|cik)$/iu.test(t)&&(l-=12),/^(?:open|high|low)$/iu.test(t)&&(l-=4),(/^https?:\/\//iu.test(e.value)||"/"===e.value)&&(l-=12),e.value.length>240&&(l-=5),l}function extractKeyValueFields(e,t={}){const l=[...e.matchAll(/(^|[\s;|])([\p{L}\p{N}][\p{L}\p{N} _./()%&+\-]{0,48})[::](?!\/\/)\s*/gu)].filter(e=>void 0!==e.index).map((e,l,i)=>{const n=i[l-1]?.[2]??"",a=function cleanFieldLabel(e,t="",l={}){const i=e.replace(/^(?:[-*]\s*)+/u,"").replace(/\s+/gu," ").trim(),n=i.match(/^.+\b(PE Ratio TTM)$/iu);if(n?.[1]&&n[1]!==i&&/(?:beta|\b20\d{2}|\b(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b)/iu.test(i))return n[1];const a=i.split(" ").filter(Boolean);return a.length>1&&/^\d{4}$/u.test(a[0]??"")||a.length>1&&/^\d+(?:\.\d+)?$/u.test(a[0]??"")&&/^(?:\d+|beta|pe|p\/b)$/iu.test(a[1]??"")||a.length>1&&/^[A-Z]$/u.test(a[0]??"")||a.length>1&&/^(?:inc\.?|llc\.?|ltd\.?|corp\.?|corporation|co\.?)$/iu.test(a[0]??"")||a.length>1&&/^(?:usd|eur|gbp|jpy|cny|cad|aud)$/iu.test(a[0]??"")||a.length>1&&/^(?:gmt|utc)$/iu.test(a[0]??"")?a.slice(1).join(" "):function trailingKnownLabel(e,t){const l=function trailingHintedLabel(e,t){const l=normalizeFieldLabel(e);return Object.values(t).flat().filter(e=>e.trim().length>0).sort((e,t)=>t.length-e.length).find(e=>l.endsWith(normalizeFieldLabel(e)))}(e,t);if(l)return l;if(/\bPE Ratio TTM$/iu.test(e)&&!/^PE Ratio TTM$/iu.test(e))return"PE Ratio TTM";const i=e.match(/\b(?:Published|Updated|Date|Time|Summary|Title|Identifier|Entity|Subject)$/iu);return i&&/(?:filed|\b20\d{2}|10-k|10-q|\bfy\b|\b(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b|\s{3,}|[a-z].{8,}\s)/iu.test(e.slice(0,i.index))?i?.[0]??e:e}(i,l)}(e[2]??"",n,t),r=function droppedLabelPrefix(e,t){const l=e.trim();if(l===t)return"";const i=l.toLowerCase().lastIndexOf(t.toLowerCase());return i>0?l.slice(0,i):""}(e[2]??"",a);return{index:(e.index??0)+String(e[1]??"").length+r.length,start:(e.index??0)+e[0].length,label:a,rawLabel:e[2]??""}}).filter(e=>!isBoundaryNoiseLabel(e.label)&&!isBoundaryNoiseLabel(e.rawLabel));return l.map((t,i)=>{const n=l[i+1]?.index??e.length;return{label:t.label,value:cleanFieldValue(e.slice(t.start,n),t.label)}}).filter(e=>e.label.length>0)}function cleanFieldValue(e,t){const l=e.replace(/^[\s,;|.-]+/u,"").replace(/[\s,;|.-]+$/u,"").replace(/\s+/gu," ").trim(),i=normalizeFieldLabel(t);if(/\brange\b/iu.test(i))return l.replace(/\s+Beta\b.*$/iu,"").trim();if(/^(?:identifier|entity identifier|标识)$/iu.test(i)){const e=l.match(/^([A-Z0-9._-]{1,24})(?:\s+\d+[.)]\s+|$)/u);if(e?.[1])return e[1]}return l}function isBoilerplateField(e){return/^(?:status|control status|evidence tool|tool|source|来源)$/iu.test(e.trim())}function isBoundaryNoiseLabel(e){return/^\d{1,2}\s+(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\b/iu.test(e)||/^(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s+\d{1,4}(?:\s+\d{1,2})?$/iu.test(e)||/^\d{4}\s+\d{1,2}$/u.test(e)}export function normalizeFieldLabel(e){return e.toLowerCase().replace(/[^a-z0-9\p{L}\p{N}]+/giu," ").trim()}function titleCaseLabel(e){if(/\p{Script=Han}/u.test(e))return e;const t=e.split(/[^A-Za-z0-9]+/u).filter(Boolean);return normalizeFieldLabel(e).split(" ").filter(Boolean).map((e,l)=>{const i=t[l]??e;return/^[A-Z0-9]{2,}$/u.test(i)?i:e.charAt(0).toUpperCase()+e.slice(1)}).join(" ")}function formatEvidence(e){const t=e.replace(/\s+/gu," ").trim();return t.length>1200?`${t.slice(0,1197)}...`:t}function escapeTableCell(e){return e.replace(/\|/gu,"\\|").replace(/\r?\n/gu," ")}function fieldKey(e){return`${e.source}\0${normalizeFieldLabel(e.label)}\0${e.value.toLowerCase()}`}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{normalizeFieldLabel as e}from"./fields.js";export function observedResultLines(e,t){const i=takeFields(e,isIdentityField,3),n=takeFields(e,isDataField,4),a=takeFields(e,isRecentField,2),
|
|
1
|
+
import{normalizeFieldLabel as e}from"./fields.js";export function observedResultLines(e,t){const i=takeFields(e,isIdentityField,3),n=takeFields(e,isDataField,4),a=takeFields(e,isRecentField,2),s=[i.length>0?observationLine("identity",i,t):void 0,n.length>0?observationLine("data",n,t):void 0,a.length>0?observationLine("recent",a,t):void 0].filter(e=>Boolean(e));return s.length>0?s:["zh"===t?"- 只观察到原始证据,无法形成更具体的归纳。":"- Only raw evidence was observed; no more specific synthesis is available."]}function takeFields(t,i,n){const a=[],s=new Set;for(const o of t){const t=e(o.label);if(!s.has(t)&&i(o)&&(s.add(t),a.push(o),a.length>=n))break}return a}function observationLine(e,t,i){const n=t.map(e=>`${e.label} ${e.value}`).join("zh"===i?";":"; ");return"zh"===i?`- ${"identity"===e?"已确认标识":"data"===e?"关键数据":"近期证据"}:${n}。`:`- ${"identity"===e?"Confirmed identifiers":"data"===e?"Observed data":"Recent evidence"}: ${n}.`}function isIdentityField(t){const i=e(t.label);return"context"===t.kind||/(?:name|title|identifier|entity|subject|名称|标题|标识)/iu.test(i)}function isDataField(t){const i=e(t.label);return"data"===t.kind||/(?:value|amount|total|ratio|rate|range|estimate|count|metric|数量|范围|比率)/iu.test(i)}function isRecentField(t){const i=e(t.label);return"timeBound"===t.kind||/(?:date|time|published|updated|summary|title|日期|时间|发布|更新|标题|摘要)/iu.test(i)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{controlBlockers as e,controlGaps as t,successfulEvidenceItems as n}from"./event-evidence.js";import{classifyFact as s,evidenceFields as r,fieldTableLines as
|
|
1
|
+
import{controlBlockers as e,controlGaps as t,successfulEvidenceItems as n}from"./event-evidence.js";import{classifyFact as s,evidenceFields as r,fieldTableLines as i,hasExtractableFields as o,selectSectionFields as c}from"./synthesis/fields.js";import{detectSynthesisLanguage as u}from"./synthesis/language.js";import{observedResultLines as a}from"./synthesis/observed.js";export function synthesizeEvidenceOnlyReport(s,r,i){if(!i.enabled||!i.synthesis.enabled||"evidence_only"!==i.synthesis.mode)return;if("pass"===r.verdict||!function hasRecoverableSynthesisIssue(e){return e.issues.some(e=>"control_blocker"!==e.code)}(r))return;const o=n(s.events).slice(-i.synthesis.maxEvidenceItems),c=e(s.events),a=t(s.events);if(0===o.length&&0===c.length&&0===a.length)return;const l=function latestDelegatedReport(e){const t=e.filter(e=>"task"===e.source&&function looksLikeFinalReport(e){const t=e.trim();return!(t.length<80)&&(/^#{1,3}\s+\S/mu.test(t)||/\n#{1,3}\s+\S/mu.test(t)||/\n-{3,}\n/u.test(t))}(e.output)&&!function looksLikeCommentaryInsteadOfEvidence(e){const t=e.trim();return!(t.length>8e3)&&[/(?:这篇文章|this article)[\s\S]{0,1200}(?:我认为|我认同|打动我|值得深入探讨|特别认同|what I find|I think|I agree)/iu,/(?:你还有什么|还想深入探讨|would you like|do you want).{0,120}[??]\s*$/iu].some(e=>e.test(t))}(e.output)).at(-1)?.output.trim();return t||void 0}(o);return l||("zh"===u(s)?function buildChineseReport(e,t,n,s){const r=evidenceFacts(e,s);return["# 调查结果","","## 结论",...resultSummaryLines(e,r,t,n,"zh",s),"","## 证据摘要",...summaryLines(e,t,n,"zh"),"",...structuredFactSections(r,"zh",s),"","## 证据缺口与阻塞",...gapLines(t,n,"zh"),"","## 使用的证据来源",...sourceLines(sourceSummary(e),"zh")].join("\n")}(o,c,a,i):function buildEnglishReport(e,t,n,s){const r=evidenceFacts(e,s);return["# Result","","## Conclusion",...resultSummaryLines(e,r,t,n,"en",s),"","## Evidence summary",...summaryLines(e,t,n,"en"),"",...structuredFactSections(r,"en",s),"","## Evidence gaps and blockers",...gapLines(t,n,"en"),"","## Sources used",...sourceLines(sourceSummary(e),"en")].join("\n")}(o,c,a,i))}function resultSummaryLines(e,t,n,s,i,o){if(0===e.length)return["zh"===i?"- 没有成功证据可用于形成调查结论。":"- No successful evidence was available for a result."];const c=[...new Set(e.map(e=>humanSourceLabel(e.source)))],u=r(t,o.synthesis.fieldKinds),l=a(u,i),d=0===n.length&&0===s.length?"zh"===i?"未观察到运行时阻塞;未覆盖的细节不应视为已确认。":"No runtime blocker was observed; uncovered details should not be treated as confirmed.":"zh"===i?`仍有 ${n.length+s.length} 个证据缺口或阻塞,结论应按部分调查读取。`:`${n.length+s.length} evidence gap(s) or blocker(s) remain, so read this as a partial result.`;return["zh"===i?`- 已基于 ${c.join("、")} 形成可交付结果。`:`- Result formed from ${c.join(", ")}.`,`- ${d}`,...l]}function sourceSummary(e){const t=new Map;for(const n of e){const e=t.get(n.source)??{source:n.source,count:0,facts:[]};e.count+=1,e.facts.push(...factLines(n.output)),t.set(n.source,e)}return[...t.values()].map(t=>({...t,facts:t.facts.length>0?t.facts.slice(0,8):[fallbackEvidenceText(evidenceTextForSource(e,t.source))]}))}function evidenceFacts(e,t){return e.flatMap(e=>{const n=factLines(e.output);return(n.length>0?n:[fallbackEvidenceText(e.output)]).map(n=>({source:e.source,text:n,kind:s(n,t.synthesis.fieldKinds)}))}).slice(0,40)}function summaryLines(e,t,n,s){if(0===e.length)return["zh"===s?"- 未观察到成功的工具或委托任务证据。":"- No successful tool or delegated-task evidence was observed."];const r=new Set(e.map(e=>e.source)).size,i=0===t.length&&0===n.length?"zh"===s?"未观察到未解决的运行时证据缺口或阻塞。":"No unresolved runtime evidence gaps or blockers were observed.":"zh"===s?`仍有 ${t.length+n.length} 个运行时证据缺口或阻塞。`:`${t.length+n.length} runtime evidence gaps or blockers remain.`;return["zh"===s?`- 已使用 ${e.length} 条完成证据,来自 ${r} 个来源。`:`- Used ${e.length} completed evidence item(s) from ${r} source(s).`,`- ${i}`]}function structuredFactSections(e,t,n){if(0===e.length)return["zh"===t?"- 证据缺口:没有可用于生成事实性结论的成功证据。":"- Evidence gap: no successful tool or delegated-task evidence was available."];const s=r(e,n.synthesis.fieldKinds);return[{kind:"context",title:"zh"===t?"## 已确认背景":"## Confirmed context"},{kind:"data",title:"zh"===t?"## 观察到的数据":"## Observed data points"},{kind:"timeBound",title:"zh"===t?"## 近期或时间相关证据":"## Recent or time-bound evidence"},{kind:"limit",title:"zh"===t?"## 证据限制":"## Evidence limits"},{kind:"other",title:"zh"===t?"## 其他观察":"## Additional observations"}].flatMap(n=>{const r=c(s,n.kind,12),u=e.filter(e=>e.kind===n.kind&&!o(e.text)).filter(e=>!function isLowValueTextFact(e){const t=e.trim();return/^https?:\/\/\S+$/iu.test(t)||/^source\s*:/iu.test(t)||/^来源\s*[::]/u.test(t)}(e.text)).slice(0,5);return 0===r.length&&0===u.length?[]:[n.title,...i(r,t),...u.map(e=>function factLine(e,t){const n=humanSourceLabel(e.source);return"zh"===t?`- ${e.text}(来源:${n})`:`- ${e.text} (source: ${n})`}(e,t)),""]}).filter((e,t,n)=>""!==e||t<n.length-1)}function sourceLines(e,t){return 0===e.length?["zh"===t?"- 未使用成功证据来源。":"- No successful evidence source was used."]:e.map(e=>`- ${humanSourceLabel(e.source)}${e.count>1?` (${e.count})`:""}: ${e.source}`)}function gapLines(e,t,n){return 0===e.length&&0===t.length?["zh"===n?"- 未观察到未解决的运行时证据缺口或阻塞。":"- No unresolved runtime evidence gaps or blockers were observed."]:"zh"===n?[...e.map(e=>`- 阻塞:${e}`),...t.map(e=>`- 证据缺口:${e}`)]:[...e.map(e=>`- Blocked: ${e}`),...t.map(e=>`- Evidence gap: ${e}`)]}function formatEvidence(e){const t=e.replace(/\s+/gu," ").trim();return t.length>1200?`${t.slice(0,1197)}...`:t}function factLines(e){const t=function factLinesFromJson(e){try{const t=JSON.parse(e);return function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}(t)?Object.entries(t).filter(([e])=>!/^(?:status|controlStatus)$/iu.test(e)).slice(0,8).map(([e,t])=>`${e}: ${formatEvidence(function stringifyJsonValue(e){return"string"==typeof e?e:JSON.stringify(e)}(t))}`):[]}catch{return[]}}(e);return t.length>0?t:function splitPlainTextFacts(e){const t=function stripControlPreamble(e){return e.replace(/^(?:Status:\s*(?:completed|success|ok|recorded)\b\.?\s*)+/iu,"").replace(/^(?:Evidence tool:\s*[A-Za-z0-9_.-]+\b\.?\s*)+/iu,"").trim()}(e);return t.split(/\r?\n|;\s*/u).map(e=>e.trim()).map(stripControlFragments).map(normalizePlainFactLine).filter(e=>e&&!function isControlFact(e){return/^Status:\s*(?:completed|success|ok|recorded)$/iu.test(e)||/^Evidence tool:\s*[A-Za-z0-9_.-]+$/iu.test(e)}(e))}(e).slice(0,8).map(formatEvidence)}function stripControlFragments(e){return e.replace(/\bStatus:\s*(?:completed|success|ok|recorded)\b\.?\s*/giu,"").replace(/\bEvidence tool:\s*[A-Za-z0-9_.-]+\b\.?\s*/giu,"").trim()}function normalizePlainFactLine(e){if(/^https?:\/\//iu.test(e))return"";const t=e.match(/^\d+[.)]\s+(.+)$/u);return t?.[1]?`List Item: ${t[1]}`:e}function evidenceTextForSource(e,t){return e.find(e=>e.source===t)?.output??""}function fallbackEvidenceText(e){return formatEvidence(e)}function humanSourceLabel(e){const t=e.replace(/([a-z])([A-Z])/gu,"$1 $2").split(/[_:.\-\s]+/u).map(e=>e.trim()).filter(Boolean);return 0===t.length?e:t.map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}
|
|
@@ -34,12 +34,14 @@ export type QualityPolicy = {
|
|
|
34
34
|
enabled: boolean;
|
|
35
35
|
mode: "evidence_only";
|
|
36
36
|
maxEvidenceItems: number;
|
|
37
|
+
fieldKinds?: Partial<Record<FactKind, string[]>>;
|
|
37
38
|
};
|
|
38
39
|
recovery: {
|
|
39
40
|
enabled: boolean;
|
|
40
41
|
maxLoops: number;
|
|
41
42
|
};
|
|
42
43
|
};
|
|
44
|
+
export type FactKind = "context" | "data" | "timeBound" | "limit" | "other";
|
|
43
45
|
export type QualityReviewInput = {
|
|
44
46
|
workspace: CompiledWorkspace;
|
|
45
47
|
agent: WorkspaceAgent;
|
|
@@ -5,6 +5,7 @@ import type { CompiledWorkspace, WorkspaceAgent } from "../workspace/types.js";
|
|
|
5
5
|
export type RuntimeCapabilityState = {
|
|
6
6
|
memory?: RuntimeMemoryContext;
|
|
7
7
|
pluginMemories?: RuntimeMemoryContext[];
|
|
8
|
+
modules: Record<string, Record<string, unknown>>;
|
|
8
9
|
};
|
|
9
10
|
export type RuntimeCapabilityContext = {
|
|
10
11
|
workspace: CompiledWorkspace;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function createRuntimeCapabilityRegistry(e){const t=e.filter(e=>Boolean(e)),o={};return{modules:t,state:o,emitSideEffects(e,o){for(const r of t)try{r.onEvent?.(e,o)}catch{continue}},async beforeAdapterRun(e){for(const r of t){const t=await(r.beforeAdapterRun?.({...e,state:o}));mergeCapabilityState(o,t)}return o},async beforeAdapterResultContract(e){for(const r of t)await(r.beforeAdapterResultContract?.({...e,state:o}))},async afterAdapterResponse(e){for(const r of t)await(r.afterAdapterResponse?.({...e,state:o}))},async stop(){await Promise.all(t.map(e=>e.stop?.()))}}}export function normalizeAdapterResult(e){return"string"==typeof e?{text:e}:e}function mergeCapabilityState(e,t){t&&(void 0!==t.memory&&(e.memory=t.memory),t.pluginMemories&&(e.pluginMemories=[...e.pluginMemories??[],...t.pluginMemories]))}
|
|
1
|
+
export function createRuntimeCapabilityRegistry(e){const t=e.filter(e=>Boolean(e)),o={modules:{}};return{modules:t,state:o,emitSideEffects(e,o){for(const r of t)try{r.onEvent?.(e,o)}catch{continue}},async beforeAdapterRun(e){for(const r of t){const t=await(r.beforeAdapterRun?.({...e,state:o}));mergeCapabilityState(o,t)}return o},async beforeAdapterResultContract(e){for(const r of t)await(r.beforeAdapterResultContract?.({...e,state:o}))},async afterAdapterResponse(e){for(const r of t)await(r.afterAdapterResponse?.({...e,state:o}))},async stop(){await Promise.all(t.map(e=>e.stop?.()))}}}export function normalizeAdapterResult(e){return"string"==typeof e?{text:e}:e}function mergeCapabilityState(e,t){t&&(void 0!==t.memory&&(e.memory=t.memory),t.pluginMemories&&(e.pluginMemories=[...e.pluginMemories??[],...t.pluginMemories]),t.modules&&(e.modules=function mergeModuleState(e,t){const o={...e};for(const[e,r]of Object.entries(t))o[e]={...o[e]??{},...r};return o}(e.modules,t.modules)))}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CompiledWorkspace, RuntimeRequest, WorkspaceAgent } from "../../types.js";
|
|
2
|
+
export type RuntimePolicyProjectionInput = {
|
|
3
|
+
workspace: CompiledWorkspace;
|
|
4
|
+
agent?: WorkspaceAgent;
|
|
5
|
+
request: RuntimeRequest;
|
|
6
|
+
};
|
|
7
|
+
export type RuntimePolicyProjection = {
|
|
8
|
+
systemPromptSections: string[];
|
|
9
|
+
};
|
|
10
|
+
export declare function projectRuntimePolicies(input: RuntimePolicyProjectionInput): RuntimePolicyProjection;
|
|
11
|
+
export declare function buildRuntimeSystemPrompt(input: RuntimePolicyProjectionInput, basePrompt?: string): string | undefined;
|
|
@@ -0,0 +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)}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { RuntimeEvent, RuntimeRequest, WorkspaceAgent } from "../../types.js";
|
|
2
|
+
export type ToolRepeatState = {
|
|
3
|
+
successfulCalls: Map<string, string>;
|
|
4
|
+
duplicateCallCounts: Map<string, number>;
|
|
5
|
+
latestSuccessfulOutputByTool: Map<string, string>;
|
|
6
|
+
successfulToolCounts: Map<string, number>;
|
|
7
|
+
toolCallCounts: Map<string, number>;
|
|
8
|
+
maxDuplicateCallsPerTool?: number;
|
|
9
|
+
maxCallsPerTool?: number;
|
|
10
|
+
maxSuccessfulCallsPerTool?: number;
|
|
11
|
+
maxCallsByTool: Map<string, number>;
|
|
12
|
+
maxSuccessfulCallsByTool: Map<string, number>;
|
|
13
|
+
returnPreviousOutputOnRepeatLimit: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type ToolRepeatDecision = {
|
|
16
|
+
eventOutput: string;
|
|
17
|
+
modelOutput: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function createToolRepeatState(config: unknown): ToolRepeatState | undefined;
|
|
20
|
+
export declare function beforeToolInvoke(toolId: string, args: unknown, state: ToolRepeatState): ToolRepeatDecision | undefined;
|
|
21
|
+
export declare function afterToolInvoke(input: {
|
|
22
|
+
toolId: string;
|
|
23
|
+
args: unknown;
|
|
24
|
+
output: string;
|
|
25
|
+
successful: boolean;
|
|
26
|
+
state: ToolRepeatState;
|
|
27
|
+
}): {
|
|
28
|
+
eventOutput?: string;
|
|
29
|
+
modelOutput?: string;
|
|
30
|
+
};
|
|
31
|
+
export declare function isToolRepeatLimitReached(toolId: string, state: ToolRepeatState | undefined): boolean;
|
|
32
|
+
export declare function missingRequiredPlanContent(input: {
|
|
33
|
+
agent: WorkspaceAgent;
|
|
34
|
+
events: RuntimeEvent[];
|
|
35
|
+
toolId: string;
|
|
36
|
+
}): string;
|
|
37
|
+
export declare function missingToolDependencyContent(input: {
|
|
38
|
+
agent: WorkspaceAgent;
|
|
39
|
+
events: RuntimeEvent[];
|
|
40
|
+
toolId: string;
|
|
41
|
+
}): string;
|
|
42
|
+
export declare function toolInvocationEvents(input: {
|
|
43
|
+
request: RuntimeRequest;
|
|
44
|
+
getEvents?: () => RuntimeEvent[];
|
|
45
|
+
}): RuntimeEvent[];
|