stable-harness 0.0.41 → 0.0.44

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 (23) hide show
  1. package/README.md +1 -1
  2. package/docs/tooling/0.1.0-bettercall-tool-quality.zh.md +3 -3
  3. package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin/task-inventory.js +1 -1
  4. package/node_modules/@stable-harness/adapter-deepagents/dist/src/internal/builtin-call-repair.js +1 -1
  5. package/node_modules/@stable-harness/adapter-deepagents/package.json +1 -1
  6. package/node_modules/@stable-harness/core/dist/runtime/selection-repair.d.ts +14 -4
  7. package/node_modules/@stable-harness/core/dist/runtime/selection-repair.js +1 -1
  8. package/node_modules/@stable-harness/core/package.json +0 -1
  9. package/node_modules/@stable-harness/tool-gateway/dist/src/argument-guard.d.ts +1 -1
  10. package/node_modules/@stable-harness/tool-gateway/dist/src/argument-guard.js +1 -1
  11. package/node_modules/@stable-harness/tool-gateway/dist/src/schema-validation.js +1 -1
  12. package/node_modules/@stable-harness/tool-gateway/package.json +1 -1
  13. package/package.json +2 -2
  14. package/packages/adapter-deepagents/dist/src/internal/builtin/task-inventory.js +1 -1
  15. package/packages/adapter-deepagents/dist/src/internal/builtin-call-repair.js +1 -1
  16. package/packages/adapter-deepagents/package.json +1 -1
  17. package/packages/core/dist/runtime/selection-repair.d.ts +14 -4
  18. package/packages/core/dist/runtime/selection-repair.js +1 -1
  19. package/packages/core/package.json +0 -1
  20. package/packages/tool-gateway/dist/src/argument-guard.d.ts +1 -1
  21. package/packages/tool-gateway/dist/src/argument-guard.js +1 -1
  22. package/packages/tool-gateway/dist/src/schema-validation.js +1 -1
  23. package/packages/tool-gateway/package.json +1 -1
package/README.md CHANGED
@@ -199,7 +199,7 @@ semantics.
199
199
 
200
200
  ## Tool Reliability
201
201
 
202
- Stable Harness uses `@botbotgo/better-call` at the tool-gateway boundary. The
202
+ Stable Harness uses `@easynet/better-call` at the tool-gateway boundary. The
203
203
  default CLI path configures repair mode for registered tools, so malformed or
204
204
  near-miss tool calls can be repaired before execution while agent inventory,
205
205
  schema validation, semantic validators, and governance policy still define what
@@ -1,6 +1,6 @@
1
1
  # BetterCall Tool Call Quality
2
2
 
3
- 本文说明 `stable-harness` 如何通过 `@botbotgo/better-call` 提升 tool call 质量。
3
+ 本文说明 `stable-harness` 如何通过 `@easynet/better-call` 提升 tool call 质量。
4
4
 
5
5
  核心原则:
6
6
 
@@ -180,7 +180,7 @@ sequenceDiagram
180
180
 
181
181
  ## Sequence: BetterCall repairModel 模式
182
182
 
183
- `@botbotgo/better-call` package 本身支持:
183
+ `@easynet/better-call` package 本身支持:
184
184
 
185
185
  ```ts
186
186
  const tools = betterTools([searchTool, calculatorTool], { repairModel });
@@ -228,4 +228,4 @@ sequenceDiagram
228
228
  - `npm run check`
229
229
  - `npm test`:74/74 通过
230
230
  - `npm run check:rules`
231
- - BetterCall package 已发布到 npm:`@botbotgo/better-call@0.1.1`
231
+ - BetterCall package 已发布到 npm:`@easynet/better-call@0.1.60`
@@ -1 +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)}
1
+ import{repairCallSelection as e}from"@easynet/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 s=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===s)return{request:a};const i=n(a.toolCall?.args),o=function readTaskSubagentType(e){const t=isRecord(e)?e:{};return readString(t.subagent_type)??readString(t.subagentType)}(i);if(o&&s.includes(o))return{request:a};const d=await e({call:{id:o,args:i},candidates:taskCallCandidates(r,s),mode:"repair"});if(d.ok){emitInventoryRepair(r,"repaired",o,d.candidateId,s);const e={...i,...d.args,subagent_type:d.candidateId};return{request:{...a,toolCall:{...a.toolCall,args:e}}}}emitInventoryRepair(r,"blocked",o,void 0,s,d.reason);const l=o?`: ${o}`:"",c=s.length>0?s.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,s){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:s}}})}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)}
@@ -1 +1 @@
1
- import{repairCallSelection as t}from"@botbotgo/better-call";import{normalizeArgsRecord as e,normalizeExecuteArgs as r,normalizeFilesystemArgs as o,normalizeWriteTodosArgs as i,shallowEqualRecord as s}from"./builtin-args.js";const a=new Set(["ls","read_file","write_file","edit_file","glob","grep"]);export async function repairBuiltinToolRequest(e){const r=normalizeBuiltinArgs(e.toolId,e.request.toolCall?.args,e.workspaceRoot),o=function builtinCandidate(t){const e=n[t];return e?{id:t,description:`DeepAgents builtin tool ${t}`,schema:e}:void 0}(e.toolId);if(!o)return updateRequestArgs(e.request,e.request.toolCall?.args,r);const i=await t({call:{id:e.toolId,args:r},candidates:[o],mode:"repair"}),s=i.ok?normalizeBuiltinArgs(e.toolId,i.args,e.workspaceRoot):r;return updateRequestArgs(e.request,e.request.toolCall?.args,s)}function normalizeBuiltinArgs(t,s,n){return"write_todos"===t?i(s):"read_todos"===t||"task"===t?e(s):"execute"===t?r(s,n):a.has(t)?o(t,s,n):e(s)}function updateRequestArgs(t,e,r){return function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}(e)&&s(e,r)?t:{...t,toolCall:{...t.toolCall,args:r}}}const n={write_todos:objectSchema({todos:{type:"array",items:{type:"object",additionalProperties:!0}}}),read_todos:objectSchema({}),task:objectSchema({subagent_type:{type:"string"},subagentType:{type:"string"},description:{type:"string"},task:{type:"string"}}),execute:objectSchema({command:{type:"string"},cwd:{type:"string"},timeoutMs:{type:"number"}}),ls:objectSchema({path:{type:"string"}}),read_file:objectSchema({path:{type:"string"},file_path:{type:"string"}}),write_file:objectSchema({path:{type:"string"},file_path:{type:"string"},content:{type:"string"}}),edit_file:objectSchema({path:{type:"string"},file_path:{type:"string"},old_string:{type:"string"},new_string:{type:"string"}}),glob:objectSchema({path:{type:"string"},pattern:{type:"string"}}),grep:objectSchema({path:{type:"string"},pattern:{type:"string"}})};function objectSchema(t){return{type:"object",properties:t,additionalProperties:!0}}
1
+ import{repairCallSelection as t}from"@easynet/better-call";import{normalizeArgsRecord as e,normalizeExecuteArgs as r,normalizeFilesystemArgs as o,normalizeWriteTodosArgs as i,shallowEqualRecord as s}from"./builtin-args.js";const a=new Set(["ls","read_file","write_file","edit_file","glob","grep"]);export async function repairBuiltinToolRequest(e){const r=normalizeBuiltinArgs(e.toolId,e.request.toolCall?.args,e.workspaceRoot),o=function builtinCandidate(t){const e=n[t];return e?{id:t,description:`DeepAgents builtin tool ${t}`,schema:e}:void 0}(e.toolId);if(!o)return updateRequestArgs(e.request,e.request.toolCall?.args,r);const i=await t({call:{id:e.toolId,args:r},candidates:[o],mode:"repair"}),s=i.ok?normalizeBuiltinArgs(e.toolId,i.args,e.workspaceRoot):r;return updateRequestArgs(e.request,e.request.toolCall?.args,s)}function normalizeBuiltinArgs(t,s,n){return"write_todos"===t?i(s):"read_todos"===t||"task"===t?e(s):"execute"===t?r(s,n):a.has(t)?o(t,s,n):e(s)}function updateRequestArgs(t,e,r){return function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}(e)&&s(e,r)?t:{...t,toolCall:{...t.toolCall,args:r}}}const n={write_todos:objectSchema({todos:{type:"array",items:{type:"object",additionalProperties:!0}}}),read_todos:objectSchema({}),task:objectSchema({subagent_type:{type:"string"},subagentType:{type:"string"},description:{type:"string"},task:{type:"string"}}),execute:objectSchema({command:{type:"string"},cwd:{type:"string"},timeoutMs:{type:"number"}}),ls:objectSchema({path:{type:"string"}}),read_file:objectSchema({path:{type:"string"},file_path:{type:"string"}}),write_file:objectSchema({path:{type:"string"},file_path:{type:"string"},content:{type:"string"}}),edit_file:objectSchema({path:{type:"string"},file_path:{type:"string"},old_string:{type:"string"},new_string:{type:"string"}}),glob:objectSchema({path:{type:"string"},pattern:{type:"string"}}),grep:objectSchema({path:{type:"string"},pattern:{type:"string"}})};function objectSchema(t){return{type:"object",properties:t,additionalProperties:!0}}
@@ -10,7 +10,7 @@
10
10
  "main": "dist/src/index.js",
11
11
  "types": "dist/src/index.d.ts",
12
12
  "peerDependencies": {
13
- "@botbotgo/better-call": "^0.1.58",
13
+ "@easynet/better-call": "^0.1.60",
14
14
  "@langchain/core": "^1.1.43",
15
15
  "@langchain/ollama": "^1.2.7",
16
16
  "@langchain/openai": "^1.4.5",
@@ -1,13 +1,23 @@
1
- import type { CallCandidate, CallSelectionDiagnostics } from "@botbotgo/better-call";
2
1
  import type { RuntimeEvent, RuntimeInventoryRepairDiagnostic, RuntimeInventoryRepairLayer } from "./events.js";
2
+ export type RuntimeSelectionCandidate = {
3
+ id: string;
4
+ description?: string;
5
+ metadata?: Record<string, unknown>;
6
+ };
7
+ export type RuntimeSelectionDiagnostics = {
8
+ originalId: string;
9
+ repairedId?: string;
10
+ matchSource?: string;
11
+ confidence?: number;
12
+ };
3
13
  export type RuntimeSelectionRepairResult = {
4
14
  ok: true;
5
15
  id: string;
6
- diagnostics?: CallSelectionDiagnostics;
16
+ diagnostics?: RuntimeSelectionDiagnostics;
7
17
  } | {
8
18
  ok: false;
9
19
  reason: string;
10
- diagnostics?: CallSelectionDiagnostics;
20
+ diagnostics?: RuntimeSelectionDiagnostics;
11
21
  };
12
22
  export type RuntimeSelectionRepairTrace = {
13
23
  layer: RuntimeInventoryRepairLayer;
@@ -19,6 +29,6 @@ export type RuntimeSelectionRepairTrace = {
19
29
  };
20
30
  export declare function repairRuntimeSelection(input: {
21
31
  id: string;
22
- candidates: CallCandidate[];
32
+ candidates: RuntimeSelectionCandidate[];
23
33
  trace?: RuntimeSelectionRepairTrace;
24
34
  }): Promise<RuntimeSelectionRepairResult>;
@@ -1 +1 @@
1
- import{repairCallSelection as e}from"@botbotgo/better-call";export async function repairRuntimeSelection(i){const a=await e({rawIntent:i.id,candidates:i.candidates,mode:"repair"});return a.ok?(emitSelectionRepair(i,"repaired",a.candidateId,a.diagnostics),{ok:!0,id:a.candidateId,diagnostics:a.diagnostics}):(emitSelectionRepair(i,"blocked",void 0,a.diagnostics,a.reason),{ok:!1,reason:a.reason,diagnostics:a.diagnostics})}function emitSelectionRepair(e,i,a,t,n){const d=e.trace;d&&d.emit({type:"runtime.inventory.repair",requestId:d.requestId,sessionId:d.sessionId,agentId:d.agentId,status:i,diagnostic:{layer:d.layer,owner:d.owner,originalId:t?.originalId??e.id,repairedId:t?.repairedId??a,candidateIds:e.candidates.map(e=>e.id),reason:n,matchSource:t?.matchSource,confidence:t?.confidence}})}
1
+ export async function repairRuntimeSelection(e){const i=function repairSelection(e,i){const n=normalizeSelectionId(e),t=i.filter(e=>normalizeSelectionId(e.id)===n);if(1===t.length){const i=t[0];return{ok:!0,id:i.id,diagnostics:{originalId:e,repairedId:i.id,matchSource:i.id===e?"exact":"normalized_id",confidence:i.id===e?1:.95}}}return{ok:!1,reason:t.length>1?"ambiguous":"no_candidate",diagnostics:{originalId:e}}}(e.id,e.candidates);return i.ok?(emitSelectionRepair(e,"repaired",i.id,i.diagnostics),i):(emitSelectionRepair(e,"blocked",void 0,i.diagnostics,i.reason),i)}function emitSelectionRepair(e,i,n,t,o){const r=e.trace;r&&r.emit({type:"runtime.inventory.repair",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agentId,status:i,diagnostic:{layer:r.layer,owner:r.owner,originalId:t?.originalId??e.id,repairedId:t?.repairedId??n,candidateIds:e.candidates.map(e=>e.id),reason:o,matchSource:t?.matchSource,confidence:t?.confidence}})}function normalizeSelectionId(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/gu,"")}
@@ -11,7 +11,6 @@
11
11
  ".": "./dist/index.js"
12
12
  },
13
13
  "peerDependencies": {
14
- "@botbotgo/better-call": "^0.1.58",
15
14
  "@stable-harness/governance": "0.0.1",
16
15
  "@stable-harness/memory": "0.0.1"
17
16
  }
@@ -1,4 +1,4 @@
1
- import type { BetterToolLike, RepairFunction, RepairModelLike, RepairPolicy } from "@botbotgo/better-call";
1
+ import type { BetterToolLike, RepairFunction, RepairModelLike, RepairPolicy } from "@easynet/better-call";
2
2
  import type { ToolArgumentGuard, ToolArgumentIssue, ToolGatewayContext, ToolGatewayTool } from "./types.js";
3
3
  type ToolGatewayRuntimeTool = ToolGatewayTool & {
4
4
  validationTool?: BetterToolLike;
@@ -1 +1 @@
1
- import{BetterToolValidationError as o,betterTools as t,defaultRepair as e,reliableToolCalls as a}from"@botbotgo/better-call";import{isRecord as r,validateWithZodSchema as i}from"./schema-validation.js";export class ToolArgumentValidationError extends Error{toolId;issues;constructor(o,t){super(`Tool argument validation failed for ${o}: ${t.map(o=>`${o.path} ${o.message}`).join("; ")}`),this.toolId=o,this.issues=t,this.name="ToolArgumentValidationError"}}export function createDefaultArgumentGuard(t={}){return{async validate(e){const a=e.tool.validateArgs?await e.tool.validateArgs({args:e.args,context:e.context}):{action:"allow",args:e.args};if("reject"===a.action)return a;const r=await async function validateWithBetterCall(t,e,a){const r=i(t.schema,e);if(void 0===t.schema)return r??{action:"allow",args:e};const l=await async function invokeBetterCallValidation(t,e,a){try{return{action:"allow",args:await createBetterCallValidationTool(t,a).invoke(e)}}catch(t){if(t instanceof o)return{action:"reject",reason:"BetterCall validation failed",issues:t.issues.map(toToolArgumentIssue)};throw t}}(t,"allow"===r?.action?r.args:e,a);return r?"allow"===r.action?l:"reject"===l.action?r:i(t.schema,l.args)||l:l}(e.tool,a.args,t.betterCall);return"reject"===r.action?r:"repair"===a.action?{...a,args:r.args}:r}}}export function assertToolArguments(o,t,e,a){return Promise.resolve(a.validate({tool:o,args:t,context:e})).then(t=>{if("reject"===t.action)throw new ToolArgumentValidationError(o.id,t.issues);return t.args})}export function prepareBetterCallTools(o,e){const a=t(o.map(toBetterCallTool),toBetterToolsOptions(e));return o.map((o,t)=>({...o,validationTool:a[t]}))}export async function repairBetterCallToolSelection(o){const t=function resolveRepair(o){return o?.repair??(o?.repairModel?e(o.repairModel):void 0)}(o.options);if(!t||0===o.tools.length)return;const i=await a({userInput:JSON.stringify({tool:o.toolId,args:o.args}),tools:o.tools.map(toToolDefinition),calls:[{tool:o.toolId,args:(l=o.args,r(l)?l:{input:l})}],repair:t,repairPolicy:o.options?.repairPolicy??{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0,allowModelRepair:!0},mode:o.options?.mode??"repair"});var l;const n=i.ok?i.calls.find(t=>o.tools.some(o=>o.id===t.tool)):void 0;return n?{toolId:n.tool,args:n.args}:void 0}function createBetterCallValidationTool(o,e){return o.validationTool??t([toBetterCallTool(o)],toBetterToolsOptions(e))[0]}function toBetterCallTool(o){return{name:o.id,description:o.description,schema:o.schema,invoke:o=>o}}function toToolDefinition(o){return{name:o.id,description:o.description,schema:o.schema}}function toToolArgumentIssue(o){return{path:o.path.replace(/^\$\.calls\[\d+\]\.args/u,"$"),message:o.message,expected:void 0===o.expected?void 0:String(o.expected),actual:o.actual}}function toBetterToolsOptions(o){return{mode:o?.mode??"repair",repair:o?.repair,repairModel:o?.repairModel,repairPolicy:o?.repairPolicy??{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0,allowModelRepair:!0}}}
1
+ import{BetterToolValidationError as o,betterTools as t,defaultRepair as e,reliableToolCalls as a}from"@easynet/better-call";import{isRecord as r,validateWithZodSchema as i}from"./schema-validation.js";export class ToolArgumentValidationError extends Error{toolId;issues;constructor(o,t){super(`Tool argument validation failed for ${o}: ${t.map(o=>`${o.path} ${o.message}`).join("; ")}`),this.toolId=o,this.issues=t,this.name="ToolArgumentValidationError"}}export function createDefaultArgumentGuard(t={}){return{async validate(e){const a=e.tool.validateArgs?await e.tool.validateArgs({args:e.args,context:e.context}):{action:"allow",args:e.args};if("reject"===a.action)return a;const r=await async function validateWithBetterCall(t,e,a){const r=i(t.schema,e);if(void 0===t.schema)return r??{action:"allow",args:e};const l=await async function invokeBetterCallValidation(t,e,a){try{return{action:"allow",args:await createBetterCallValidationTool(t,a).invoke(e)}}catch(t){if(t instanceof o)return{action:"reject",reason:"BetterCall validation failed",issues:t.issues.map(toToolArgumentIssue)};throw t}}(t,"allow"===r?.action?r.args:e,a);return r?"allow"===r.action?l:"reject"===l.action?r:i(t.schema,l.args)||l:l}(e.tool,a.args,t.betterCall);return"reject"===r.action?r:"repair"===a.action?{...a,args:r.args}:r}}}export function assertToolArguments(o,t,e,a){return Promise.resolve(a.validate({tool:o,args:t,context:e})).then(t=>{if("reject"===t.action)throw new ToolArgumentValidationError(o.id,t.issues);return t.args})}export function prepareBetterCallTools(o,e){const a=t(o.map(toBetterCallTool),toBetterToolsOptions(e));return o.map((o,t)=>({...o,validationTool:a[t]}))}export async function repairBetterCallToolSelection(o){const t=function resolveRepair(o){return o?.repair??(o?.repairModel?e(o.repairModel):void 0)}(o.options);if(!t||0===o.tools.length)return;const i=await a({userInput:JSON.stringify({tool:o.toolId,args:o.args}),tools:o.tools.map(toToolDefinition),calls:[{tool:o.toolId,args:(l=o.args,r(l)?l:{input:l})}],repair:t,repairPolicy:o.options?.repairPolicy??{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0,allowModelRepair:!0},mode:o.options?.mode??"repair"});var l;const n=i.ok?i.calls.find(t=>o.tools.some(o=>o.id===t.tool)):void 0;return n?{toolId:n.tool,args:n.args}:void 0}function createBetterCallValidationTool(o,e){return o.validationTool??t([toBetterCallTool(o)],toBetterToolsOptions(e))[0]}function toBetterCallTool(o){return{name:o.id,description:o.description,schema:o.schema,invoke:o=>o}}function toToolDefinition(o){return{name:o.id,description:o.description,schema:o.schema}}function toToolArgumentIssue(o){return{path:o.path.replace(/^\$\.calls\[\d+\]\.args/u,"$"),message:o.message,expected:void 0===o.expected?void 0:String(o.expected),actual:o.actual}}function toBetterToolsOptions(o){return{mode:o?.mode??"repair",repair:o?.repair,repairModel:o?.repairModel,repairPolicy:o?.repairPolicy??{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0,allowModelRepair:!0}}}
@@ -1 +1 @@
1
- import{normalizeArgsBySchema as e}from"@botbotgo/better-call";export function validateWithZodSchema(t,o){return isZodLike(t)?toZodGuardResult(t.safeParse(o??{})):function isZodShape(e){return isRecord(e)&&Object.values(e).length>0&&Object.values(e).every(isZodLike)}(t)?function validateWithZodShape(t,o){const r=function normalizeZodShapeArgs(t,o){const r=isRecord(o)?o:{};return e(t,r,{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0}).args}(t,o),a={},s=[];for(const[e,o]of Object.entries(t)){const t=o.safeParse(r[e]);t.success?void 0!==t.data&&(a[e]=t.data):s.push(...t.error.issues.map(t=>({...t,path:[e,...t.path]})))}return s.length>0?toZodGuardResult({success:!1,error:{issues:s}}):{action:"allow",args:a}}(t,o):void 0}export function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function toZodGuardResult(e){return e.success?{action:"allow",args:e.data}:{action:"reject",reason:"Zod schema validation failed",issues:e.error.issues.map(e=>{return{path:(t=e.path,t.length>0?`$.${t.map(String).join(".")}`:"$"),message:e.message,expected:"schema"};var t})}}function isZodLike(e){return isRecord(e)&&"function"==typeof e.safeParse}
1
+ import{normalizeArgsBySchema as e}from"@easynet/better-call";export function validateWithZodSchema(a,r){return isZodLike(a)?toZodGuardResult(a.safeParse(r??{})):function isZodShape(e){return isRecord(e)&&Object.values(e).length>0&&Object.values(e).every(isZodLike)}(a)?function validateWithZodShape(a,r){const t=function normalizeZodShapeArgs(a,r){const t=isRecord(r)?r:{};return e(a,t,{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0}).args}(a,r),s={},o=[];for(const[e,r]of Object.entries(a)){const a=r.safeParse(t[e]);a.success?void 0!==a.data&&(s[e]=a.data):o.push(...a.error.issues.map(a=>({...a,path:[e,...a.path]})))}return o.length>0?toZodGuardResult({success:!1,error:{issues:o}}):{action:"allow",args:s}}(a,r):void 0}export function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function toZodGuardResult(e){return e.success?{action:"allow",args:e.data}:{action:"reject",reason:"Zod schema validation failed",issues:e.error.issues.map(e=>{return{path:(a=e.path,a.length>0?`$.${a.map(String).join(".")}`:"$"),message:e.message,expected:"schema"};var a})}}function isZodLike(e){return isRecord(e)&&"function"==typeof e.safeParse}
@@ -10,6 +10,6 @@
10
10
  "main": "dist/src/index.js",
11
11
  "types": "dist/src/index.d.ts",
12
12
  "peerDependencies": {
13
- "@botbotgo/better-call": "^0.1.58"
13
+ "@easynet/better-call": "^0.1.60"
14
14
  }
15
15
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stable-harness",
3
- "version": "0.0.41",
3
+ "version": "0.0.44",
4
4
  "type": "module",
5
5
  "description": "Stable application runtime and operator control plane for agent workspaces.",
6
6
  "license": "Apache-2.0",
@@ -78,7 +78,7 @@
78
78
  "packages/*"
79
79
  ],
80
80
  "dependencies": {
81
- "@botbotgo/better-call": "^0.1.58",
81
+ "@easynet/better-call": "^0.1.60",
82
82
  "@langchain/core": "^1.1.43",
83
83
  "@langchain/langgraph": "^1.3.0",
84
84
  "@langchain/langgraph-api": "^1.2.1",
@@ -1 +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)}
1
+ import{repairCallSelection as e}from"@easynet/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 s=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===s)return{request:a};const i=n(a.toolCall?.args),o=function readTaskSubagentType(e){const t=isRecord(e)?e:{};return readString(t.subagent_type)??readString(t.subagentType)}(i);if(o&&s.includes(o))return{request:a};const d=await e({call:{id:o,args:i},candidates:taskCallCandidates(r,s),mode:"repair"});if(d.ok){emitInventoryRepair(r,"repaired",o,d.candidateId,s);const e={...i,...d.args,subagent_type:d.candidateId};return{request:{...a,toolCall:{...a.toolCall,args:e}}}}emitInventoryRepair(r,"blocked",o,void 0,s,d.reason);const l=o?`: ${o}`:"",c=s.length>0?s.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,s){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:s}}})}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)}
@@ -1 +1 @@
1
- import{repairCallSelection as t}from"@botbotgo/better-call";import{normalizeArgsRecord as e,normalizeExecuteArgs as r,normalizeFilesystemArgs as o,normalizeWriteTodosArgs as i,shallowEqualRecord as s}from"./builtin-args.js";const a=new Set(["ls","read_file","write_file","edit_file","glob","grep"]);export async function repairBuiltinToolRequest(e){const r=normalizeBuiltinArgs(e.toolId,e.request.toolCall?.args,e.workspaceRoot),o=function builtinCandidate(t){const e=n[t];return e?{id:t,description:`DeepAgents builtin tool ${t}`,schema:e}:void 0}(e.toolId);if(!o)return updateRequestArgs(e.request,e.request.toolCall?.args,r);const i=await t({call:{id:e.toolId,args:r},candidates:[o],mode:"repair"}),s=i.ok?normalizeBuiltinArgs(e.toolId,i.args,e.workspaceRoot):r;return updateRequestArgs(e.request,e.request.toolCall?.args,s)}function normalizeBuiltinArgs(t,s,n){return"write_todos"===t?i(s):"read_todos"===t||"task"===t?e(s):"execute"===t?r(s,n):a.has(t)?o(t,s,n):e(s)}function updateRequestArgs(t,e,r){return function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}(e)&&s(e,r)?t:{...t,toolCall:{...t.toolCall,args:r}}}const n={write_todos:objectSchema({todos:{type:"array",items:{type:"object",additionalProperties:!0}}}),read_todos:objectSchema({}),task:objectSchema({subagent_type:{type:"string"},subagentType:{type:"string"},description:{type:"string"},task:{type:"string"}}),execute:objectSchema({command:{type:"string"},cwd:{type:"string"},timeoutMs:{type:"number"}}),ls:objectSchema({path:{type:"string"}}),read_file:objectSchema({path:{type:"string"},file_path:{type:"string"}}),write_file:objectSchema({path:{type:"string"},file_path:{type:"string"},content:{type:"string"}}),edit_file:objectSchema({path:{type:"string"},file_path:{type:"string"},old_string:{type:"string"},new_string:{type:"string"}}),glob:objectSchema({path:{type:"string"},pattern:{type:"string"}}),grep:objectSchema({path:{type:"string"},pattern:{type:"string"}})};function objectSchema(t){return{type:"object",properties:t,additionalProperties:!0}}
1
+ import{repairCallSelection as t}from"@easynet/better-call";import{normalizeArgsRecord as e,normalizeExecuteArgs as r,normalizeFilesystemArgs as o,normalizeWriteTodosArgs as i,shallowEqualRecord as s}from"./builtin-args.js";const a=new Set(["ls","read_file","write_file","edit_file","glob","grep"]);export async function repairBuiltinToolRequest(e){const r=normalizeBuiltinArgs(e.toolId,e.request.toolCall?.args,e.workspaceRoot),o=function builtinCandidate(t){const e=n[t];return e?{id:t,description:`DeepAgents builtin tool ${t}`,schema:e}:void 0}(e.toolId);if(!o)return updateRequestArgs(e.request,e.request.toolCall?.args,r);const i=await t({call:{id:e.toolId,args:r},candidates:[o],mode:"repair"}),s=i.ok?normalizeBuiltinArgs(e.toolId,i.args,e.workspaceRoot):r;return updateRequestArgs(e.request,e.request.toolCall?.args,s)}function normalizeBuiltinArgs(t,s,n){return"write_todos"===t?i(s):"read_todos"===t||"task"===t?e(s):"execute"===t?r(s,n):a.has(t)?o(t,s,n):e(s)}function updateRequestArgs(t,e,r){return function isRecord(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)}(e)&&s(e,r)?t:{...t,toolCall:{...t.toolCall,args:r}}}const n={write_todos:objectSchema({todos:{type:"array",items:{type:"object",additionalProperties:!0}}}),read_todos:objectSchema({}),task:objectSchema({subagent_type:{type:"string"},subagentType:{type:"string"},description:{type:"string"},task:{type:"string"}}),execute:objectSchema({command:{type:"string"},cwd:{type:"string"},timeoutMs:{type:"number"}}),ls:objectSchema({path:{type:"string"}}),read_file:objectSchema({path:{type:"string"},file_path:{type:"string"}}),write_file:objectSchema({path:{type:"string"},file_path:{type:"string"},content:{type:"string"}}),edit_file:objectSchema({path:{type:"string"},file_path:{type:"string"},old_string:{type:"string"},new_string:{type:"string"}}),glob:objectSchema({path:{type:"string"},pattern:{type:"string"}}),grep:objectSchema({path:{type:"string"},pattern:{type:"string"}})};function objectSchema(t){return{type:"object",properties:t,additionalProperties:!0}}
@@ -10,7 +10,7 @@
10
10
  "main": "dist/src/index.js",
11
11
  "types": "dist/src/index.d.ts",
12
12
  "peerDependencies": {
13
- "@botbotgo/better-call": "^0.1.58",
13
+ "@easynet/better-call": "^0.1.60",
14
14
  "@langchain/core": "^1.1.43",
15
15
  "@langchain/ollama": "^1.2.7",
16
16
  "@langchain/openai": "^1.4.5",
@@ -1,13 +1,23 @@
1
- import type { CallCandidate, CallSelectionDiagnostics } from "@botbotgo/better-call";
2
1
  import type { RuntimeEvent, RuntimeInventoryRepairDiagnostic, RuntimeInventoryRepairLayer } from "./events.js";
2
+ export type RuntimeSelectionCandidate = {
3
+ id: string;
4
+ description?: string;
5
+ metadata?: Record<string, unknown>;
6
+ };
7
+ export type RuntimeSelectionDiagnostics = {
8
+ originalId: string;
9
+ repairedId?: string;
10
+ matchSource?: string;
11
+ confidence?: number;
12
+ };
3
13
  export type RuntimeSelectionRepairResult = {
4
14
  ok: true;
5
15
  id: string;
6
- diagnostics?: CallSelectionDiagnostics;
16
+ diagnostics?: RuntimeSelectionDiagnostics;
7
17
  } | {
8
18
  ok: false;
9
19
  reason: string;
10
- diagnostics?: CallSelectionDiagnostics;
20
+ diagnostics?: RuntimeSelectionDiagnostics;
11
21
  };
12
22
  export type RuntimeSelectionRepairTrace = {
13
23
  layer: RuntimeInventoryRepairLayer;
@@ -19,6 +29,6 @@ export type RuntimeSelectionRepairTrace = {
19
29
  };
20
30
  export declare function repairRuntimeSelection(input: {
21
31
  id: string;
22
- candidates: CallCandidate[];
32
+ candidates: RuntimeSelectionCandidate[];
23
33
  trace?: RuntimeSelectionRepairTrace;
24
34
  }): Promise<RuntimeSelectionRepairResult>;
@@ -1 +1 @@
1
- import{repairCallSelection as e}from"@botbotgo/better-call";export async function repairRuntimeSelection(i){const a=await e({rawIntent:i.id,candidates:i.candidates,mode:"repair"});return a.ok?(emitSelectionRepair(i,"repaired",a.candidateId,a.diagnostics),{ok:!0,id:a.candidateId,diagnostics:a.diagnostics}):(emitSelectionRepair(i,"blocked",void 0,a.diagnostics,a.reason),{ok:!1,reason:a.reason,diagnostics:a.diagnostics})}function emitSelectionRepair(e,i,a,t,n){const d=e.trace;d&&d.emit({type:"runtime.inventory.repair",requestId:d.requestId,sessionId:d.sessionId,agentId:d.agentId,status:i,diagnostic:{layer:d.layer,owner:d.owner,originalId:t?.originalId??e.id,repairedId:t?.repairedId??a,candidateIds:e.candidates.map(e=>e.id),reason:n,matchSource:t?.matchSource,confidence:t?.confidence}})}
1
+ export async function repairRuntimeSelection(e){const i=function repairSelection(e,i){const n=normalizeSelectionId(e),t=i.filter(e=>normalizeSelectionId(e.id)===n);if(1===t.length){const i=t[0];return{ok:!0,id:i.id,diagnostics:{originalId:e,repairedId:i.id,matchSource:i.id===e?"exact":"normalized_id",confidence:i.id===e?1:.95}}}return{ok:!1,reason:t.length>1?"ambiguous":"no_candidate",diagnostics:{originalId:e}}}(e.id,e.candidates);return i.ok?(emitSelectionRepair(e,"repaired",i.id,i.diagnostics),i):(emitSelectionRepair(e,"blocked",void 0,i.diagnostics,i.reason),i)}function emitSelectionRepair(e,i,n,t,o){const r=e.trace;r&&r.emit({type:"runtime.inventory.repair",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agentId,status:i,diagnostic:{layer:r.layer,owner:r.owner,originalId:t?.originalId??e.id,repairedId:t?.repairedId??n,candidateIds:e.candidates.map(e=>e.id),reason:o,matchSource:t?.matchSource,confidence:t?.confidence}})}function normalizeSelectionId(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/gu,"")}
@@ -11,7 +11,6 @@
11
11
  ".": "./dist/index.js"
12
12
  },
13
13
  "peerDependencies": {
14
- "@botbotgo/better-call": "^0.1.58",
15
14
  "@stable-harness/governance": "0.0.1",
16
15
  "@stable-harness/memory": "0.0.1"
17
16
  }
@@ -1,4 +1,4 @@
1
- import type { BetterToolLike, RepairFunction, RepairModelLike, RepairPolicy } from "@botbotgo/better-call";
1
+ import type { BetterToolLike, RepairFunction, RepairModelLike, RepairPolicy } from "@easynet/better-call";
2
2
  import type { ToolArgumentGuard, ToolArgumentIssue, ToolGatewayContext, ToolGatewayTool } from "./types.js";
3
3
  type ToolGatewayRuntimeTool = ToolGatewayTool & {
4
4
  validationTool?: BetterToolLike;
@@ -1 +1 @@
1
- import{BetterToolValidationError as o,betterTools as t,defaultRepair as e,reliableToolCalls as a}from"@botbotgo/better-call";import{isRecord as r,validateWithZodSchema as i}from"./schema-validation.js";export class ToolArgumentValidationError extends Error{toolId;issues;constructor(o,t){super(`Tool argument validation failed for ${o}: ${t.map(o=>`${o.path} ${o.message}`).join("; ")}`),this.toolId=o,this.issues=t,this.name="ToolArgumentValidationError"}}export function createDefaultArgumentGuard(t={}){return{async validate(e){const a=e.tool.validateArgs?await e.tool.validateArgs({args:e.args,context:e.context}):{action:"allow",args:e.args};if("reject"===a.action)return a;const r=await async function validateWithBetterCall(t,e,a){const r=i(t.schema,e);if(void 0===t.schema)return r??{action:"allow",args:e};const l=await async function invokeBetterCallValidation(t,e,a){try{return{action:"allow",args:await createBetterCallValidationTool(t,a).invoke(e)}}catch(t){if(t instanceof o)return{action:"reject",reason:"BetterCall validation failed",issues:t.issues.map(toToolArgumentIssue)};throw t}}(t,"allow"===r?.action?r.args:e,a);return r?"allow"===r.action?l:"reject"===l.action?r:i(t.schema,l.args)||l:l}(e.tool,a.args,t.betterCall);return"reject"===r.action?r:"repair"===a.action?{...a,args:r.args}:r}}}export function assertToolArguments(o,t,e,a){return Promise.resolve(a.validate({tool:o,args:t,context:e})).then(t=>{if("reject"===t.action)throw new ToolArgumentValidationError(o.id,t.issues);return t.args})}export function prepareBetterCallTools(o,e){const a=t(o.map(toBetterCallTool),toBetterToolsOptions(e));return o.map((o,t)=>({...o,validationTool:a[t]}))}export async function repairBetterCallToolSelection(o){const t=function resolveRepair(o){return o?.repair??(o?.repairModel?e(o.repairModel):void 0)}(o.options);if(!t||0===o.tools.length)return;const i=await a({userInput:JSON.stringify({tool:o.toolId,args:o.args}),tools:o.tools.map(toToolDefinition),calls:[{tool:o.toolId,args:(l=o.args,r(l)?l:{input:l})}],repair:t,repairPolicy:o.options?.repairPolicy??{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0,allowModelRepair:!0},mode:o.options?.mode??"repair"});var l;const n=i.ok?i.calls.find(t=>o.tools.some(o=>o.id===t.tool)):void 0;return n?{toolId:n.tool,args:n.args}:void 0}function createBetterCallValidationTool(o,e){return o.validationTool??t([toBetterCallTool(o)],toBetterToolsOptions(e))[0]}function toBetterCallTool(o){return{name:o.id,description:o.description,schema:o.schema,invoke:o=>o}}function toToolDefinition(o){return{name:o.id,description:o.description,schema:o.schema}}function toToolArgumentIssue(o){return{path:o.path.replace(/^\$\.calls\[\d+\]\.args/u,"$"),message:o.message,expected:void 0===o.expected?void 0:String(o.expected),actual:o.actual}}function toBetterToolsOptions(o){return{mode:o?.mode??"repair",repair:o?.repair,repairModel:o?.repairModel,repairPolicy:o?.repairPolicy??{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0,allowModelRepair:!0}}}
1
+ import{BetterToolValidationError as o,betterTools as t,defaultRepair as e,reliableToolCalls as a}from"@easynet/better-call";import{isRecord as r,validateWithZodSchema as i}from"./schema-validation.js";export class ToolArgumentValidationError extends Error{toolId;issues;constructor(o,t){super(`Tool argument validation failed for ${o}: ${t.map(o=>`${o.path} ${o.message}`).join("; ")}`),this.toolId=o,this.issues=t,this.name="ToolArgumentValidationError"}}export function createDefaultArgumentGuard(t={}){return{async validate(e){const a=e.tool.validateArgs?await e.tool.validateArgs({args:e.args,context:e.context}):{action:"allow",args:e.args};if("reject"===a.action)return a;const r=await async function validateWithBetterCall(t,e,a){const r=i(t.schema,e);if(void 0===t.schema)return r??{action:"allow",args:e};const l=await async function invokeBetterCallValidation(t,e,a){try{return{action:"allow",args:await createBetterCallValidationTool(t,a).invoke(e)}}catch(t){if(t instanceof o)return{action:"reject",reason:"BetterCall validation failed",issues:t.issues.map(toToolArgumentIssue)};throw t}}(t,"allow"===r?.action?r.args:e,a);return r?"allow"===r.action?l:"reject"===l.action?r:i(t.schema,l.args)||l:l}(e.tool,a.args,t.betterCall);return"reject"===r.action?r:"repair"===a.action?{...a,args:r.args}:r}}}export function assertToolArguments(o,t,e,a){return Promise.resolve(a.validate({tool:o,args:t,context:e})).then(t=>{if("reject"===t.action)throw new ToolArgumentValidationError(o.id,t.issues);return t.args})}export function prepareBetterCallTools(o,e){const a=t(o.map(toBetterCallTool),toBetterToolsOptions(e));return o.map((o,t)=>({...o,validationTool:a[t]}))}export async function repairBetterCallToolSelection(o){const t=function resolveRepair(o){return o?.repair??(o?.repairModel?e(o.repairModel):void 0)}(o.options);if(!t||0===o.tools.length)return;const i=await a({userInput:JSON.stringify({tool:o.toolId,args:o.args}),tools:o.tools.map(toToolDefinition),calls:[{tool:o.toolId,args:(l=o.args,r(l)?l:{input:l})}],repair:t,repairPolicy:o.options?.repairPolicy??{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0,allowModelRepair:!0},mode:o.options?.mode??"repair"});var l;const n=i.ok?i.calls.find(t=>o.tools.some(o=>o.id===t.tool)):void 0;return n?{toolId:n.tool,args:n.args}:void 0}function createBetterCallValidationTool(o,e){return o.validationTool??t([toBetterCallTool(o)],toBetterToolsOptions(e))[0]}function toBetterCallTool(o){return{name:o.id,description:o.description,schema:o.schema,invoke:o=>o}}function toToolDefinition(o){return{name:o.id,description:o.description,schema:o.schema}}function toToolArgumentIssue(o){return{path:o.path.replace(/^\$\.calls\[\d+\]\.args/u,"$"),message:o.message,expected:void 0===o.expected?void 0:String(o.expected),actual:o.actual}}function toBetterToolsOptions(o){return{mode:o?.mode??"repair",repair:o?.repair,repairModel:o?.repairModel,repairPolicy:o?.repairPolicy??{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0,allowModelRepair:!0}}}
@@ -1 +1 @@
1
- import{normalizeArgsBySchema as e}from"@botbotgo/better-call";export function validateWithZodSchema(t,o){return isZodLike(t)?toZodGuardResult(t.safeParse(o??{})):function isZodShape(e){return isRecord(e)&&Object.values(e).length>0&&Object.values(e).every(isZodLike)}(t)?function validateWithZodShape(t,o){const r=function normalizeZodShapeArgs(t,o){const r=isRecord(o)?o:{};return e(t,r,{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0}).args}(t,o),a={},s=[];for(const[e,o]of Object.entries(t)){const t=o.safeParse(r[e]);t.success?void 0!==t.data&&(a[e]=t.data):s.push(...t.error.issues.map(t=>({...t,path:[e,...t.path]})))}return s.length>0?toZodGuardResult({success:!1,error:{issues:s}}):{action:"allow",args:a}}(t,o):void 0}export function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function toZodGuardResult(e){return e.success?{action:"allow",args:e.data}:{action:"reject",reason:"Zod schema validation failed",issues:e.error.issues.map(e=>{return{path:(t=e.path,t.length>0?`$.${t.map(String).join(".")}`:"$"),message:e.message,expected:"schema"};var t})}}function isZodLike(e){return isRecord(e)&&"function"==typeof e.safeParse}
1
+ import{normalizeArgsBySchema as e}from"@easynet/better-call";export function validateWithZodSchema(a,r){return isZodLike(a)?toZodGuardResult(a.safeParse(r??{})):function isZodShape(e){return isRecord(e)&&Object.values(e).length>0&&Object.values(e).every(isZodLike)}(a)?function validateWithZodShape(a,r){const t=function normalizeZodShapeArgs(a,r){const t=isRecord(r)?r:{};return e(a,t,{allowCoercion:!0,allowClamp:!0,allowArrayStringSplit:!0}).args}(a,r),s={},o=[];for(const[e,r]of Object.entries(a)){const a=r.safeParse(t[e]);a.success?void 0!==a.data&&(s[e]=a.data):o.push(...a.error.issues.map(a=>({...a,path:[e,...a.path]})))}return o.length>0?toZodGuardResult({success:!1,error:{issues:o}}):{action:"allow",args:s}}(a,r):void 0}export function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function toZodGuardResult(e){return e.success?{action:"allow",args:e.data}:{action:"reject",reason:"Zod schema validation failed",issues:e.error.issues.map(e=>{return{path:(a=e.path,a.length>0?`$.${a.map(String).join(".")}`:"$"),message:e.message,expected:"schema"};var a})}}function isZodLike(e){return isRecord(e)&&"function"==typeof e.safeParse}
@@ -10,6 +10,6 @@
10
10
  "main": "dist/src/index.js",
11
11
  "types": "dist/src/index.d.ts",
12
12
  "peerDependencies": {
13
- "@botbotgo/better-call": "^0.1.58"
13
+ "@easynet/better-call": "^0.1.60"
14
14
  }
15
15
  }