@mikode13/harness 10.0.0 → 11.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -16
- package/dist/agent/domain/agent.d.ts +24 -6
- package/dist/agent/domain/agent.js.map +1 -1
- package/dist/engines/domain/model/backgroundAgents.d.ts +60 -0
- package/dist/engines/domain/model/backgroundAgents.js +165 -0
- package/dist/engines/domain/model/backgroundAgents.js.map +1 -0
- package/dist/engines/domain/model/llmAgent.d.ts +4 -11
- package/dist/engines/domain/model/llmAgent.js +103 -83
- package/dist/engines/domain/model/llmAgent.js.map +1 -1
- package/dist/factory/infrastructure/agentLLMFactory.d.ts +1 -1
- package/dist/factory/infrastructure/agentLLMFactory.js +2 -2
- package/dist/factory/infrastructure/agentLLMFactory.js.map +1 -1
- package/dist/tools/domain/preparedCall.d.ts +43 -7
- package/dist/tools/domain/preparedCall.js +3 -0
- package/dist/tools/domain/preparedCall.js.map +1 -1
- package/dist/tools/infrastructure/agentAsTool.d.ts +11 -9
- package/dist/tools/infrastructure/agentAsTool.js +39 -40
- package/dist/tools/infrastructure/agentAsTool.js.map +1 -1
- package/dist/tools/infrastructure/defineTool.d.ts +14 -1
- package/dist/tools/infrastructure/defineTool.js +24 -0
- package/dist/tools/infrastructure/defineTool.js.map +1 -1
- package/dist/tools/infrastructure/exploreTool.d.ts +2 -2
- package/dist/tools/infrastructure/exploreTool.js +35 -42
- package/dist/tools/infrastructure/exploreTool.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentLLMFactory.js","sourceRoot":"","sources":["../../../src/factory/infrastructure/agentLLMFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAE9D,OAAO,EACN,eAAe,EACf,eAAe,EACf,yBAAyB,GACzB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACN,eAAe,EACf,YAAY,EACZ,sBAAsB,GACtB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACN,oBAAoB,EACpB,mCAAmC,EACnC,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,mCAAmC,GACnC,MAAM,mDAAmD,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,mEAAmE,CAAC;AAE9G,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAErD,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAE3D,OAAO,EAGN,WAAW,EAEX,gBAAgB,EAChB,iBAAiB,GACjB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACN,cAAc,EAEd,YAAY,EAEZ,SAAS,EACT,aAAa,EACb,gBAAgB,GAEhB,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,OAAO,EACN,qBAAqB,EACrB,sBAAsB,GACtB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAa,MAAM,mBAAmB,CAAC;AACrF,OAAO,EACN,cAAc,GAKd,MAAM,YAAY,CAAC;AAEpB,oDAAoD;AACpD,MAAM,CAAC,MAAM,SAAS,GAAG;IACxB,SAAS,EAAE,eAAe;IAC1B,MAAM,EAAE,YAAY;CACsD,CAAC;AAE5E,+DAA+D;AAC/D,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAClC,SAAS,EAAE,yBAAyB;IACpC,MAAM,EAAE,sBAAsB;CACiD,CAAC;AAEjF,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAC3B,QAAkB,EAClB,KAAa;IAEb,OAAO,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,sBAAsB,CACrC,QAAkB,EAClB,KAAa;IAEb,OAAO,OAAO,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;AACtD,CAAC;AAiED,8FAA8F;AAC9F,MAAM,gBAAgB,GAAqC;IAC1D,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;CACZ,CAAC;AAEF,oCAAoC;AACpC,MAAM,qBAAqB,GAAiD;IAC3E,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,SAAS;CACnB,CAAC;AAEF;;;;;;GAMG;AACH,SAAS,OAAO,CACf,IAAY,EACZ,KAAc,EACd,QAAqC,EACrC,EAAE,IAAI,EAAE,OAAO,EAAqC;IAEpD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC3F,uFAAuF;IACvF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,uBAAuB,CAChC,GAAG,IAAI,qCAAqC,IAAI,sBAAsB,OAAO,EAAE,CAC/E,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,QAAQ,CAAC,CAAC,CAAC;IACvE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,uBAAuB,CAChC,GAAG,IAAI,mCAAmC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,0CAA0C,CACtG,CAAC;IACH,CAAC;IACD,8EAA8E;IAC9E,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,CAAC,MAAM,CACpE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAChC,CAAC;IACF,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;AACtD,CAAC;AA6CD,MAAM,qBAAqB,GAAG;IAC7B,SAAS,EAAE,QAAQ;IACnB,MAAM,EAAE,cAAc;CAC+B,CAAC;AAEvD,SAAS,eAAe,CAAC,QAAe;IACvC,OAAO,IAAI,uBAAuB,CACjC,IAAI,MAAM,CAAC,QAAQ,CAAC,gDAAgD,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC/F,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CACpB,QAAuB,EACvB,EACC,KAAK,EACL,eAAe,EACf,SAAS,EACT,YAAY,EACZ,MAAM,GAON;IAED,QAAQ,QAAQ,EAAE,CAAC;QAClB,KAAK,WAAW;YACf,OAAO,IAAI,eAAe,CAAC;gBAC1B,KAAK,EAAE,KAAK,IAAI,qBAAqB,CAAC,SAAS;gBAC/C,eAAe;gBACf,SAAS;gBACT,YAAY;gBACZ,MAAM;aACN,CAAC,CAAC;QACJ,KAAK,QAAQ;YACZ,OAAO,IAAI,eAAe,CAAC;gBAC1B,KAAK,EAAE,KAAK,IAAI,qBAAqB,CAAC,MAAM;gBAC5C,eAAe;gBACf,SAAS;gBACT,YAAY;gBACZ,MAAM;aACN,CAAC,CAAC;QACJ;YACC,gCAAgC;YAChC,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;AACF,CAAC;AAED,sEAAsE;AACtE,SAAS,aAAa,CAAC,QAAuB,EAAE,MAAe;IAC9D,OAAO,QAAQ,KAAK,WAAW;QAC9B,CAAC,CAAC,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;QAC5F,CAAC,CAAC,IAAI,eAAe,CAAC;YACpB,KAAK,EAAE,cAAc;YACrB,eAAe,EAAE,MAAM;YACvB,YAAY,EAAE,EAAE;YAChB,MAAM;SACN,CAAC,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,SAAS,SAAS,CAAC,SAA2B,EAAE,MAAe;IAC9D,sFAAsF;IACtF,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,uBAAuB,CAAC,qCAAqC,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,KAAyC,CAAC;IAC9C,MAAM,IAAI,GAAG,GAAG,EAAE;QACjB,KAAK,KAAK,gBAAgB,CAAC,SAAS,CAAC;aACnC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;aAC1D,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACzB,+EAA+E;YAC/E,KAAK,GAAG,SAAS,CAAC;YAClB,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QACJ,OAAO,KAAK,CAAC;IACd,CAAC,CAAC;IACF,OAAO;QACN,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE;QAC/C,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,aAAa,EAAE;QACzD,OAAO,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;KACrD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,KAAsB;IAChD,MAAM,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACtF,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,CACvC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CAC5E,CAAC;IACF,OAAO;QACN,gBAAgB;QAChB,GAAG,SAAS;QACZ,uCAAuC,KAAK,CAAC,IAAI,2HAA2H;KAC5K,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB,EAAE,QAAgB;IAC3D,OAAO,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,OAAO,QAAQ,EAAE,CAAC;AAC1E,CAAC;AAED,0EAA0E;AAC1E,SAAS,aAAa,CACrB,QAAuB,EACvB,EACC,KAAK,EACL,eAAe,EACf,YAAY,EACZ,KAAK,EACL,OAAO,EACP,UAAU,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,MAAM,EACN,YAAY,GAaZ;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,EAAE;QACxC,KAAK;QACL,eAAe;QACf,SAAS;QACT,YAAY;QACZ,MAAM;KACN,CAAC,CAAC;IACH,0FAA0F;IAC1F,OAAO,IAAI,aAAa,CAAC;QACxB,KAAK,EAAE,IAAI,QAAQ,CAAC;YACnB,SAAS;YACT,KAAK;YACL,WAAW;YACX,MAAM;YACN,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrC,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;YAC/C,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzC,CAAC;QACF,MAAM;QACN,YAAY,EAAE,KAAK;KACnB,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAC7B,QAAuB,EACvB,EACC,KAAK,EACL,eAAe,EACf,YAAY,EACZ,KAAK,GAAG,EAAE,EACV,SAAS,EACT,eAAe,GAAG,IAAI,EACtB,QAAQ,EACR,SAAS,EACT,WAAW,EACX,MAAM,GAAG,IAAI,MAAM,EAAE,EACrB,YAAY,GACW;IAExB,OAAO,aAAa,CAAC,QAAQ,EAAE;QAC9B,KAAK;QACL,eAAe;QACf,YAAY,EAAE,SAAS;YACtB,CAAC,CAAC,YAAY,CAAC,YAAY,EAAE,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAChE,CAAC,CAAC,YAAY;QACf,4EAA4E;QAC5E,KAAK,EAAE,KAAoB;QAC3B,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,SAAS,IAAI,eAAe,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxF,QAAQ;QACR,SAAS;QACT,WAAW;QACX,MAAM;QACN,YAAY;KACZ,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACpC,QAAuB,EACvB,SAA2B,EAC3B,EACC,MAAM,GAAG,IAAI,MAAM,EAAE,EACrB,QAAQ,EACR,SAAS,MAC4D,EAAE;IAExE,gCAAgC;IAChC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;QAAE,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,QAAQ,KAAK,SAAS;QAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,SAAS,KAAK,SAAS;QAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtF,OAAO,CAAC,MAAM,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAA0B,CAAC;AACnF,CAAC;AAED,2EAA2E;AAC3E,KAAK,UAAU,aAAa,CAC3B,QAAuB,EACvB,SAA0B,EAC1B,QAA8B;IAE9B,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChD,sEAAsE;IACtE,IAAI,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/E,OAAO,CAAC,GAAG,KAAK,EAAE,MAAM,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,gFAAgF;AAChF,SAAS,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,EAAmB;IACvD,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC,MAAM,CAChD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,CAC7D,CAAC;IACF,OAAO,CAAC,GAAG,OAAO,EAAE,qBAAqB,CAAC,MAAM,CAAC,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,YAAY,CAC1B,SAA0B,EAC1B,IAAiB,EACjB,QAA8B,EAC9B,QAAqB;IAErB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IACpC,MAAM,KAAK,GAAG;QACb,GAAG,aAAa,CAAC,SAAS,CAAC;QAC3B,qBAAqB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QACxC,iBAAiB,CAAC,QAAQ,CAAC;KAC3B,CAAC;IACF,MAAM,GAAG,GAAG,QAAQ,IAAI,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,OAAO,CAAC,GAAG,KAAK,EAAE,MAAM,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,QAAQ,GACb,uKAAuK,CAAC;AAEzK,8EAA8E;AAC9E,MAAM,aAAa,GAClB,gNAAgN,CAAC;AAElN,+FAA+F;AAC/F,yEAAyE;AACzE,MAAM,SAAS,GACd,ySAAyS,CAAC;AAE3S,6DAA6D;AAC7D,MAAM,aAAa,GAAG;IACrB,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE;IACxD,MAAM,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE;CACsC,CAAC;AAEpG,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB,MAAM,oBAAoB,GAAG,wlBAAwlB,aAAa,EAAE,CAAC;AAEroB,6FAA6F;AAC7F,6FAA6F;AAC7F,gFAAgF;AAChF,MAAM,kBAAkB,GAAgC;IACvD,OAAO,EAAE,+NAA+N,SAAS,IAAI,aAAa,EAAE;IACpQ,QAAQ,EAAE,+KAA+K,QAAQ,EAAE;IACnM,QAAQ,EAAE,mGAAmG,SAAS,IAAI,aAAa,EAAE;CACzI,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAC3C,QAAQ,EACR,WAAW,EACX,aAAa,GAAG,EAAE,EAClB,SAAS,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EAChE,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,SAAS,EACT,eAAe,GAAG,IAAI,EACtB,MAAM,GAAG,IAAI,MAAM,EAAE,EACrB,YAAY,MACqB,EAAE;IACnC,MAAM,KAAK,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE;QAC7D,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,qBAAqB;KAC9B,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,SAAS,EAAE,qBAAqB,EAAE;QACzE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,wBAAwB;KACjC,CAAC,CAAC;IACH,IAAI,SAAS,KAAK,SAAS;QAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtF,MAAM,QAAQ,GAAG,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,eAAe,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/F,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACxF,6FAA6F;IAC7F,kEAAkE;IAClE,MAAM,MAAM,GAAG,CAAC,IAAiB,EAAE,GAAuB,EAAE,YAAoB,EAAE,EAAE,CACnF,GAAG,KAAK,SAAS;QAChB,CAAC,CAAC,YAAY,CAAC,YAAY,EAAE,GAAG,QAAQ,KAAK,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;QACxE,CAAC,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAChC,4CAA4C;IAC5C,MAAM,aAAa,GAAG,CAAC,KAA0B,EAAE,EAAE,CACpD,YAAY,IAAI,CAAC,CAAC,UAAsB,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACtF,gEAAgE;IAChE,IAAI,QAAQ,KAAK,SAAS;QAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACvD,+FAA+F;IAC/F,MAAM,eAAe,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,CAAC,QAAuB,EAAE,EAAE,CAAC,GAAG,EAAE,CAClD,aAAa,CAAC,QAAQ,EAAE;QACvB,GAAG,aAAa,CAAC,QAAQ,CAAC;QAC1B,YAAY,EAAE,YAAY,CAAC,oBAAoB,EAAE,QAAQ,CAAC;QAC1D,KAAK,EAAE,eAAe;QACtB,QAAQ,EAAE,aAAa;QACvB,MAAM;QACN,YAAY,EAAE,aAAa,CAAC,UAAU,CAAC;KACvC,CAAC,CAAC;IACJ,MAAM,MAAM,GAAG,KAAK,EACnB,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAQ,EAC1C,IAAiB,EACjB,YAAoB,EACnB,EAAE,CACH,aAAa,CAAC,QAAQ,EAAE;QACvB,KAAK;QACL,eAAe;QACf,YAAY;QACZ,KAAK,EAAE,MAAM,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrE,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC;QACrB,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC;QAC3B,YAAY,EAAE,aAAa,CAAC,IAAI,CAAC;QACjC,GAAG,MAAM;KACT,CAAC,CAAC;IACJ,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAC3B,MAAM,eAAe,GAAG,MAAM,aAAa,CAC1C,QAAQ,CAAC,QAAQ,EACjB,MAAM,EACN,QAAQ,IAAI,WAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,CAC7C,CAAC;IACF,4FAA4F;IAC5F,yBAAyB;IACzB,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAE9E,OAAO,IAAI,iBAAiB,CAAC;QAC5B,YAAY,EAAE,MAAM,MAAM,CACzB,KAAK,CAAC,OAAO,EACb,SAAS,EACT,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAC7D;QACD,aAAa,EAAE,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE;YAC/C,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,YAAY,EAAE,MAAM,CACnB,UAAU,EACV,aAAa,CAAC,QAAQ,EACtB,YAAY,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,mCAAmC,CACzE;YACD,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,UAAU,CAAC,QAAQ;YAC9B,WAAW;YACX,YAAY,EAAE,aAAa,CAAC,UAAU,CAAC;YACvC,GAAG,MAAM;SACT,CAAC;QACF,aAAa,EAAE,MAAM,MAAM,CAC1B,KAAK,CAAC,QAAQ,EACd,UAAU,EACV,MAAM,CACL,UAAU,EACV,aAAa,CAAC,QAAQ,EACtB,YAAY,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,mCAAmC,CACzE,CACD;QACD,yBAAyB,EAAE,IAAI,yBAAyB,EAAE;QAC1D,MAAM;KACN,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { resolve } from 'node:path';\nimport type { Agent } from '#src/agent/domain/agent';\nimport type { Transcript, TranscriptCallback } from '#src/agent/domain/transcript';\nimport type { HistoryReader } from '#src/engines/domain/model/historyFollower';\nimport { LLMAgent } from '#src/engines/domain/model/llmAgent';\nimport type { LLMClient } from '#src/llm/domain/llm';\nimport {\n\tClaudeLLMClient,\n\tclaudeLLMModels,\n\tclaudeLLMReasoningEfforts,\n} from '#src/llm/infrastructure/claudeLLMClient';\nimport {\n\tOpenAILLMClient,\n\topenAIModels,\n\topenAIReasoningEfforts,\n} from '#src/llm/infrastructure/openAILLMClient';\nimport {\n\texecutorInstructions,\n\texecutorInstructionsWithoutCommands,\n\tOrchestratorAgent,\n\tplannerInstructions,\n\treviewerInstructions,\n\treviewerInstructionsWithoutCommands,\n} from '#src/orchestration/domain/model/orchestratorAgent';\nimport { ReviewerDecisionValidator } from '#src/orchestration/infrastructure/model/reviewerDecisionValidator';\nimport type { RecoveryStore } from '#src/recovery/domain/recoveryStore';\nimport { RetryingAgent } from '#src/retry/domain/model/retryingAgent';\nimport { InvalidAgentConfigError } from '#src/shared/domain/errors';\nimport { isOneOf } from '#src/shared/domain/isOneOf';\nimport type { ILogger } from '#src/shared/domain/logger';\nimport { Logger } from '#src/shared/infrastructure/logger';\nimport type { WorkspaceRoot } from '#src/tools/domain/accessPolicy';\nimport {\n\ttype CommandRole,\n\ttype Commands,\n\tcommandsFor,\n\ttype Formatter,\n\tvalidateCommands,\n\tvalidateFormatter,\n} from '#src/tools/domain/commands';\nimport type { AgentTool } from '#src/tools/domain/preparedCall';\nimport type { Tool } from '#src/tools/domain/tool';\nimport {\n\tcommandToolFor,\n\ttype FileTool,\n\tfileToolsFor,\n\ttype OpenedWorkspace,\n\topenStore,\n\topenWorkspace,\n\tstateDirectoryOf,\n\ttype WorkspaceOptions,\n} from '#src/tools/infrastructure/fileTools';\nimport type { DelegationTool } from '#src/tools/infrastructure/agentAsTool';\nimport { createExploreTool } from '#src/tools/infrastructure/exploreTool';\nimport { createShowChangesTool } from '#src/tools/infrastructure/showChangesTool';\nimport {\n\tcreateTrackedReadFile,\n\tcreateTrackedReadFiles,\n} from '#src/tools/infrastructure/trackedReadFile';\nimport { createWorkspaceTools } from '#src/tools/infrastructure/workspaceTools';\nimport { isAgentProvider, orchestratorRolesFor, type Role } from './agentFactory.ts';\nimport {\n\tagentProviders,\n\ttype AgentModel,\n\ttype AgentProvider,\n\ttype CreateOrchestratorOptions,\n\ttype ReasoningEffort,\n} from './types.ts';\n\n/** The models each provider's model API accepts. */\nexport const llmModels = {\n\tanthropic: claudeLLMModels,\n\topenai: openAIModels,\n} as const satisfies Readonly<Record<AgentProvider, readonly AgentModel[]>>;\n\n/** The reasoning efforts each provider's model API accepts. */\nexport const llmReasoningEfforts = {\n\tanthropic: claudeLLMReasoningEfforts,\n\topenai: openAIReasoningEfforts,\n} as const satisfies Readonly<Record<AgentProvider, readonly ReasoningEffort[]>>;\n\n/** Narrows a model to one accepted by the selected provider's model API. */\nexport function isLLMModelOf<Provider extends AgentProvider>(\n\tprovider: Provider,\n\tvalue: string,\n): value is (typeof llmModels)[Provider][number] {\n\treturn isOneOf(llmModels[provider], value);\n}\n\n/** Narrows a reasoning effort to one accepted by the selected provider's model API. */\nexport function isLLMReasoningEffortOf<Provider extends AgentProvider>(\n\tprovider: Provider,\n\tvalue: string,\n): value is (typeof llmReasoningEfforts)[Provider][number] {\n\treturn isOneOf(llmReasoningEfforts[provider], value);\n}\n\nexport interface CreateLLMAgentOptions {\n\t/**\n\t * Defaults to `'sonnet'` on Anthropic and `'gpt-5.6-luna'` on OpenAI. The provider's client\n\t * rejects a model it does not support.\n\t */\n\tmodel?: AgentModel;\n\t/** Defaults to `'high'`. The provider's client rejects an effort it does not support. */\n\treasoningEffort?: ReasoningEffort;\n\t/** Sent as the model's instructions on every call. */\n\tsystemPrompt: string;\n\t/**\n\t * The tools the model may call: the consumer's own, those of `createFileTools`, and agents\n\t * offered with `agentAsTool`. Defaults to none.\n\t */\n\ttools?: (Tool | FileTool | DelegationTool)[];\n\t/**\n\t * The folders the agent works on, the same as given to `createFileTools`. With it, the agent\n\t * follows the workspace's history: after the user undoes runs, its next run starts from the\n\t * conversation as it was, and is told what was undone. The system prompt is followed by the\n\t * roots and how to name a file in them.\n\t */\n\tworkspace?: WorkspaceOptions;\n\t/**\n\t * With `workspace`, a summary of what was undone, from the provider's cheap model, in place\n\t * of the undone prompts. That is Claude Haiku 5.5 or `gpt-5.6-luna`, at high effort, and the\n\t * call is billed with the run's tokens. Defaults to `true`.\n\t */\n\tsummarizeUndone?: boolean;\n\t/**\n\t * How many calls to the model one run may make before it fails. Defaults to 65, with no upper\n\t * bound. A run that asks for exactly the same tool calls 5 times in a row fails before that.\n\t */\n\tmaxSteps?: number;\n\t/**\n\t * The input tokens at which the provider compacts the conversation on its side: it replaces\n\t * every turn before that call with its own summary, which only its model reads back. The\n\t * conversation keeps every original turn. Without it, the conversation is never compacted.\n\t * At least 50,000 on Anthropic.\n\t */\n\tcompactAt?: number;\n\t/**\n\t * Runs every tool call without asking, `destructive` ones included, for CI where no one can\n\t * answer. Without it, a `destructive` call goes to the run's `approve`, or is denied.\n\t */\n\tautoApprove?: boolean;\n\t/** Defaults to warnings on stderr. */\n\tlogger?: ILogger;\n\t/**\n\t * Receives what the model saw in each run once the run ended, completed, failed or\n\t * cancelled, for debugging. See `Transcript`. Without it, nothing is kept.\n\t */\n\tonTranscript?: TranscriptCallback;\n}\n\n/** A limit per role of `createLLMOrchestrator`; a role left out keeps its default. */\nexport type RoleSteps = Partial<Record<OrchestratorRole, number>>;\n\n/** A number of tokens per role of `createLLMOrchestrator`; a role left out keeps its default. */\nexport type RoleTokens = Partial<Record<OrchestratorRole, number>>;\n\n// The same three roles a command can be given to.\ntype OrchestratorRole = CommandRole;\n\n// The executor reads, edits and checks, so it needs more calls than the roles that only read.\nconst defaultRoleSteps: Record<OrchestratorRole, number> = {\n\tplanner: 65,\n\texecutor: 80,\n\treviewer: 65,\n};\n\n// No role compacts unless asked to.\nconst defaultRoleCompaction: Record<OrchestratorRole, number | undefined> = {\n\tplanner: undefined,\n\texecutor: undefined,\n\treviewer: undefined,\n};\n\n/**\n * Each role's value of the option `name`, from one number for all of them or a number per role.\n * Each number is checked by whatever takes it.\n *\n * @throws {InvalidAgentConfigError} for a value that is neither, and for a role that does not\n * exist, which is a typo that would otherwise leave that role on its default without a word.\n */\nfunction perRole<T extends number | undefined>(\n\tname: string,\n\tvalue: unknown,\n\tdefaults: Record<OrchestratorRole, T>,\n\t{ unit, example }: { unit: string; example: string },\n): Record<OrchestratorRole, T | number> {\n\tif (value === undefined) return defaults;\n\tif (typeof value === 'number') return { planner: value, executor: value, reviewer: value };\n\t// Untyped input, such as the CLI's configuration file, can hold `null` or a list here.\n\tif (typeof value !== 'object' || value === null || Array.isArray(value)) {\n\t\tthrow new InvalidAgentConfigError(\n\t\t\t`${name} must be a number or an object of ${unit} per role, such as ${example}`,\n\t\t);\n\t}\n\tconst unknown = Object.keys(value).filter(role => !(role in defaults));\n\tif (unknown.length > 0) {\n\t\tthrow new InvalidAgentConfigError(\n\t\t\t`${name} names roles that do not exist: ${unknown.join(', ')}; expected planner, executor or reviewer`,\n\t\t);\n\t}\n\t// A role given as `undefined`, which untyped input can do, keeps its default.\n\tconst given = Object.entries(value as Record<string, unknown>).filter(\n\t\t([, each]) => each !== undefined,\n\t);\n\treturn { ...defaults, ...Object.fromEntries(given) };\n}\n\nexport interface CreateLLMOrchestratorOptions extends CreateOrchestratorOptions {\n\t/**\n\t * The folders the agents work on. The executor changes files only in a `write` root, every\n\t * change recorded in the workspace's history. Defaults to the current working directory,\n\t * read only.\n\t */\n\tworkspace?: WorkspaceOptions;\n\t/**\n\t * How many calls to the model one run of each role may make: one number for every role, or a\n\t * number per role. Defaults to 80 for the executor and 65 for the planner and the reviewer,\n\t * with no upper bound. A run that asks for exactly the same tool calls 5 times in a row fails\n\t * before its limit.\n\t */\n\tmaxSteps?: number | RoleSteps;\n\t/**\n\t * The input tokens at which each role's provider compacts its conversation, as\n\t * `CreateLLMAgentOptions.compactAt`: one number for every role, or a number per role. Without\n\t * it, no role compacts.\n\t */\n\tcompactAt?: number | RoleTokens;\n\t/**\n\t * Commands the roles may run, such as the project's tests, through `runCommand`. Each goes to\n\t * the roles its `roles` names, the executor by default. See `createFileTools`. Each needs a\n\t * `write` root to run in.\n\t */\n\tcommands?: Commands;\n\t/**\n\t * A program the executor's edits run on each file they create or change, such as the\n\t * project's formatter. See `createFileTools`. It needs a `write` root to run in.\n\t */\n\tformatter?: Formatter;\n\t/**\n\t * A summary of what the user undid, from the planner's provider's cheap model, for every\n\t * role. See `CreateLLMAgentOptions.summarizeUndone`. Defaults to `true`.\n\t */\n\tsummarizeUndone?: boolean;\n\t/**\n\t * Receives what the model saw in each run of each role and each explorer, once the run\n\t * ended, for debugging. Each transcript names its role. See `Transcript`.\n\t */\n\tonTranscript?: TranscriptCallback;\n}\n\nconst defaultLLMAgentModels = {\n\tanthropic: 'sonnet',\n\topenai: 'gpt-5.6-luna',\n} as const satisfies Record<AgentProvider, AgentModel>;\n\nfunction unknownProvider(provider: never): InvalidAgentConfigError {\n\treturn new InvalidAgentConfigError(\n\t\t`\"${String(provider)}\" is not an agent provider; expected one of: ${agentProviders.join(', ')}`,\n\t);\n}\n\nfunction llmClientFor(\n\tprovider: AgentProvider,\n\t{\n\t\tmodel,\n\t\treasoningEffort,\n\t\tcompactAt,\n\t\tsystemPrompt,\n\t\tlogger,\n\t}: {\n\t\tmodel?: AgentModel;\n\t\treasoningEffort?: ReasoningEffort;\n\t\tcompactAt?: number | undefined;\n\t\tsystemPrompt: string;\n\t\tlogger: ILogger;\n\t},\n): LLMClient {\n\tswitch (provider) {\n\t\tcase 'anthropic':\n\t\t\treturn new ClaudeLLMClient({\n\t\t\t\tmodel: model ?? defaultLLMAgentModels.anthropic,\n\t\t\t\treasoningEffort,\n\t\t\t\tcompactAt,\n\t\t\t\tsystemPrompt,\n\t\t\t\tlogger,\n\t\t\t});\n\t\tcase 'openai':\n\t\t\treturn new OpenAILLMClient({\n\t\t\t\tmodel: model ?? defaultLLMAgentModels.openai,\n\t\t\t\treasoningEffort,\n\t\t\t\tcompactAt,\n\t\t\t\tsystemPrompt,\n\t\t\t\tlogger,\n\t\t\t});\n\t\tdefault:\n\t\t\t// Reachable from untyped input.\n\t\t\tthrow unknownProvider(provider);\n\t}\n}\n\n/** The provider's cheap model, for the summary of what was undone. */\nfunction summarizerFor(provider: AgentProvider, logger: ILogger): LLMClient {\n\treturn provider === 'anthropic'\n\t\t? new ClaudeLLMClient({ model: 'haiku', reasoningEffort: 'high', systemPrompt: '', logger })\n\t\t: new OpenAILLMClient({\n\t\t\t\tmodel: 'gpt-5.6-luna',\n\t\t\t\treasoningEffort: 'high',\n\t\t\t\tsystemPrompt: '',\n\t\t\t\tlogger,\n\t\t\t});\n}\n\n/**\n * The workspace's history, opened on first use, so a factory that builds an agent stays\n * synchronous. Every agent and every file tool of one workspace reads the same files on disk.\n */\nfunction historyOf(workspace: WorkspaceOptions, logger: ILogger): HistoryReader {\n\t// Checked now: an agent with no root to follow is a setup error, not a first-run one.\n\tif (workspace.roots.length === 0) {\n\t\tthrow new InvalidAgentConfigError('A workspace needs at least one root');\n\t}\n\tlet store: Promise<RecoveryStore> | undefined;\n\tconst open = () => {\n\t\tstore ??= stateDirectoryOf(workspace)\n\t\t\t.then(directory => openStore(workspace, directory, logger))\n\t\t\t.catch((error: unknown) => {\n\t\t\t\t// Not kept: the next run tries again, as one whose disk was full for a moment.\n\t\t\t\tstore = undefined;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\treturn store;\n\t};\n\treturn {\n\t\tlistRuns: async () => (await open()).listRuns(),\n\t\tlistRevisions: async () => (await open()).listRevisions(),\n\t\treadRun: async runId => (await open()).readRun(runId),\n\t};\n}\n\n/**\n * What the model is told about the workspace after its instructions: the roots, which it may\n * change, and how to name a file. A host path in an error sends the model looking for it, so\n * the real root is given here once.\n */\nfunction workspaceGuidance(roots: WorkspaceRoot[]): string {\n\tconst [first, ...others] = roots.map(root => ({ ...root, path: resolve(root.path) }));\n\tif (!first) return '';\n\tconst described = [first, ...others].map(\n\t\t({ path, access }) => `- ${path}${access === 'write' ? '' : ' (read only)'}`,\n\t);\n\treturn [\n\t\t'The workspace:',\n\t\t...described,\n\t\t`Name a file by its path relative to ${first.path}, such as src/index.ts, and a file in another folder of the workspace by its full path. Read a file before you change it.`,\n\t].join('\\n');\n}\n\nfunction withGuidance(systemPrompt: string, guidance: string): string {\n\treturn guidance === '' ? systemPrompt : `${systemPrompt}\\n\\n${guidance}`;\n}\n\n/** An `LLMAgent` on `provider`, wrapped in the harness's retry policy. */\nfunction buildLLMAgent(\n\tprovider: AgentProvider,\n\t{\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt,\n\t\ttools,\n\t\thistory,\n\t\tsummarizer,\n\t\tmaxSteps,\n\t\tcompactAt,\n\t\tautoApprove,\n\t\tlogger,\n\t\tonTranscript,\n\t}: {\n\t\tmodel?: AgentModel;\n\t\treasoningEffort?: ReasoningEffort;\n\t\tsystemPrompt: string;\n\t\ttools: AgentTool[];\n\t\thistory?: HistoryReader;\n\t\tsummarizer?: LLMClient;\n\t\tmaxSteps?: number;\n\t\tcompactAt?: number | undefined;\n\t\tautoApprove?: boolean;\n\t\tlogger: ILogger;\n\t\tonTranscript?: TranscriptCallback | undefined;\n\t},\n): Agent {\n\tconst llmClient = llmClientFor(provider, {\n\t\tmodel,\n\t\treasoningEffort,\n\t\tcompactAt,\n\t\tsystemPrompt,\n\t\tlogger,\n\t});\n\t// LLMAgent records nothing from a failed call, so the original prompt is the whole story.\n\treturn new RetryingAgent({\n\t\tinner: new LLMAgent({\n\t\t\tllmClient,\n\t\t\ttools,\n\t\t\tautoApprove,\n\t\t\tlogger,\n\t\t\t...(history ? { history } : {}),\n\t\t\t...(summarizer ? { summarizer } : {}),\n\t\t\t...(maxSteps === undefined ? {} : { maxSteps }),\n\t\t\t...(onTranscript ? { onTranscript } : {}),\n\t\t}),\n\t\tlogger,\n\t\tnoteFailures: false,\n\t});\n}\n\n/**\n * Builds an agent whose conversation MiKode owns, on a provider's model API, already wrapped in\n * the harness's retry policy. It needs the provider's API key and bills per token, where\n * `createAgent` uses the Agent SDK's login. Each tool judges the risk of each call; a\n * `destructive` one runs only when the run's `approve` allows it, or with `autoApprove`.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider, a model or reasoning effort its\n * client does not support, or two tools that share a name.\n * @throws {UnrecoverableError} when the client cannot be set up, for example because\n * `OPENAI_API_KEY` is missing. The Anthropic SDK resolves credentials lazily, so a missing\n * `ANTHROPIC_API_KEY` fails the first run instead, with an `UnrecoverableError`.\n */\nexport function createLLMAgent(\n\tprovider: AgentProvider,\n\t{\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt,\n\t\ttools = [],\n\t\tworkspace,\n\t\tsummarizeUndone = true,\n\t\tmaxSteps,\n\t\tcompactAt,\n\t\tautoApprove,\n\t\tlogger = new Logger(),\n\t\tonTranscript,\n\t}: CreateLLMAgentOptions,\n): Agent {\n\treturn buildLLMAgent(provider, {\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt: workspace\n\t\t\t? withGuidance(systemPrompt, workspaceGuidance(workspace.roots))\n\t\t\t: systemPrompt,\n\t\t// A file tool or a delegation tool is a harness tool under its public name.\n\t\ttools: tools as AgentTool[],\n\t\t...(workspace ? { history: historyOf(workspace, logger) } : {}),\n\t\t...(workspace && summarizeUndone ? { summarizer: summarizerFor(provider, logger) } : {}),\n\t\tmaxSteps,\n\t\tcompactAt,\n\t\tautoApprove,\n\t\tlogger,\n\t\tonTranscript,\n\t});\n}\n\n/**\n * The file tools for an agent from `createLLMAgent` on `provider`, over `workspace`, in the\n * provider's own format:\n *\n * - OpenAI: `listFiles`, `searchText`, `readFile`, `readFiles` and its native `apply_patch`;\n * - Anthropic: `listFiles`, `searchText`, its native text editor, whose `view` reads, and\n * `delete_file`.\n *\n * Every one goes through the workspace's access policy: a path outside the roots, a secret,\n * a file `.gitignore` excludes or the harness protects is refused. A change is made only in a\n * `write` root, only from a version the agent read, and is recorded in the workspace's history,\n * so it can be undone. Without a `write` root the tools only read. Give the agent the same\n * `workspace`, so it follows what the history undoes.\n *\n * With `commands`, they include `runCommand`, which runs one of them by name, with only the\n * parameters it declares and never through a shell. Each run asks the approver, showing the\n * program exactly as it will run, and gets a small environment without the provider keys. The\n * files of the `write` roots are captured before it and compared after, so what it changed is\n * in the history too. It is trusted execution, not a sandbox: a command can reach whatever\n * this user can. Not supported on Windows yet.\n *\n * With `formatter`, every file an edit creates or changes is formatted right after, its path\n * the formatter's last argument. The edit shows the lines the formatter rewrote, and the model\n * reads a file it rewrote again before editing it. Like a command it runs without a shell, in a small environment, and what it changes in that file is\n * in the history. When it fails, the file stays as the edit wrote it, and the model is told\n * why. Not supported on Windows yet.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider, a workspace with no root, or an\n * invalid command or formatter, including one whose `cwd` is not in a `write` root, or any on\n * Windows.\n * @throws {UnrecoverableError} when no program can read the first root.\n */\nexport async function createFileTools(\n\tprovider: AgentProvider,\n\tworkspace: WorkspaceOptions,\n\t{\n\t\tlogger = new Logger(),\n\t\tcommands,\n\t\tformatter,\n\t}: { logger?: ILogger; commands?: Commands; formatter?: Formatter } = {},\n): Promise<FileTool[]> {\n\t// Reachable from untyped input.\n\tif (!isAgentProvider(provider)) throw unknownProvider(provider);\n\tif (commands !== undefined) validateCommands(commands);\n\tif (formatter !== undefined) validateFormatter(formatter);\n\tconst opened = await openWorkspace(workspace, logger, formatter ? { formatter } : {});\n\treturn (await executorTools(provider, opened, commands)) as unknown as FileTool[];\n}\n\n/** The executor's file tools, and `runCommand` when there are commands. */\nasync function executorTools(\n\tprovider: AgentProvider,\n\tworkspace: OpenedWorkspace,\n\tcommands: Commands | undefined,\n): Promise<AgentTool[]> {\n\tconst tools = fileToolsFor(provider, workspace);\n\t// Every command may belong to other roles, leaving none for this one.\n\tif (commands === undefined || Object.keys(commands).length === 0) return tools;\n\treturn [...tools, await commandToolFor(workspace, commands)];\n}\n\n/** What an explorer finds and reads with: no edits, no changes, no commands. */\nfunction explorerTools({ read, policy }: OpenedWorkspace): AgentTool[] {\n\tconst finding = createWorkspaceTools(read).filter(\n\t\ttool => tool.name !== 'readFile' && tool.name !== 'readFiles',\n\t);\n\treturn [...finding, createTrackedReadFile(policy), createTrackedReadFiles(policy)];\n}\n\n/**\n * What the planner and the reviewer read with: no edits, the current task's changes, `explore`\n * with `explorer`, and the commands given to their role.\n */\nasync function readingTools(\n\tworkspace: OpenedWorkspace,\n\trole: CommandRole,\n\tcommands: Commands | undefined,\n\texplorer: () => Agent,\n): Promise<AgentTool[]> {\n\tconst { policy, store } = workspace;\n\tconst tools = [\n\t\t...explorerTools(workspace),\n\t\tcreateShowChangesTool({ store, policy }),\n\t\tcreateExploreTool(explorer),\n\t];\n\tconst own = commands && commandsFor(commands, role);\n\tif (!own || Object.keys(own).length === 0) return tools;\n\treturn [...tools, await commandToolFor(workspace, own)];\n}\n\nconst batching =\n\t'When you know you need several files, or several searches, ask for all of them in one answer rather than one at a time: each answer is a step, and steps are limited.';\n\n// For the roles that have `readFiles`, which the executor on Claude does not.\nconst batchingReads =\n\t'When you know you need several files, or several ranges, read them in one readFiles call, and ask for several searches in one answer, rather than one at a time: each answer is a step, and steps are limited.';\n\n// The explorers find and the role reads, as a reader asks a librarian where a book is and then\n// reads it: their reports are where to look, not a summary to work from.\nconst exploring =\n\t'To find where something is in the repository, ask explorers instead of searching yourself: send `explore` the independent questions you have in one call, and each answers with the files and line ranges that hold what you asked. Then read those ranges yourself, all of them in one readFiles call.';\n\n// Each provider's cheaper model, which only finds and reads.\nconst explorerRoles = {\n\tanthropic: { model: 'haiku', reasoningEffort: 'medium' },\n\topenai: { model: 'gpt-5.6-luna', reasoningEffort: 'medium' },\n} as const satisfies Record<AgentProvider, { model: AgentModel; reasoningEffort: ReasoningEffort }>;\n\nconst explorerSteps = 30;\n\nconst explorerInstructions = `You find things in a repository for another agent, which is planning or reviewing a change and asked you one question, as a reader asks a librarian where a book is. Find where the answer is with listFiles, searchText, readFile and readFiles, reading only what you need to be sure. Answer with where it is: each file and the line ranges that matter, and in a sentence what each range holds and why it answers the question. The other agent reads those ranges itself, so do not copy code beyond a line that marks a place. Say what you looked for and could not find. Do not propose changes or a plan. ${batchingReads}`;\n\n// How each role finds its way, sent after the workspace's roots, so it stays short. Only the\n// planner learns the repository; the executor and the reviewer work from its plan, so a plan\n// that leaves them guessing is the planner's to fix, not theirs to make up for.\nconst repositoryGuidance: Record<CommandRole, string> = {\n\tplanner: `Start with AGENTS.md, which says where the architecture and the decisions are, and read only the parts your task needs. Name in the plan every file to change and what to change in it, so the executor needs nothing else. ${exploring} ${batchingReads}`,\n\texecutor: `Work from the plan: read the files it names, and only what you need to change them. Do not study the repository's architecture or decisions; the plan already applied them. ${batching}`,\n\treviewer: `Work from the plan and the changes: read what they touch, and only what you need to judge them. ${exploring} ${batchingReads}`,\n};\n\n/**\n * Builds the planner → executor → reviewer workflow with every role on the model APIs, each\n * holding its role's instructions, or `systemPrompts`, as its system prompt, followed by the\n * workspace's roots.\n *\n * - The planner and the reviewer read: `listFiles`, `searchText`, `readFile`, `readFiles`, `showChanges`,\n * the current task's changes as far as each may read them, and `explore`, which sends up to 4\n * read-only explorers at once on the role's provider's cheaper model, each a new agent that\n * starts from its question.\n * - The executor gets its provider's file tools (see `createFileTools`), and changes files only\n * in a `write` root; `autoApprove` reaches only it.\n * - Each role has its own step limit: `maxSteps`, 80 for the executor and 65 for the others by\n * default.\n * - Each role gets `runCommand` with the `commands` whose `roles` name it, the executor by\n * default. A command asks the approver in any role, and its files are captured around it.\n * - When the executor has a command, it is told to finish only once the tests and checks pass,\n * or to say which fail, and the reviewer takes from its response whether they pass. Without\n * one, both are told the tests were not run, and the reviewer judges from the code whether\n * they would pass.\n *\n * One run of the orchestrator is one run of the workspace's history, every round and retry\n * included, and its `AgentResponse` names it. Every role follows what the user undoes.\n * Asynchronous because opening the workspace is.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider, or a workspace with no root.\n * @throws {UnrecoverableError} when a role cannot be set up, for example because\n * `OPENAI_API_KEY` is missing, or when no program can read the repository.\n */\nexport async function createLLMOrchestrator({\n\tprovider,\n\tautoApprove,\n\tsystemPrompts = {},\n\tworkspace = { roots: [{ path: process.cwd(), access: 'read' }] },\n\tmaxSteps,\n\tcompactAt,\n\tcommands,\n\tformatter,\n\tsummarizeUndone = true,\n\tlogger = new Logger(),\n\tonTranscript,\n}: CreateLLMOrchestratorOptions = {}): Promise<Agent> {\n\tconst roles = orchestratorRolesFor(provider);\n\tconst steps = perRole('maxSteps', maxSteps, defaultRoleSteps, {\n\t\tunit: 'steps',\n\t\texample: '{ \"executor\": 120 }',\n\t});\n\tconst compaction = perRole('compactAt', compactAt, defaultRoleCompaction, {\n\t\tunit: 'tokens',\n\t\texample: '{ \"executor\": 200000 }',\n\t});\n\tif (formatter !== undefined) validateFormatter(formatter);\n\tconst opened = await openWorkspace(workspace, logger, formatter ? { formatter } : {});\n\tconst guidance = workspaceGuidance(workspace.roots);\n\tconst summarizer = summarizeUndone ? summarizerFor(roles.planner.provider, logger) : undefined;\n\tconst shared = { history: opened.store, ...(summarizer ? { summarizer } : {}), logger };\n\t// A caller's own prompt replaces our instructions and guidance, not the workspace: the model\n\t// needs the roots to name a file, as `createLLMAgent` gives them.\n\tconst prompt = (role: CommandRole, own: string | undefined, instructions: string) =>\n\t\town === undefined\n\t\t\t? withGuidance(instructions, `${guidance}\\n${repositoryGuidance[role]}`)\n\t\t\t: withGuidance(own, guidance);\n\t// Each transcript names the agent it is of.\n\tconst transcriptsOf = (agent: Transcript['agent']) =>\n\t\tonTranscript && ((transcript: Transcript) => onTranscript({ ...transcript, agent }));\n\t// Every command, checked once, before any role takes its share.\n\tif (commands !== undefined) validateCommands(commands);\n\t// A new explorer for each question, on the role's provider: it starts from the question alone.\n\tconst explorerToolset = explorerTools(opened);\n\tconst explorer = (provider: AgentProvider) => () =>\n\t\tbuildLLMAgent(provider, {\n\t\t\t...explorerRoles[provider],\n\t\t\tsystemPrompt: withGuidance(explorerInstructions, guidance),\n\t\t\ttools: explorerToolset,\n\t\t\tmaxSteps: explorerSteps,\n\t\t\tlogger,\n\t\t\tonTranscript: transcriptsOf('explorer'),\n\t\t});\n\tconst reader = async (\n\t\t{ provider, model, reasoningEffort }: Role,\n\t\trole: CommandRole,\n\t\tsystemPrompt: string,\n\t) =>\n\t\tbuildLLMAgent(provider, {\n\t\t\tmodel,\n\t\t\treasoningEffort,\n\t\t\tsystemPrompt,\n\t\t\ttools: await readingTools(opened, role, commands, explorer(provider)),\n\t\t\tmaxSteps: steps[role],\n\t\t\tcompactAt: compaction[role],\n\t\t\tonTranscript: transcriptsOf(role),\n\t\t\t...shared,\n\t\t});\n\tconst { executor } = roles;\n\tconst executorToolset = await executorTools(\n\t\texecutor.provider,\n\t\topened,\n\t\tcommands && commandsFor(commands, 'executor'),\n\t);\n\t// The executor and the reviewer are told whether the tests were run, which only an executor\n\t// with a command can do.\n\tconst executorRuns = executorToolset.some(tool => tool.name === 'runCommand');\n\n\treturn new OrchestratorAgent({\n\t\tplannerAgent: await reader(\n\t\t\troles.planner,\n\t\t\t'planner',\n\t\t\tprompt('planner', systemPrompts.planner, plannerInstructions),\n\t\t),\n\t\texecutorAgent: buildLLMAgent(executor.provider, {\n\t\t\tmodel: executor.model,\n\t\t\treasoningEffort: executor.reasoningEffort,\n\t\t\tsystemPrompt: prompt(\n\t\t\t\t'executor',\n\t\t\t\tsystemPrompts.executor,\n\t\t\t\texecutorRuns ? executorInstructions : executorInstructionsWithoutCommands,\n\t\t\t),\n\t\t\ttools: executorToolset,\n\t\t\tmaxSteps: steps.executor,\n\t\t\tcompactAt: compaction.executor,\n\t\t\tautoApprove,\n\t\t\tonTranscript: transcriptsOf('executor'),\n\t\t\t...shared,\n\t\t}),\n\t\treviewerAgent: await reader(\n\t\t\troles.reviewer,\n\t\t\t'reviewer',\n\t\t\tprompt(\n\t\t\t\t'reviewer',\n\t\t\t\tsystemPrompts.reviewer,\n\t\t\t\texecutorRuns ? reviewerInstructions : reviewerInstructionsWithoutCommands,\n\t\t\t),\n\t\t),\n\t\treviewerDecisionValidator: new ReviewerDecisionValidator(),\n\t\tlogger,\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agentLLMFactory.js","sourceRoot":"","sources":["../../../src/factory/infrastructure/agentLLMFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAE9D,OAAO,EACN,eAAe,EACf,eAAe,EACf,yBAAyB,GACzB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACN,eAAe,EACf,YAAY,EACZ,sBAAsB,GACtB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACN,oBAAoB,EACpB,mCAAmC,EACnC,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,mCAAmC,GACnC,MAAM,mDAAmD,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,mEAAmE,CAAC;AAE9G,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAErD,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAE3D,OAAO,EAGN,WAAW,EAEX,gBAAgB,EAChB,iBAAiB,GACjB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACN,cAAc,EAEd,YAAY,EAEZ,SAAS,EACT,aAAa,EACb,gBAAgB,GAEhB,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,OAAO,EACN,qBAAqB,EACrB,sBAAsB,GACtB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAa,MAAM,mBAAmB,CAAC;AACrF,OAAO,EACN,cAAc,GAKd,MAAM,YAAY,CAAC;AAEpB,oDAAoD;AACpD,MAAM,CAAC,MAAM,SAAS,GAAG;IACxB,SAAS,EAAE,eAAe;IAC1B,MAAM,EAAE,YAAY;CACsD,CAAC;AAE5E,+DAA+D;AAC/D,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAClC,SAAS,EAAE,yBAAyB;IACpC,MAAM,EAAE,sBAAsB;CACiD,CAAC;AAEjF,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAC3B,QAAkB,EAClB,KAAa;IAEb,OAAO,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,sBAAsB,CACrC,QAAkB,EAClB,KAAa;IAEb,OAAO,OAAO,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;AACtD,CAAC;AAiED,8FAA8F;AAC9F,MAAM,gBAAgB,GAAqC;IAC1D,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;CACZ,CAAC;AAEF,oCAAoC;AACpC,MAAM,qBAAqB,GAAiD;IAC3E,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,SAAS;CACnB,CAAC;AAEF;;;;;;GAMG;AACH,SAAS,OAAO,CACf,IAAY,EACZ,KAAc,EACd,QAAqC,EACrC,EAAE,IAAI,EAAE,OAAO,EAAqC;IAEpD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC3F,uFAAuF;IACvF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,uBAAuB,CAChC,GAAG,IAAI,qCAAqC,IAAI,sBAAsB,OAAO,EAAE,CAC/E,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,QAAQ,CAAC,CAAC,CAAC;IACvE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,uBAAuB,CAChC,GAAG,IAAI,mCAAmC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,0CAA0C,CACtG,CAAC;IACH,CAAC;IACD,8EAA8E;IAC9E,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,CAAC,MAAM,CACpE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAChC,CAAC;IACF,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;AACtD,CAAC;AA6CD,MAAM,qBAAqB,GAAG;IAC7B,SAAS,EAAE,QAAQ;IACnB,MAAM,EAAE,cAAc;CAC+B,CAAC;AAEvD,SAAS,eAAe,CAAC,QAAe;IACvC,OAAO,IAAI,uBAAuB,CACjC,IAAI,MAAM,CAAC,QAAQ,CAAC,gDAAgD,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC/F,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CACpB,QAAuB,EACvB,EACC,KAAK,EACL,eAAe,EACf,SAAS,EACT,YAAY,EACZ,MAAM,GAON;IAED,QAAQ,QAAQ,EAAE,CAAC;QAClB,KAAK,WAAW;YACf,OAAO,IAAI,eAAe,CAAC;gBAC1B,KAAK,EAAE,KAAK,IAAI,qBAAqB,CAAC,SAAS;gBAC/C,eAAe;gBACf,SAAS;gBACT,YAAY;gBACZ,MAAM;aACN,CAAC,CAAC;QACJ,KAAK,QAAQ;YACZ,OAAO,IAAI,eAAe,CAAC;gBAC1B,KAAK,EAAE,KAAK,IAAI,qBAAqB,CAAC,MAAM;gBAC5C,eAAe;gBACf,SAAS;gBACT,YAAY;gBACZ,MAAM;aACN,CAAC,CAAC;QACJ;YACC,gCAAgC;YAChC,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;AACF,CAAC;AAED,sEAAsE;AACtE,SAAS,aAAa,CAAC,QAAuB,EAAE,MAAe;IAC9D,OAAO,QAAQ,KAAK,WAAW;QAC9B,CAAC,CAAC,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;QAC5F,CAAC,CAAC,IAAI,eAAe,CAAC;YACpB,KAAK,EAAE,cAAc;YACrB,eAAe,EAAE,MAAM;YACvB,YAAY,EAAE,EAAE;YAChB,MAAM;SACN,CAAC,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,SAAS,SAAS,CAAC,SAA2B,EAAE,MAAe;IAC9D,sFAAsF;IACtF,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,uBAAuB,CAAC,qCAAqC,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,KAAyC,CAAC;IAC9C,MAAM,IAAI,GAAG,GAAG,EAAE;QACjB,KAAK,KAAK,gBAAgB,CAAC,SAAS,CAAC;aACnC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;aAC1D,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACzB,+EAA+E;YAC/E,KAAK,GAAG,SAAS,CAAC;YAClB,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QACJ,OAAO,KAAK,CAAC;IACd,CAAC,CAAC;IACF,OAAO;QACN,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE;QAC/C,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,aAAa,EAAE;QACzD,OAAO,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;KACrD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,KAAsB;IAChD,MAAM,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACtF,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,CACvC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CAC5E,CAAC;IACF,OAAO;QACN,gBAAgB;QAChB,GAAG,SAAS;QACZ,uCAAuC,KAAK,CAAC,IAAI,2HAA2H;KAC5K,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB,EAAE,QAAgB;IAC3D,OAAO,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,OAAO,QAAQ,EAAE,CAAC;AAC1E,CAAC;AAED,0EAA0E;AAC1E,SAAS,aAAa,CACrB,QAAuB,EACvB,EACC,KAAK,EACL,eAAe,EACf,YAAY,EACZ,KAAK,EACL,OAAO,EACP,UAAU,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,MAAM,EACN,YAAY,GAaZ;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,EAAE;QACxC,KAAK;QACL,eAAe;QACf,SAAS;QACT,YAAY;QACZ,MAAM;KACN,CAAC,CAAC;IACH,0FAA0F;IAC1F,OAAO,IAAI,aAAa,CAAC;QACxB,KAAK,EAAE,IAAI,QAAQ,CAAC;YACnB,SAAS;YACT,KAAK;YACL,WAAW;YACX,MAAM;YACN,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrC,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;YAC/C,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzC,CAAC;QACF,MAAM;QACN,YAAY,EAAE,KAAK;KACnB,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAC7B,QAAuB,EACvB,EACC,KAAK,EACL,eAAe,EACf,YAAY,EACZ,KAAK,GAAG,EAAE,EACV,SAAS,EACT,eAAe,GAAG,IAAI,EACtB,QAAQ,EACR,SAAS,EACT,WAAW,EACX,MAAM,GAAG,IAAI,MAAM,EAAE,EACrB,YAAY,GACW;IAExB,OAAO,aAAa,CAAC,QAAQ,EAAE;QAC9B,KAAK;QACL,eAAe;QACf,YAAY,EAAE,SAAS;YACtB,CAAC,CAAC,YAAY,CAAC,YAAY,EAAE,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAChE,CAAC,CAAC,YAAY;QACf,4EAA4E;QAC5E,KAAK,EAAE,KAAoB;QAC3B,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,SAAS,IAAI,eAAe,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxF,QAAQ;QACR,SAAS;QACT,WAAW;QACX,MAAM;QACN,YAAY;KACZ,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACpC,QAAuB,EACvB,SAA2B,EAC3B,EACC,MAAM,GAAG,IAAI,MAAM,EAAE,EACrB,QAAQ,EACR,SAAS,MAC4D,EAAE;IAExE,gCAAgC;IAChC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;QAAE,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,QAAQ,KAAK,SAAS;QAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,SAAS,KAAK,SAAS;QAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtF,OAAO,CAAC,MAAM,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAA0B,CAAC;AACnF,CAAC;AAED,2EAA2E;AAC3E,KAAK,UAAU,aAAa,CAC3B,QAAuB,EACvB,SAA0B,EAC1B,QAA8B;IAE9B,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChD,sEAAsE;IACtE,IAAI,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/E,OAAO,CAAC,GAAG,KAAK,EAAE,MAAM,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,gFAAgF;AAChF,SAAS,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,EAAmB;IACvD,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC,MAAM,CAChD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,CAC7D,CAAC;IACF,OAAO,CAAC,GAAG,OAAO,EAAE,qBAAqB,CAAC,MAAM,CAAC,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,YAAY,CAC1B,SAA0B,EAC1B,IAAiB,EACjB,QAA8B,EAC9B,QAAqB;IAErB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IACpC,MAAM,KAAK,GAAG;QACb,GAAG,aAAa,CAAC,SAAS,CAAC;QAC3B,qBAAqB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QACxC,iBAAiB,CAAC,QAAQ,CAAC;KAC3B,CAAC;IACF,MAAM,GAAG,GAAG,QAAQ,IAAI,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,OAAO,CAAC,GAAG,KAAK,EAAE,MAAM,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,QAAQ,GACb,uKAAuK,CAAC;AAEzK,8EAA8E;AAC9E,MAAM,aAAa,GAClB,gNAAgN,CAAC;AAElN,+FAA+F;AAC/F,yEAAyE;AACzE,MAAM,SAAS,GACd,6WAA6W,CAAC;AAE/W,6DAA6D;AAC7D,MAAM,aAAa,GAAG;IACrB,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE;IACxD,MAAM,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE;CACsC,CAAC;AAEpG,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB,MAAM,oBAAoB,GAAG,wlBAAwlB,aAAa,EAAE,CAAC;AAEroB,6FAA6F;AAC7F,6FAA6F;AAC7F,gFAAgF;AAChF,MAAM,kBAAkB,GAAgC;IACvD,OAAO,EAAE,+NAA+N,SAAS,IAAI,aAAa,EAAE;IACpQ,QAAQ,EAAE,+KAA+K,QAAQ,EAAE;IACnM,QAAQ,EAAE,mGAAmG,SAAS,IAAI,aAAa,EAAE;CACzI,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAC3C,QAAQ,EACR,WAAW,EACX,aAAa,GAAG,EAAE,EAClB,SAAS,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EAChE,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,SAAS,EACT,eAAe,GAAG,IAAI,EACtB,MAAM,GAAG,IAAI,MAAM,EAAE,EACrB,YAAY,MACqB,EAAE;IACnC,MAAM,KAAK,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE;QAC7D,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,qBAAqB;KAC9B,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,SAAS,EAAE,qBAAqB,EAAE;QACzE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,wBAAwB;KACjC,CAAC,CAAC;IACH,IAAI,SAAS,KAAK,SAAS;QAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtF,MAAM,QAAQ,GAAG,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,eAAe,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/F,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACxF,6FAA6F;IAC7F,kEAAkE;IAClE,MAAM,MAAM,GAAG,CAAC,IAAiB,EAAE,GAAuB,EAAE,YAAoB,EAAE,EAAE,CACnF,GAAG,KAAK,SAAS;QAChB,CAAC,CAAC,YAAY,CAAC,YAAY,EAAE,GAAG,QAAQ,KAAK,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;QACxE,CAAC,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAChC,4CAA4C;IAC5C,MAAM,aAAa,GAAG,CAAC,KAA0B,EAAE,EAAE,CACpD,YAAY,IAAI,CAAC,CAAC,UAAsB,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACtF,gEAAgE;IAChE,IAAI,QAAQ,KAAK,SAAS;QAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACvD,+FAA+F;IAC/F,MAAM,eAAe,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,CAAC,QAAuB,EAAE,EAAE,CAAC,GAAG,EAAE,CAClD,aAAa,CAAC,QAAQ,EAAE;QACvB,GAAG,aAAa,CAAC,QAAQ,CAAC;QAC1B,YAAY,EAAE,YAAY,CAAC,oBAAoB,EAAE,QAAQ,CAAC;QAC1D,KAAK,EAAE,eAAe;QACtB,QAAQ,EAAE,aAAa;QACvB,MAAM;QACN,YAAY,EAAE,aAAa,CAAC,UAAU,CAAC;KACvC,CAAC,CAAC;IACJ,MAAM,MAAM,GAAG,KAAK,EACnB,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAQ,EAC1C,IAAiB,EACjB,YAAoB,EACnB,EAAE,CACH,aAAa,CAAC,QAAQ,EAAE;QACvB,KAAK;QACL,eAAe;QACf,YAAY;QACZ,KAAK,EAAE,MAAM,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrE,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC;QACrB,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC;QAC3B,YAAY,EAAE,aAAa,CAAC,IAAI,CAAC;QACjC,GAAG,MAAM;KACT,CAAC,CAAC;IACJ,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAC3B,MAAM,eAAe,GAAG,MAAM,aAAa,CAC1C,QAAQ,CAAC,QAAQ,EACjB,MAAM,EACN,QAAQ,IAAI,WAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,CAC7C,CAAC;IACF,4FAA4F;IAC5F,yBAAyB;IACzB,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAE9E,OAAO,IAAI,iBAAiB,CAAC;QAC5B,YAAY,EAAE,MAAM,MAAM,CACzB,KAAK,CAAC,OAAO,EACb,SAAS,EACT,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAC7D;QACD,aAAa,EAAE,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE;YAC/C,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,YAAY,EAAE,MAAM,CACnB,UAAU,EACV,aAAa,CAAC,QAAQ,EACtB,YAAY,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,mCAAmC,CACzE;YACD,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,UAAU,CAAC,QAAQ;YAC9B,WAAW;YACX,YAAY,EAAE,aAAa,CAAC,UAAU,CAAC;YACvC,GAAG,MAAM;SACT,CAAC;QACF,aAAa,EAAE,MAAM,MAAM,CAC1B,KAAK,CAAC,QAAQ,EACd,UAAU,EACV,MAAM,CACL,UAAU,EACV,aAAa,CAAC,QAAQ,EACtB,YAAY,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,mCAAmC,CACzE,CACD;QACD,yBAAyB,EAAE,IAAI,yBAAyB,EAAE;QAC1D,MAAM;KACN,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { resolve } from 'node:path';\nimport type { Agent } from '#src/agent/domain/agent';\nimport type { Transcript, TranscriptCallback } from '#src/agent/domain/transcript';\nimport type { HistoryReader } from '#src/engines/domain/model/historyFollower';\nimport { LLMAgent } from '#src/engines/domain/model/llmAgent';\nimport type { LLMClient } from '#src/llm/domain/llm';\nimport {\n\tClaudeLLMClient,\n\tclaudeLLMModels,\n\tclaudeLLMReasoningEfforts,\n} from '#src/llm/infrastructure/claudeLLMClient';\nimport {\n\tOpenAILLMClient,\n\topenAIModels,\n\topenAIReasoningEfforts,\n} from '#src/llm/infrastructure/openAILLMClient';\nimport {\n\texecutorInstructions,\n\texecutorInstructionsWithoutCommands,\n\tOrchestratorAgent,\n\tplannerInstructions,\n\treviewerInstructions,\n\treviewerInstructionsWithoutCommands,\n} from '#src/orchestration/domain/model/orchestratorAgent';\nimport { ReviewerDecisionValidator } from '#src/orchestration/infrastructure/model/reviewerDecisionValidator';\nimport type { RecoveryStore } from '#src/recovery/domain/recoveryStore';\nimport { RetryingAgent } from '#src/retry/domain/model/retryingAgent';\nimport { InvalidAgentConfigError } from '#src/shared/domain/errors';\nimport { isOneOf } from '#src/shared/domain/isOneOf';\nimport type { ILogger } from '#src/shared/domain/logger';\nimport { Logger } from '#src/shared/infrastructure/logger';\nimport type { WorkspaceRoot } from '#src/tools/domain/accessPolicy';\nimport {\n\ttype CommandRole,\n\ttype Commands,\n\tcommandsFor,\n\ttype Formatter,\n\tvalidateCommands,\n\tvalidateFormatter,\n} from '#src/tools/domain/commands';\nimport type { AgentTool } from '#src/tools/domain/preparedCall';\nimport type { Tool } from '#src/tools/domain/tool';\nimport {\n\tcommandToolFor,\n\ttype FileTool,\n\tfileToolsFor,\n\ttype OpenedWorkspace,\n\topenStore,\n\topenWorkspace,\n\tstateDirectoryOf,\n\ttype WorkspaceOptions,\n} from '#src/tools/infrastructure/fileTools';\nimport type { DelegationTool } from '#src/tools/infrastructure/agentAsTool';\nimport { createExploreTool } from '#src/tools/infrastructure/exploreTool';\nimport { createShowChangesTool } from '#src/tools/infrastructure/showChangesTool';\nimport {\n\tcreateTrackedReadFile,\n\tcreateTrackedReadFiles,\n} from '#src/tools/infrastructure/trackedReadFile';\nimport { createWorkspaceTools } from '#src/tools/infrastructure/workspaceTools';\nimport { isAgentProvider, orchestratorRolesFor, type Role } from './agentFactory.ts';\nimport {\n\tagentProviders,\n\ttype AgentModel,\n\ttype AgentProvider,\n\ttype CreateOrchestratorOptions,\n\ttype ReasoningEffort,\n} from './types.ts';\n\n/** The models each provider's model API accepts. */\nexport const llmModels = {\n\tanthropic: claudeLLMModels,\n\topenai: openAIModels,\n} as const satisfies Readonly<Record<AgentProvider, readonly AgentModel[]>>;\n\n/** The reasoning efforts each provider's model API accepts. */\nexport const llmReasoningEfforts = {\n\tanthropic: claudeLLMReasoningEfforts,\n\topenai: openAIReasoningEfforts,\n} as const satisfies Readonly<Record<AgentProvider, readonly ReasoningEffort[]>>;\n\n/** Narrows a model to one accepted by the selected provider's model API. */\nexport function isLLMModelOf<Provider extends AgentProvider>(\n\tprovider: Provider,\n\tvalue: string,\n): value is (typeof llmModels)[Provider][number] {\n\treturn isOneOf(llmModels[provider], value);\n}\n\n/** Narrows a reasoning effort to one accepted by the selected provider's model API. */\nexport function isLLMReasoningEffortOf<Provider extends AgentProvider>(\n\tprovider: Provider,\n\tvalue: string,\n): value is (typeof llmReasoningEfforts)[Provider][number] {\n\treturn isOneOf(llmReasoningEfforts[provider], value);\n}\n\nexport interface CreateLLMAgentOptions {\n\t/**\n\t * Defaults to `'sonnet'` on Anthropic and `'gpt-5.6-luna'` on OpenAI. The provider's client\n\t * rejects a model it does not support.\n\t */\n\tmodel?: AgentModel;\n\t/** Defaults to `'high'`. The provider's client rejects an effort it does not support. */\n\treasoningEffort?: ReasoningEffort;\n\t/** Sent as the model's instructions on every call. */\n\tsystemPrompt: string;\n\t/**\n\t * The tools the model may call: the consumer's own, those of `createFileTools`, and agents\n\t * offered with `agentAsTool`. Defaults to none.\n\t */\n\ttools?: (Tool | FileTool | DelegationTool)[];\n\t/**\n\t * The folders the agent works on, the same as given to `createFileTools`. With it, the agent\n\t * follows the workspace's history: after the user undoes runs, its next run starts from the\n\t * conversation as it was, and is told what was undone. The system prompt is followed by the\n\t * roots and how to name a file in them.\n\t */\n\tworkspace?: WorkspaceOptions;\n\t/**\n\t * With `workspace`, a summary of what was undone, from the provider's cheap model, in place\n\t * of the undone prompts. That is Claude Haiku 5.5 or `gpt-5.6-luna`, at high effort, and the\n\t * call is billed with the run's tokens. Defaults to `true`.\n\t */\n\tsummarizeUndone?: boolean;\n\t/**\n\t * How many calls to the model one run may make before it fails. Defaults to 65, with no upper\n\t * bound. A run that asks for exactly the same tool calls 5 times in a row fails before that.\n\t */\n\tmaxSteps?: number;\n\t/**\n\t * The input tokens at which the provider compacts the conversation on its side: it replaces\n\t * every turn before that call with its own summary, which only its model reads back. The\n\t * conversation keeps every original turn. Without it, the conversation is never compacted.\n\t * At least 50,000 on Anthropic.\n\t */\n\tcompactAt?: number;\n\t/**\n\t * Runs every tool call without asking, `destructive` ones included, for CI where no one can\n\t * answer. Without it, a `destructive` call goes to the run's `approve`, or is denied.\n\t */\n\tautoApprove?: boolean;\n\t/** Defaults to warnings on stderr. */\n\tlogger?: ILogger;\n\t/**\n\t * Receives what the model saw in each run once the run ended, completed, failed or\n\t * cancelled, for debugging. See `Transcript`. Without it, nothing is kept.\n\t */\n\tonTranscript?: TranscriptCallback;\n}\n\n/** A limit per role of `createLLMOrchestrator`; a role left out keeps its default. */\nexport type RoleSteps = Partial<Record<OrchestratorRole, number>>;\n\n/** A number of tokens per role of `createLLMOrchestrator`; a role left out keeps its default. */\nexport type RoleTokens = Partial<Record<OrchestratorRole, number>>;\n\n// The same three roles a command can be given to.\ntype OrchestratorRole = CommandRole;\n\n// The executor reads, edits and checks, so it needs more calls than the roles that only read.\nconst defaultRoleSteps: Record<OrchestratorRole, number> = {\n\tplanner: 65,\n\texecutor: 80,\n\treviewer: 65,\n};\n\n// No role compacts unless asked to.\nconst defaultRoleCompaction: Record<OrchestratorRole, number | undefined> = {\n\tplanner: undefined,\n\texecutor: undefined,\n\treviewer: undefined,\n};\n\n/**\n * Each role's value of the option `name`, from one number for all of them or a number per role.\n * Each number is checked by whatever takes it.\n *\n * @throws {InvalidAgentConfigError} for a value that is neither, and for a role that does not\n * exist, which is a typo that would otherwise leave that role on its default without a word.\n */\nfunction perRole<T extends number | undefined>(\n\tname: string,\n\tvalue: unknown,\n\tdefaults: Record<OrchestratorRole, T>,\n\t{ unit, example }: { unit: string; example: string },\n): Record<OrchestratorRole, T | number> {\n\tif (value === undefined) return defaults;\n\tif (typeof value === 'number') return { planner: value, executor: value, reviewer: value };\n\t// Untyped input, such as the CLI's configuration file, can hold `null` or a list here.\n\tif (typeof value !== 'object' || value === null || Array.isArray(value)) {\n\t\tthrow new InvalidAgentConfigError(\n\t\t\t`${name} must be a number or an object of ${unit} per role, such as ${example}`,\n\t\t);\n\t}\n\tconst unknown = Object.keys(value).filter(role => !(role in defaults));\n\tif (unknown.length > 0) {\n\t\tthrow new InvalidAgentConfigError(\n\t\t\t`${name} names roles that do not exist: ${unknown.join(', ')}; expected planner, executor or reviewer`,\n\t\t);\n\t}\n\t// A role given as `undefined`, which untyped input can do, keeps its default.\n\tconst given = Object.entries(value as Record<string, unknown>).filter(\n\t\t([, each]) => each !== undefined,\n\t);\n\treturn { ...defaults, ...Object.fromEntries(given) };\n}\n\nexport interface CreateLLMOrchestratorOptions extends CreateOrchestratorOptions {\n\t/**\n\t * The folders the agents work on. The executor changes files only in a `write` root, every\n\t * change recorded in the workspace's history. Defaults to the current working directory,\n\t * read only.\n\t */\n\tworkspace?: WorkspaceOptions;\n\t/**\n\t * How many calls to the model one run of each role may make: one number for every role, or a\n\t * number per role. Defaults to 80 for the executor and 65 for the planner and the reviewer,\n\t * with no upper bound. A run that asks for exactly the same tool calls 5 times in a row fails\n\t * before its limit.\n\t */\n\tmaxSteps?: number | RoleSteps;\n\t/**\n\t * The input tokens at which each role's provider compacts its conversation, as\n\t * `CreateLLMAgentOptions.compactAt`: one number for every role, or a number per role. Without\n\t * it, no role compacts.\n\t */\n\tcompactAt?: number | RoleTokens;\n\t/**\n\t * Commands the roles may run, such as the project's tests, through `runCommand`. Each goes to\n\t * the roles its `roles` names, the executor by default. See `createFileTools`. Each needs a\n\t * `write` root to run in.\n\t */\n\tcommands?: Commands;\n\t/**\n\t * A program the executor's edits run on each file they create or change, such as the\n\t * project's formatter. See `createFileTools`. It needs a `write` root to run in.\n\t */\n\tformatter?: Formatter;\n\t/**\n\t * A summary of what the user undid, from the planner's provider's cheap model, for every\n\t * role. See `CreateLLMAgentOptions.summarizeUndone`. Defaults to `true`.\n\t */\n\tsummarizeUndone?: boolean;\n\t/**\n\t * Receives what the model saw in each run of each role and each explorer, once the run\n\t * ended, for debugging. Each transcript names its role. See `Transcript`.\n\t */\n\tonTranscript?: TranscriptCallback;\n}\n\nconst defaultLLMAgentModels = {\n\tanthropic: 'sonnet',\n\topenai: 'gpt-5.6-luna',\n} as const satisfies Record<AgentProvider, AgentModel>;\n\nfunction unknownProvider(provider: never): InvalidAgentConfigError {\n\treturn new InvalidAgentConfigError(\n\t\t`\"${String(provider)}\" is not an agent provider; expected one of: ${agentProviders.join(', ')}`,\n\t);\n}\n\nfunction llmClientFor(\n\tprovider: AgentProvider,\n\t{\n\t\tmodel,\n\t\treasoningEffort,\n\t\tcompactAt,\n\t\tsystemPrompt,\n\t\tlogger,\n\t}: {\n\t\tmodel?: AgentModel;\n\t\treasoningEffort?: ReasoningEffort;\n\t\tcompactAt?: number | undefined;\n\t\tsystemPrompt: string;\n\t\tlogger: ILogger;\n\t},\n): LLMClient {\n\tswitch (provider) {\n\t\tcase 'anthropic':\n\t\t\treturn new ClaudeLLMClient({\n\t\t\t\tmodel: model ?? defaultLLMAgentModels.anthropic,\n\t\t\t\treasoningEffort,\n\t\t\t\tcompactAt,\n\t\t\t\tsystemPrompt,\n\t\t\t\tlogger,\n\t\t\t});\n\t\tcase 'openai':\n\t\t\treturn new OpenAILLMClient({\n\t\t\t\tmodel: model ?? defaultLLMAgentModels.openai,\n\t\t\t\treasoningEffort,\n\t\t\t\tcompactAt,\n\t\t\t\tsystemPrompt,\n\t\t\t\tlogger,\n\t\t\t});\n\t\tdefault:\n\t\t\t// Reachable from untyped input.\n\t\t\tthrow unknownProvider(provider);\n\t}\n}\n\n/** The provider's cheap model, for the summary of what was undone. */\nfunction summarizerFor(provider: AgentProvider, logger: ILogger): LLMClient {\n\treturn provider === 'anthropic'\n\t\t? new ClaudeLLMClient({ model: 'haiku', reasoningEffort: 'high', systemPrompt: '', logger })\n\t\t: new OpenAILLMClient({\n\t\t\t\tmodel: 'gpt-5.6-luna',\n\t\t\t\treasoningEffort: 'high',\n\t\t\t\tsystemPrompt: '',\n\t\t\t\tlogger,\n\t\t\t});\n}\n\n/**\n * The workspace's history, opened on first use, so a factory that builds an agent stays\n * synchronous. Every agent and every file tool of one workspace reads the same files on disk.\n */\nfunction historyOf(workspace: WorkspaceOptions, logger: ILogger): HistoryReader {\n\t// Checked now: an agent with no root to follow is a setup error, not a first-run one.\n\tif (workspace.roots.length === 0) {\n\t\tthrow new InvalidAgentConfigError('A workspace needs at least one root');\n\t}\n\tlet store: Promise<RecoveryStore> | undefined;\n\tconst open = () => {\n\t\tstore ??= stateDirectoryOf(workspace)\n\t\t\t.then(directory => openStore(workspace, directory, logger))\n\t\t\t.catch((error: unknown) => {\n\t\t\t\t// Not kept: the next run tries again, as one whose disk was full for a moment.\n\t\t\t\tstore = undefined;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\treturn store;\n\t};\n\treturn {\n\t\tlistRuns: async () => (await open()).listRuns(),\n\t\tlistRevisions: async () => (await open()).listRevisions(),\n\t\treadRun: async runId => (await open()).readRun(runId),\n\t};\n}\n\n/**\n * What the model is told about the workspace after its instructions: the roots, which it may\n * change, and how to name a file. A host path in an error sends the model looking for it, so\n * the real root is given here once.\n */\nfunction workspaceGuidance(roots: WorkspaceRoot[]): string {\n\tconst [first, ...others] = roots.map(root => ({ ...root, path: resolve(root.path) }));\n\tif (!first) return '';\n\tconst described = [first, ...others].map(\n\t\t({ path, access }) => `- ${path}${access === 'write' ? '' : ' (read only)'}`,\n\t);\n\treturn [\n\t\t'The workspace:',\n\t\t...described,\n\t\t`Name a file by its path relative to ${first.path}, such as src/index.ts, and a file in another folder of the workspace by its full path. Read a file before you change it.`,\n\t].join('\\n');\n}\n\nfunction withGuidance(systemPrompt: string, guidance: string): string {\n\treturn guidance === '' ? systemPrompt : `${systemPrompt}\\n\\n${guidance}`;\n}\n\n/** An `LLMAgent` on `provider`, wrapped in the harness's retry policy. */\nfunction buildLLMAgent(\n\tprovider: AgentProvider,\n\t{\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt,\n\t\ttools,\n\t\thistory,\n\t\tsummarizer,\n\t\tmaxSteps,\n\t\tcompactAt,\n\t\tautoApprove,\n\t\tlogger,\n\t\tonTranscript,\n\t}: {\n\t\tmodel?: AgentModel;\n\t\treasoningEffort?: ReasoningEffort;\n\t\tsystemPrompt: string;\n\t\ttools: AgentTool[];\n\t\thistory?: HistoryReader;\n\t\tsummarizer?: LLMClient;\n\t\tmaxSteps?: number;\n\t\tcompactAt?: number | undefined;\n\t\tautoApprove?: boolean;\n\t\tlogger: ILogger;\n\t\tonTranscript?: TranscriptCallback | undefined;\n\t},\n): Agent {\n\tconst llmClient = llmClientFor(provider, {\n\t\tmodel,\n\t\treasoningEffort,\n\t\tcompactAt,\n\t\tsystemPrompt,\n\t\tlogger,\n\t});\n\t// LLMAgent records nothing from a failed call, so the original prompt is the whole story.\n\treturn new RetryingAgent({\n\t\tinner: new LLMAgent({\n\t\t\tllmClient,\n\t\t\ttools,\n\t\t\tautoApprove,\n\t\t\tlogger,\n\t\t\t...(history ? { history } : {}),\n\t\t\t...(summarizer ? { summarizer } : {}),\n\t\t\t...(maxSteps === undefined ? {} : { maxSteps }),\n\t\t\t...(onTranscript ? { onTranscript } : {}),\n\t\t}),\n\t\tlogger,\n\t\tnoteFailures: false,\n\t});\n}\n\n/**\n * Builds an agent whose conversation MiKode owns, on a provider's model API, already wrapped in\n * the harness's retry policy. It needs the provider's API key and bills per token, where\n * `createAgent` uses the Agent SDK's login. Each tool judges the risk of each call; a\n * `destructive` one runs only when the run's `approve` allows it, or with `autoApprove`.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider, a model or reasoning effort its\n * client does not support, or two tools that share a name.\n * @throws {UnrecoverableError} when the client cannot be set up, for example because\n * `OPENAI_API_KEY` is missing. The Anthropic SDK resolves credentials lazily, so a missing\n * `ANTHROPIC_API_KEY` fails the first run instead, with an `UnrecoverableError`.\n */\nexport function createLLMAgent(\n\tprovider: AgentProvider,\n\t{\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt,\n\t\ttools = [],\n\t\tworkspace,\n\t\tsummarizeUndone = true,\n\t\tmaxSteps,\n\t\tcompactAt,\n\t\tautoApprove,\n\t\tlogger = new Logger(),\n\t\tonTranscript,\n\t}: CreateLLMAgentOptions,\n): Agent {\n\treturn buildLLMAgent(provider, {\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt: workspace\n\t\t\t? withGuidance(systemPrompt, workspaceGuidance(workspace.roots))\n\t\t\t: systemPrompt,\n\t\t// A file tool or a delegation tool is a harness tool under its public name.\n\t\ttools: tools as AgentTool[],\n\t\t...(workspace ? { history: historyOf(workspace, logger) } : {}),\n\t\t...(workspace && summarizeUndone ? { summarizer: summarizerFor(provider, logger) } : {}),\n\t\tmaxSteps,\n\t\tcompactAt,\n\t\tautoApprove,\n\t\tlogger,\n\t\tonTranscript,\n\t});\n}\n\n/**\n * The file tools for an agent from `createLLMAgent` on `provider`, over `workspace`, in the\n * provider's own format:\n *\n * - OpenAI: `listFiles`, `searchText`, `readFile`, `readFiles` and its native `apply_patch`;\n * - Anthropic: `listFiles`, `searchText`, its native text editor, whose `view` reads, and\n * `delete_file`.\n *\n * Every one goes through the workspace's access policy: a path outside the roots, a secret,\n * a file `.gitignore` excludes or the harness protects is refused. A change is made only in a\n * `write` root, only from a version the agent read, and is recorded in the workspace's history,\n * so it can be undone. Without a `write` root the tools only read. Give the agent the same\n * `workspace`, so it follows what the history undoes.\n *\n * With `commands`, they include `runCommand`, which runs one of them by name, with only the\n * parameters it declares and never through a shell. Each run asks the approver, showing the\n * program exactly as it will run, and gets a small environment without the provider keys. The\n * files of the `write` roots are captured before it and compared after, so what it changed is\n * in the history too. It is trusted execution, not a sandbox: a command can reach whatever\n * this user can. Not supported on Windows yet.\n *\n * With `formatter`, every file an edit creates or changes is formatted right after, its path\n * the formatter's last argument. The edit shows the lines the formatter rewrote, and the model\n * reads a file it rewrote again before editing it. Like a command it runs without a shell, in a small environment, and what it changes in that file is\n * in the history. When it fails, the file stays as the edit wrote it, and the model is told\n * why. Not supported on Windows yet.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider, a workspace with no root, or an\n * invalid command or formatter, including one whose `cwd` is not in a `write` root, or any on\n * Windows.\n * @throws {UnrecoverableError} when no program can read the first root.\n */\nexport async function createFileTools(\n\tprovider: AgentProvider,\n\tworkspace: WorkspaceOptions,\n\t{\n\t\tlogger = new Logger(),\n\t\tcommands,\n\t\tformatter,\n\t}: { logger?: ILogger; commands?: Commands; formatter?: Formatter } = {},\n): Promise<FileTool[]> {\n\t// Reachable from untyped input.\n\tif (!isAgentProvider(provider)) throw unknownProvider(provider);\n\tif (commands !== undefined) validateCommands(commands);\n\tif (formatter !== undefined) validateFormatter(formatter);\n\tconst opened = await openWorkspace(workspace, logger, formatter ? { formatter } : {});\n\treturn (await executorTools(provider, opened, commands)) as unknown as FileTool[];\n}\n\n/** The executor's file tools, and `runCommand` when there are commands. */\nasync function executorTools(\n\tprovider: AgentProvider,\n\tworkspace: OpenedWorkspace,\n\tcommands: Commands | undefined,\n): Promise<AgentTool[]> {\n\tconst tools = fileToolsFor(provider, workspace);\n\t// Every command may belong to other roles, leaving none for this one.\n\tif (commands === undefined || Object.keys(commands).length === 0) return tools;\n\treturn [...tools, await commandToolFor(workspace, commands)];\n}\n\n/** What an explorer finds and reads with: no edits, no changes, no commands. */\nfunction explorerTools({ read, policy }: OpenedWorkspace): AgentTool[] {\n\tconst finding = createWorkspaceTools(read).filter(\n\t\ttool => tool.name !== 'readFile' && tool.name !== 'readFiles',\n\t);\n\treturn [...finding, createTrackedReadFile(policy), createTrackedReadFiles(policy)];\n}\n\n/**\n * What the planner and the reviewer read with: no edits, the current task's changes, `explore`\n * with `explorer`, and the commands given to their role.\n */\nasync function readingTools(\n\tworkspace: OpenedWorkspace,\n\trole: CommandRole,\n\tcommands: Commands | undefined,\n\texplorer: () => Agent,\n): Promise<AgentTool[]> {\n\tconst { policy, store } = workspace;\n\tconst tools = [\n\t\t...explorerTools(workspace),\n\t\tcreateShowChangesTool({ store, policy }),\n\t\tcreateExploreTool(explorer),\n\t];\n\tconst own = commands && commandsFor(commands, role);\n\tif (!own || Object.keys(own).length === 0) return tools;\n\treturn [...tools, await commandToolFor(workspace, own)];\n}\n\nconst batching =\n\t'When you know you need several files, or several searches, ask for all of them in one answer rather than one at a time: each answer is a step, and steps are limited.';\n\n// For the roles that have `readFiles`, which the executor on Claude does not.\nconst batchingReads =\n\t'When you know you need several files, or several ranges, read them in one readFiles call, and ask for several searches in one answer, rather than one at a time: each answer is a step, and steps are limited.';\n\n// The explorers find and the role reads, as a reader asks a librarian where a book is and then\n// reads it: their reports are where to look, not a summary to work from.\nconst exploring =\n\t'To find where something is in the repository, ask explorers instead of searching yourself: send `explore` the independent questions you have in one call. They work in the background while you go on, and each one answers, once it finishes, with the files and line ranges that hold what you asked. Then read those ranges yourself, all of them in one readFiles call.';\n\n// Each provider's cheaper model, which only finds and reads.\nconst explorerRoles = {\n\tanthropic: { model: 'haiku', reasoningEffort: 'medium' },\n\topenai: { model: 'gpt-5.6-luna', reasoningEffort: 'medium' },\n} as const satisfies Record<AgentProvider, { model: AgentModel; reasoningEffort: ReasoningEffort }>;\n\nconst explorerSteps = 30;\n\nconst explorerInstructions = `You find things in a repository for another agent, which is planning or reviewing a change and asked you one question, as a reader asks a librarian where a book is. Find where the answer is with listFiles, searchText, readFile and readFiles, reading only what you need to be sure. Answer with where it is: each file and the line ranges that matter, and in a sentence what each range holds and why it answers the question. The other agent reads those ranges itself, so do not copy code beyond a line that marks a place. Say what you looked for and could not find. Do not propose changes or a plan. ${batchingReads}`;\n\n// How each role finds its way, sent after the workspace's roots, so it stays short. Only the\n// planner learns the repository; the executor and the reviewer work from its plan, so a plan\n// that leaves them guessing is the planner's to fix, not theirs to make up for.\nconst repositoryGuidance: Record<CommandRole, string> = {\n\tplanner: `Start with AGENTS.md, which says where the architecture and the decisions are, and read only the parts your task needs. Name in the plan every file to change and what to change in it, so the executor needs nothing else. ${exploring} ${batchingReads}`,\n\texecutor: `Work from the plan: read the files it names, and only what you need to change them. Do not study the repository's architecture or decisions; the plan already applied them. ${batching}`,\n\treviewer: `Work from the plan and the changes: read what they touch, and only what you need to judge them. ${exploring} ${batchingReads}`,\n};\n\n/**\n * Builds the planner → executor → reviewer workflow with every role on the model APIs, each\n * holding its role's instructions, or `systemPrompts`, as its system prompt, followed by the\n * workspace's roots.\n *\n * - The planner and the reviewer read: `listFiles`, `searchText`, `readFile`, `readFiles`, `showChanges`,\n * the current task's changes as far as each may read them, and `explore`, which sends up to 4\n * read-only explorers at once on the role's provider's cheaper model, each a new agent that\n * starts from its question and works in the background while the role goes on.\n * - The executor gets its provider's file tools (see `createFileTools`), and changes files only\n * in a `write` root; `autoApprove` reaches only it.\n * - Each role has its own step limit: `maxSteps`, 80 for the executor and 65 for the others by\n * default.\n * - Each role gets `runCommand` with the `commands` whose `roles` name it, the executor by\n * default. A command asks the approver in any role, and its files are captured around it.\n * - When the executor has a command, it is told to finish only once the tests and checks pass,\n * or to say which fail, and the reviewer takes from its response whether they pass. Without\n * one, both are told the tests were not run, and the reviewer judges from the code whether\n * they would pass.\n *\n * One run of the orchestrator is one run of the workspace's history, every round and retry\n * included, and its `AgentResponse` names it. Every role follows what the user undoes.\n * Asynchronous because opening the workspace is.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider, or a workspace with no root.\n * @throws {UnrecoverableError} when a role cannot be set up, for example because\n * `OPENAI_API_KEY` is missing, or when no program can read the repository.\n */\nexport async function createLLMOrchestrator({\n\tprovider,\n\tautoApprove,\n\tsystemPrompts = {},\n\tworkspace = { roots: [{ path: process.cwd(), access: 'read' }] },\n\tmaxSteps,\n\tcompactAt,\n\tcommands,\n\tformatter,\n\tsummarizeUndone = true,\n\tlogger = new Logger(),\n\tonTranscript,\n}: CreateLLMOrchestratorOptions = {}): Promise<Agent> {\n\tconst roles = orchestratorRolesFor(provider);\n\tconst steps = perRole('maxSteps', maxSteps, defaultRoleSteps, {\n\t\tunit: 'steps',\n\t\texample: '{ \"executor\": 120 }',\n\t});\n\tconst compaction = perRole('compactAt', compactAt, defaultRoleCompaction, {\n\t\tunit: 'tokens',\n\t\texample: '{ \"executor\": 200000 }',\n\t});\n\tif (formatter !== undefined) validateFormatter(formatter);\n\tconst opened = await openWorkspace(workspace, logger, formatter ? { formatter } : {});\n\tconst guidance = workspaceGuidance(workspace.roots);\n\tconst summarizer = summarizeUndone ? summarizerFor(roles.planner.provider, logger) : undefined;\n\tconst shared = { history: opened.store, ...(summarizer ? { summarizer } : {}), logger };\n\t// A caller's own prompt replaces our instructions and guidance, not the workspace: the model\n\t// needs the roots to name a file, as `createLLMAgent` gives them.\n\tconst prompt = (role: CommandRole, own: string | undefined, instructions: string) =>\n\t\town === undefined\n\t\t\t? withGuidance(instructions, `${guidance}\\n${repositoryGuidance[role]}`)\n\t\t\t: withGuidance(own, guidance);\n\t// Each transcript names the agent it is of.\n\tconst transcriptsOf = (agent: Transcript['agent']) =>\n\t\tonTranscript && ((transcript: Transcript) => onTranscript({ ...transcript, agent }));\n\t// Every command, checked once, before any role takes its share.\n\tif (commands !== undefined) validateCommands(commands);\n\t// A new explorer for each question, on the role's provider: it starts from the question alone.\n\tconst explorerToolset = explorerTools(opened);\n\tconst explorer = (provider: AgentProvider) => () =>\n\t\tbuildLLMAgent(provider, {\n\t\t\t...explorerRoles[provider],\n\t\t\tsystemPrompt: withGuidance(explorerInstructions, guidance),\n\t\t\ttools: explorerToolset,\n\t\t\tmaxSteps: explorerSteps,\n\t\t\tlogger,\n\t\t\tonTranscript: transcriptsOf('explorer'),\n\t\t});\n\tconst reader = async (\n\t\t{ provider, model, reasoningEffort }: Role,\n\t\trole: CommandRole,\n\t\tsystemPrompt: string,\n\t) =>\n\t\tbuildLLMAgent(provider, {\n\t\t\tmodel,\n\t\t\treasoningEffort,\n\t\t\tsystemPrompt,\n\t\t\ttools: await readingTools(opened, role, commands, explorer(provider)),\n\t\t\tmaxSteps: steps[role],\n\t\t\tcompactAt: compaction[role],\n\t\t\tonTranscript: transcriptsOf(role),\n\t\t\t...shared,\n\t\t});\n\tconst { executor } = roles;\n\tconst executorToolset = await executorTools(\n\t\texecutor.provider,\n\t\topened,\n\t\tcommands && commandsFor(commands, 'executor'),\n\t);\n\t// The executor and the reviewer are told whether the tests were run, which only an executor\n\t// with a command can do.\n\tconst executorRuns = executorToolset.some(tool => tool.name === 'runCommand');\n\n\treturn new OrchestratorAgent({\n\t\tplannerAgent: await reader(\n\t\t\troles.planner,\n\t\t\t'planner',\n\t\t\tprompt('planner', systemPrompts.planner, plannerInstructions),\n\t\t),\n\t\texecutorAgent: buildLLMAgent(executor.provider, {\n\t\t\tmodel: executor.model,\n\t\t\treasoningEffort: executor.reasoningEffort,\n\t\t\tsystemPrompt: prompt(\n\t\t\t\t'executor',\n\t\t\t\tsystemPrompts.executor,\n\t\t\t\texecutorRuns ? executorInstructions : executorInstructionsWithoutCommands,\n\t\t\t),\n\t\t\ttools: executorToolset,\n\t\t\tmaxSteps: steps.executor,\n\t\t\tcompactAt: compaction.executor,\n\t\t\tautoApprove,\n\t\t\tonTranscript: transcriptsOf('executor'),\n\t\t\t...shared,\n\t\t}),\n\t\treviewerAgent: await reader(\n\t\t\troles.reviewer,\n\t\t\t'reviewer',\n\t\t\tprompt(\n\t\t\t\t'reviewer',\n\t\t\t\tsystemPrompts.reviewer,\n\t\t\t\texecutorRuns ? reviewerInstructions : reviewerInstructionsWithoutCommands,\n\t\t\t),\n\t\t),\n\t\treviewerDecisionValidator: new ReviewerDecisionValidator(),\n\t\tlogger,\n\t});\n}\n"]}
|
|
@@ -69,18 +69,54 @@ export declare class RunEndingToolError extends Error {
|
|
|
69
69
|
export interface PreparingTool extends ToolDefinition {
|
|
70
70
|
/** Describes the model's input without exposing preparation details to the provider. */
|
|
71
71
|
summarize?: ToolSummarizer;
|
|
72
|
-
/**
|
|
73
|
-
* Its calls run at the same time as the other calls of their step whose tool is `parallel`,
|
|
74
|
-
* such as agents a parent delegates to. Every other call runs alone, in order.
|
|
75
|
-
*/
|
|
76
|
-
readonly parallel?: true;
|
|
77
72
|
/** Rejects with a message for the model when the call cannot run. */
|
|
78
73
|
prepare(input: unknown, signal: AbortSignal, call: ToolCallContext): Promise<PreparedCall>;
|
|
79
74
|
}
|
|
75
|
+
/** What an agent a call handed a task to answered, for the model that sent it. */
|
|
76
|
+
export interface DelegatedAnswer {
|
|
77
|
+
readonly text: string;
|
|
78
|
+
/** It failed, and `text` says why. */
|
|
79
|
+
readonly failed?: true;
|
|
80
|
+
}
|
|
81
|
+
/** An agent a call handed a task to, working in the background until it answers. */
|
|
82
|
+
export interface Delegated {
|
|
83
|
+
/** Which agent it is, as its `subagent` events name it: `explorer`, or the tool's name. */
|
|
84
|
+
readonly name: string;
|
|
85
|
+
/** Its number among the agents of its call, from 1, as its `subagent` events carry it. */
|
|
86
|
+
readonly subagent: number;
|
|
87
|
+
/** The task it was given, as the model wrote it. */
|
|
88
|
+
readonly task: string;
|
|
89
|
+
/**
|
|
90
|
+
* Its answer for the model that sent it, or why it failed. It rejects only when the run was
|
|
91
|
+
* cancelled, or with a `RunEndingToolError`.
|
|
92
|
+
*/
|
|
93
|
+
readonly answer: Promise<DelegatedAnswer>;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* A call that hands tasks to agents, checked before anyone approves it. Once approved, `start`
|
|
97
|
+
* sends them and the call answers at once: they work in the background, and each one's answer
|
|
98
|
+
* reaches the model when it finishes.
|
|
99
|
+
*/
|
|
100
|
+
export interface PreparedDelegation {
|
|
101
|
+
readonly risk: ToolRisk;
|
|
102
|
+
/** The agents may run a consumer's tools, whose changes the history does not record. */
|
|
103
|
+
readonly unrecorded?: true;
|
|
104
|
+
start(signal: AbortSignal): readonly Delegated[];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A tool built by the harness whose calls hand tasks to agents working in the background, such
|
|
108
|
+
* as `explore`. Internal.
|
|
109
|
+
*/
|
|
110
|
+
export interface DelegatingTool extends ToolDefinition {
|
|
111
|
+
summarize?: ToolSummarizer;
|
|
112
|
+
/** Rejects with a message for the model when the tasks cannot be handed over. */
|
|
113
|
+
delegate(input: unknown, signal: AbortSignal, call: ToolCallContext): Promise<PreparedDelegation>;
|
|
114
|
+
}
|
|
80
115
|
/** What an agent can run: a consumer's `Tool`, or one the harness built. */
|
|
81
|
-
export type AgentTool = Tool | PreparingTool;
|
|
116
|
+
export type AgentTool = Tool | PreparingTool | DelegatingTool;
|
|
117
|
+
export declare function isDelegating(tool: AgentTool): tool is DelegatingTool;
|
|
82
118
|
/**
|
|
83
119
|
* Brings any tool into the one lifecycle of prepare, approve, run. A consumer's `Tool` has its
|
|
84
120
|
* risk judged now, and later runs on the input as the model sent it.
|
|
85
121
|
*/
|
|
86
|
-
export declare function prepareCall(tool:
|
|
122
|
+
export declare function prepareCall(tool: Tool | PreparingTool, input: unknown, signal: AbortSignal, call: ToolCallContext): Promise<PreparedCall>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preparedCall.js","sourceRoot":"","sources":["../../../src/tools/domain/preparedCall.ts"],"names":[],"mappings":"AA+CA;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACnC,QAAQ,CAAqB;IAEtC,YAAY,OAAe,EAAE,EAAE,QAAQ,KAA4B,EAAE;QACpE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACnC,OAAO,CAAU;IAE1B,YAAY,OAAgB;QAC3B,KAAK,CAAC,2CAA2C,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD;
|
|
1
|
+
{"version":3,"file":"preparedCall.js","sourceRoot":"","sources":["../../../src/tools/domain/preparedCall.ts"],"names":[],"mappings":"AA+CA;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACnC,QAAQ,CAAqB;IAEtC,YAAY,OAAe,EAAE,EAAE,QAAQ,KAA4B,EAAE;QACpE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACnC,OAAO,CAAU;IAE1B,YAAY,OAAgB;QAC3B,KAAK,CAAC,2CAA2C,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD;AA4DD,MAAM,UAAU,YAAY,CAAC,IAAe;IAC3C,OAAO,UAAU,IAAI,IAAI,CAAC;AAC3B,CAAC;AAED,SAAS,WAAW,CAAC,IAAe;IACnC,OAAO,SAAS,IAAI,IAAI,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,IAA0B,EAC1B,KAAc,EACd,MAAmB,EACnB,IAAqB;IAErB,IAAI,WAAW,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAEhE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;AACrF,CAAC","sourcesContent":["import type { CommandLine, ToolRisk } from '#src/agent/domain/approval';\nimport type { ToolDefinition } from '#src/llm/domain/tool';\nimport type { ToolCallContext } from './readRegistry.ts';\nimport type { Tool, ToolSummarizer } from './tool.ts';\n\n/** How a configured command ended, for telling a command run again for nothing. */\nexport interface CommandEnding {\n\t/** It exited with code 0. */\n\tpassed: boolean;\n\t/** How it ended, such as \"exited with code 1\" or \"ran past its time limit\". */\n\thow: string;\n\t/** What it printed, or the end of it, without colors, as the user is shown it. */\n\toutput: string;\n\t/**\n\t * A hash of everything it printed, line by line, without colors or the times a known test\n\t * runner adds: what tells two endings apart.\n\t */\n\tfingerprint: string;\n\t/**\n\t * What the files the run changed held when it ended, as `RunJournal.contentState` gives it.\n\t * Missing when it changed something the history could not record.\n\t */\n\tstate?: string;\n\t/** The file of every change the run had applied by then, in order, as the model names it. */\n\tchanged: readonly string[];\n}\n\n/**\n * A tool call checked and fixed before anyone approves it: its risk is judged on what will\n * really happen, and `run` does exactly that, nothing worked out again.\n */\nexport interface PreparedCall {\n\treadonly risk: ToolRisk;\n\t/** For a change to a file, what it will change as a unified diff, fixed when prepared. */\n\treadonly diff?: string;\n\t/** For a call that runs a configured command, what it will run, fixed when prepared. */\n\treadonly command?: CommandLine;\n\t/**\n\t * For a call that runs a configured command, how it ended once it has. `undefined` before it\n\t * runs, and when it never did.\n\t */\n\treadonly ending?: () => CommandEnding | undefined;\n\t/** A consumer's call: whatever it changes, the history does not record. */\n\treadonly unrecorded?: true;\n\trun(signal: AbortSignal): Promise<string>;\n}\n\n/**\n * A tool ran and produced a result the model should see as an error. Internal tools use this\n * instead of a plain error when the result also carries narrative metadata, such as a command's\n * non-zero exit code.\n */\nexport class ToolExecutionError extends Error {\n\treadonly exitCode: number | undefined;\n\n\tconstructor(message: string, { exitCode }: { exitCode?: number } = {}) {\n\t\tsuper(message);\n\t\tthis.exitCode = exitCode;\n\t}\n}\n\n/**\n * A failure inside a call that ends the run instead of the call, such as an approver that failed\n * while an agent the call started was asking it: host code failed, and the model must not carry\n * on as if a tool had. Internal.\n */\nexport class RunEndingToolError extends Error {\n\treadonly failure: unknown;\n\n\tconstructor(failure: unknown) {\n\t\tsuper('A failure inside a tool call ends the run');\n\t\tthis.failure = failure;\n\t}\n}\n\n/**\n * A tool built by the harness, such as a write tool, which prepares each call against the\n * state of the run before it is approved. Internal: consumers build a `Tool`.\n */\nexport interface PreparingTool extends ToolDefinition {\n\t/** Describes the model's input without exposing preparation details to the provider. */\n\tsummarize?: ToolSummarizer;\n\t/** Rejects with a message for the model when the call cannot run. */\n\tprepare(input: unknown, signal: AbortSignal, call: ToolCallContext): Promise<PreparedCall>;\n}\n\n/** What an agent a call handed a task to answered, for the model that sent it. */\nexport interface DelegatedAnswer {\n\treadonly text: string;\n\t/** It failed, and `text` says why. */\n\treadonly failed?: true;\n}\n\n/** An agent a call handed a task to, working in the background until it answers. */\nexport interface Delegated {\n\t/** Which agent it is, as its `subagent` events name it: `explorer`, or the tool's name. */\n\treadonly name: string;\n\t/** Its number among the agents of its call, from 1, as its `subagent` events carry it. */\n\treadonly subagent: number;\n\t/** The task it was given, as the model wrote it. */\n\treadonly task: string;\n\t/**\n\t * Its answer for the model that sent it, or why it failed. It rejects only when the run was\n\t * cancelled, or with a `RunEndingToolError`.\n\t */\n\treadonly answer: Promise<DelegatedAnswer>;\n}\n\n/**\n * A call that hands tasks to agents, checked before anyone approves it. Once approved, `start`\n * sends them and the call answers at once: they work in the background, and each one's answer\n * reaches the model when it finishes.\n */\nexport interface PreparedDelegation {\n\treadonly risk: ToolRisk;\n\t/** The agents may run a consumer's tools, whose changes the history does not record. */\n\treadonly unrecorded?: true;\n\tstart(signal: AbortSignal): readonly Delegated[];\n}\n\n/**\n * A tool built by the harness whose calls hand tasks to agents working in the background, such\n * as `explore`. Internal.\n */\nexport interface DelegatingTool extends ToolDefinition {\n\tsummarize?: ToolSummarizer;\n\t/** Rejects with a message for the model when the tasks cannot be handed over. */\n\tdelegate(input: unknown, signal: AbortSignal, call: ToolCallContext): Promise<PreparedDelegation>;\n}\n\n/** What an agent can run: a consumer's `Tool`, or one the harness built. */\nexport type AgentTool = Tool | PreparingTool | DelegatingTool;\n\nexport function isDelegating(tool: AgentTool): tool is DelegatingTool {\n\treturn 'delegate' in tool;\n}\n\nfunction isPreparing(tool: AgentTool): tool is PreparingTool {\n\treturn 'prepare' in tool;\n}\n\n/**\n * Brings any tool into the one lifecycle of prepare, approve, run. A consumer's `Tool` has its\n * risk judged now, and later runs on the input as the model sent it.\n */\nexport async function prepareCall(\n\ttool: Tool | PreparingTool,\n\tinput: unknown,\n\tsignal: AbortSignal,\n\tcall: ToolCallContext,\n): Promise<PreparedCall> {\n\tif (isPreparing(tool)) return tool.prepare(input, signal, call);\n\n\tconst risk = tool.risk(input);\n\treturn { risk, unrecorded: true, run: runSignal => tool.execute(input, runSignal) };\n}\n"]}
|
|
@@ -35,22 +35,24 @@ export interface AgentAsToolOptions {
|
|
|
35
35
|
maxDepth?: number;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
* Offers an agent to another agent as a tool. The calling model writes the task
|
|
39
|
-
* it as part of the caller's run,
|
|
38
|
+
* Offers an agent to another agent as a tool. The calling model writes the task, and the call
|
|
39
|
+
* answers at once: the agent works on it in the background, as part of the caller's run, while
|
|
40
|
+
* the caller keeps working. Its answer reaches the caller's model in a message of its own once it
|
|
41
|
+
* finishes, and nothing else of its work does:
|
|
40
42
|
*
|
|
41
43
|
* - its changes go into the same run of the workspace's history, so one undo reverts both, and
|
|
42
44
|
* each agent keeps its own tools' access policy and its own reads;
|
|
43
45
|
* - what it spends counts in the caller's `tokens`, a failed attempt included;
|
|
44
|
-
* - its progress
|
|
45
|
-
* call in `delegation`;
|
|
46
|
+
* - its progress reaches the consumer as `subagent` events of the call, and a transcript it gives
|
|
47
|
+
* names the call in `delegation`;
|
|
46
48
|
* - it is asked and approved through the run's `ask` and `approve`. Delegating never grants
|
|
47
49
|
* `autoApprove`: the agent has it only if the `createAgent` option gave it.
|
|
48
50
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
51
|
+
* The caller's run ends only once every agent it sent has finished. Every change and command of
|
|
52
|
+
* the run is made one at a time, so the history stays exact, but agents working at once can see
|
|
53
|
+
* each other's unfinished work. An agent that fails answers with why, for the model to act on; a
|
|
54
|
+
* cancellation, or a run's approver or asker that failed inside it, ends the run and stops every
|
|
55
|
+
* agent still working.
|
|
54
56
|
*
|
|
55
57
|
* Only for agents on the model APIs, from `createLLMAgent`: an Agent SDK agent from the
|
|
56
58
|
* `createAgent` factory runs as its own run, outside these guarantees.
|
|
@@ -5,27 +5,29 @@ import { InvalidAgentConfigError, RecoverableError, UnrecoverableError, withSpen
|
|
|
5
5
|
import { isAbortError } from '#src/shared/domain/isAbortError';
|
|
6
6
|
import { classifyHostFailure } from '#src/shared/domain/providerFailure';
|
|
7
7
|
import { RunEndingToolError } from "../domain/preparedCall.js";
|
|
8
|
-
import {
|
|
8
|
+
import { defineDelegatingTool } from "./defineTool.js";
|
|
9
9
|
import { cutAnswer, failureOf, subagentOptions } from "./subagents.js";
|
|
10
10
|
/** How deep agents may delegate unless a tool says otherwise: planner → coder → committer. */
|
|
11
11
|
export const defaultMaxDepth = 2;
|
|
12
12
|
/**
|
|
13
|
-
* Offers an agent to another agent as a tool. The calling model writes the task
|
|
14
|
-
* it as part of the caller's run,
|
|
13
|
+
* Offers an agent to another agent as a tool. The calling model writes the task, and the call
|
|
14
|
+
* answers at once: the agent works on it in the background, as part of the caller's run, while
|
|
15
|
+
* the caller keeps working. Its answer reaches the caller's model in a message of its own once it
|
|
16
|
+
* finishes, and nothing else of its work does:
|
|
15
17
|
*
|
|
16
18
|
* - its changes go into the same run of the workspace's history, so one undo reverts both, and
|
|
17
19
|
* each agent keeps its own tools' access policy and its own reads;
|
|
18
20
|
* - what it spends counts in the caller's `tokens`, a failed attempt included;
|
|
19
|
-
* - its progress
|
|
20
|
-
* call in `delegation`;
|
|
21
|
+
* - its progress reaches the consumer as `subagent` events of the call, and a transcript it gives
|
|
22
|
+
* names the call in `delegation`;
|
|
21
23
|
* - it is asked and approved through the run's `ask` and `approve`. Delegating never grants
|
|
22
24
|
* `autoApprove`: the agent has it only if the `createAgent` option gave it.
|
|
23
25
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* The caller's run ends only once every agent it sent has finished. Every change and command of
|
|
27
|
+
* the run is made one at a time, so the history stays exact, but agents working at once can see
|
|
28
|
+
* each other's unfinished work. An agent that fails answers with why, for the model to act on; a
|
|
29
|
+
* cancellation, or a run's approver or asker that failed inside it, ends the run and stops every
|
|
30
|
+
* agent still working.
|
|
29
31
|
*
|
|
30
32
|
* Only for agents on the model APIs, from `createLLMAgent`: an Agent SDK agent from the
|
|
31
33
|
* `createAgent` factory runs as its own run, outside these guarantees.
|
|
@@ -36,35 +38,32 @@ export function agentAsTool({ name, description, createAgent, risk = 'mutating',
|
|
|
36
38
|
if (!Number.isInteger(maxDepth) || maxDepth < 1) {
|
|
37
39
|
throw new InvalidAgentConfigError(`maxDepth of "${name}" must be a positive integer; got ${String(maxDepth)}`);
|
|
38
40
|
}
|
|
39
|
-
const tool = {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
.describe('The whole task. The agent starts from it alone, so say what to do and what to report back.'),
|
|
47
|
-
}),
|
|
48
|
-
summarize: ({ task }) => task,
|
|
49
|
-
prepare: ({ task }, _, call) => {
|
|
50
|
-
const asked = task.trim();
|
|
51
|
-
if (asked === '')
|
|
52
|
-
return Promise.reject(new Error('The task needs some text.'));
|
|
53
|
-
if (call.depth >= maxDepth) {
|
|
54
|
-
return Promise.reject(new Error(`"${name}" may run at most ${String(maxDepth)} delegations deep, and this agent already runs ${String(call.depth)} deep. Do the work yourself, or answer with what you have.`));
|
|
55
|
-
}
|
|
56
|
-
return Promise.resolve({
|
|
57
|
-
risk,
|
|
58
|
-
// What the agent changes is in the history, but it may run tools of the consumer's
|
|
59
|
-
// that change what the history never sees.
|
|
60
|
-
unrecorded: true,
|
|
61
|
-
run: signal => delegate(asked, signal, call),
|
|
62
|
-
});
|
|
63
|
-
},
|
|
41
|
+
const tool = defineDelegatingTool({
|
|
42
|
+
name,
|
|
43
|
+
description,
|
|
44
|
+
input: z.object({
|
|
45
|
+
task: z
|
|
46
|
+
.string()
|
|
47
|
+
.describe('The whole task. The agent starts from it alone, so say what to do and what to report back.'),
|
|
64
48
|
}),
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
49
|
+
summarize: ({ task }) => task,
|
|
50
|
+
delegate: ({ task }, _, call) => {
|
|
51
|
+
const asked = task.trim();
|
|
52
|
+
if (asked === '')
|
|
53
|
+
return Promise.reject(new Error('The task needs some text.'));
|
|
54
|
+
if (call.depth >= maxDepth) {
|
|
55
|
+
return Promise.reject(new Error(`"${name}" may run at most ${String(maxDepth)} delegations deep, and this agent already runs ${String(call.depth)} deep. Do the work yourself, or answer with what you have.`));
|
|
56
|
+
}
|
|
57
|
+
return Promise.resolve({
|
|
58
|
+
risk,
|
|
59
|
+
// What the agent changes is in the history, but it may run tools of the consumer's
|
|
60
|
+
// that change what the history never sees.
|
|
61
|
+
unrecorded: true,
|
|
62
|
+
start: signal => [{ name, subagent: 1, task: asked, answer: hand(asked, signal, call) }],
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
async function hand(task, signal, call) {
|
|
68
67
|
// The run's approver and asker are host code: one that fails inside the agent ends the
|
|
69
68
|
// run, not just the agent's task.
|
|
70
69
|
const failed = { host: false };
|
|
@@ -89,7 +88,7 @@ export function agentAsTool({ name, description, createAgent, risk = 'mutating',
|
|
|
89
88
|
try {
|
|
90
89
|
const { response, tokens } = await agent.run(task, options);
|
|
91
90
|
call.spend(tokens, tokens === undefined);
|
|
92
|
-
return cutAnswer(response || 'It finished without an answer.');
|
|
91
|
+
return { text: cutAnswer(response || 'It finished without an answer.') };
|
|
93
92
|
}
|
|
94
93
|
catch (error) {
|
|
95
94
|
if (isAbortError(error))
|
|
@@ -103,7 +102,7 @@ export function agentAsTool({ name, description, createAgent, risk = 'mutating',
|
|
|
103
102
|
throw new RunEndingToolError(withSpentTokens(classifyHostFailure(error, `The agent for "${name}" failed`), undefined, true));
|
|
104
103
|
}
|
|
105
104
|
call.spend(error.tokens, error.usageUnreported);
|
|
106
|
-
|
|
105
|
+
return { text: `The agent failed: ${failureOf(error)}`, failed: true };
|
|
107
106
|
}
|
|
108
107
|
}
|
|
109
108
|
// A file tool's kind of brand: the harness built it, and only `createLLMAgent` takes it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentAsTool.js","sourceRoot":"","sources":["../../../src/tools/infrastructure/agentAsTool.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport type { Agent, RunOptions } from '#src/agent/domain/agent';\nimport { type Approver, readDecision, type ToolRisk } from '#src/agent/domain/approval';\nimport { type Asker, readAnswers } from '#src/agent/domain/question';\nimport {\n\tInvalidAgentConfigError,\n\tRecoverableError,\n\tUnrecoverableError,\n\twithSpentTokens,\n} from '#src/shared/domain/errors';\nimport { isAbortError } from '#src/shared/domain/isAbortError';\nimport { classifyHostFailure } from '#src/shared/domain/providerFailure';\nimport type { ToolDefinition } from '#src/llm/domain/tool';\nimport { type PreparingTool, RunEndingToolError } from '../domain/preparedCall.ts';\nimport type { ToolCallContext } from '../domain/readRegistry.ts';\nimport { definePreparingTool } from './defineTool.ts';\nimport { cutAnswer, failureOf, subagentOptions } from './subagents.ts';\n\ndeclare const delegationToolBrand: unique symbol;\n\n/**\n * A tool from `agentAsTool`, which hands a task to another agent. It goes to an agent from\n * `createLLMAgent` beside its other tools; what it does inside is the harness's.\n */\nexport type DelegationTool = ToolDefinition & { readonly [delegationToolBrand]: true };\n\n/** How deep agents may delegate unless a tool says otherwise: planner → coder → committer. */\nexport const defaultMaxDepth = 2;\n\nexport interface AgentAsToolOptions {\n\t/** The name the model calls it by, such as `commit`. */\n\tname: string;\n\t/** What the agent does and when to hand it a task, for the model that may call it. */\n\tdescription: string;\n\t/**\n\t * A new agent for each call, such as one from `createLLMAgent`: it starts from the task alone\n\t * and never shares a conversation with another call.\n\t */\n\tcreateAgent: () => Agent;\n\t/**\n\t * How the call itself is judged before it runs. `mutating` unless given: handing over a task\n\t * asks no one, and the agent's own `destructive` calls are approved through the run's\n\t * `approve`, as the calling agent's would be. `destructive` asks before every task is handed\n\t * over.\n\t */\n\trisk?: ToolRisk;\n\t/**\n\t * How many delegations deep the agent may run, 1 for one the top-level agent calls. A call\n\t * that would go deeper is refused, and the model is told why. Defaults to 2.\n\t */\n\tmaxDepth?: number;\n}\n\n/**\n * Offers an agent to another agent as a tool. The calling model writes the task; the agent runs\n * it as part of the caller's run, and its answer is the call's result:\n *\n * - its changes go into the same run of the workspace's history, so one undo reverts both, and\n * each agent keeps its own tools' access policy and its own reads;\n * - what it spends counts in the caller's `tokens`, a failed attempt included;\n * - its progress arrives as `subagent` events of the call, and a transcript it gives names the\n * call in `delegation`;\n * - it is asked and approved through the run's `ask` and `approve`. Delegating never grants\n * `autoApprove`: the agent has it only if the `createAgent` option gave it.\n *\n * Calls of these tools next to each other in one step run at once, and any other call runs\n * alone. Every change and command of the run is made one at a time, so the history stays exact,\n * but agents working at once can see each other's unfinished work. An agent that fails is the\n * call's error result, for the model to act on; a cancellation, or a run's approver or asker that\n * failed inside it, ends the run.\n *\n * Only for agents on the model APIs, from `createLLMAgent`: an Agent SDK agent from the\n * `createAgent` factory runs as its own run, outside these guarantees.\n *\n * @throws {InvalidAgentConfigError} when `maxDepth` is not a positive integer.\n */\nexport function agentAsTool({\n\tname,\n\tdescription,\n\tcreateAgent,\n\trisk = 'mutating',\n\tmaxDepth = defaultMaxDepth,\n}: AgentAsToolOptions): DelegationTool {\n\tif (!Number.isInteger(maxDepth) || maxDepth < 1) {\n\t\tthrow new InvalidAgentConfigError(\n\t\t\t`maxDepth of \"${name}\" must be a positive integer; got ${String(maxDepth)}`,\n\t\t);\n\t}\n\tconst tool: PreparingTool = {\n\t\t...definePreparingTool({\n\t\t\tname,\n\t\t\tdescription,\n\t\t\tinput: z.object({\n\t\t\t\ttask: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.describe(\n\t\t\t\t\t\t'The whole task. The agent starts from it alone, so say what to do and what to report back.',\n\t\t\t\t\t),\n\t\t\t}),\n\t\t\tsummarize: ({ task }) => task,\n\t\t\tprepare: ({ task }, _, call) => {\n\t\t\t\tconst asked = task.trim();\n\t\t\t\tif (asked === '') return Promise.reject(new Error('The task needs some text.'));\n\t\t\t\tif (call.depth >= maxDepth) {\n\t\t\t\t\treturn Promise.reject(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`\"${name}\" may run at most ${String(maxDepth)} delegations deep, and this agent already runs ${String(call.depth)} deep. Do the work yourself, or answer with what you have.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn Promise.resolve({\n\t\t\t\t\trisk,\n\t\t\t\t\t// What the agent changes is in the history, but it may run tools of the consumer's\n\t\t\t\t\t// that change what the history never sees.\n\t\t\t\t\tunrecorded: true,\n\t\t\t\t\trun: signal => delegate(asked, signal, call),\n\t\t\t\t});\n\t\t\t},\n\t\t}),\n\t\tparallel: true,\n\t};\n\n\tasync function delegate(task: string, signal: AbortSignal, call: ToolCallContext) {\n\t\t// The run's approver and asker are host code: one that fails inside the agent ends the\n\t\t// run, not just the agent's task.\n\t\tconst failed = { host: false };\n\t\tconst options = subagentOptions(call, {\n\t\t\ttool: name,\n\t\t\tname,\n\t\t\tsubagent: 1,\n\t\t\ttask,\n\t\t\toptions: {\n\t\t\t\tsignal,\n\t\t\t\t...(call.approve ? { approve: watchedApprover(call.approve, failed) } : {}),\n\t\t\t\t...(call.ask ? { ask: watchedAsker(call.ask, failed) } : {}),\n\t\t\t} satisfies RunOptions,\n\t\t});\n\n\t\tlet agent: Agent;\n\t\ttry {\n\t\t\tagent = createAgent();\n\t\t} catch (error) {\n\t\t\tthrow new RunEndingToolError(\n\t\t\t\tclassifyHostFailure(error, `The agent for \"${name}\" could not be created`),\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tconst { response, tokens } = await agent.run(task, options);\n\t\t\tcall.spend(tokens, tokens === undefined);\n\t\t\treturn cutAnswer(response || 'It finished without an answer.');\n\t\t} catch (error) {\n\t\t\tif (isAbortError(error)) throw error;\n\t\t\tconst classified = error instanceof RecoverableError || error instanceof UnrecoverableError;\n\t\t\t// Its failure carries what it spent, which the run's failure keeps.\n\t\t\tif (classified && failed.host) throw new RunEndingToolError(error);\n\t\t\tif (!classified) {\n\t\t\t\t// It broke the contract of `Agent`, so what it spent is unknown, not nothing.\n\t\t\t\tthrow new RunEndingToolError(\n\t\t\t\t\twithSpentTokens(\n\t\t\t\t\t\tclassifyHostFailure(error, `The agent for \"${name}\" failed`),\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tcall.spend(error.tokens, error.usageUnreported);\n\t\t\tthrow new Error(`The agent failed: ${failureOf(error)}`, { cause: error });\n\t\t}\n\t}\n\n\t// A file tool's kind of brand: the harness built it, and only `createLLMAgent` takes it.\n\treturn tool as unknown as DelegationTool;\n}\n\n/** `approve`, noting in `failed` when it throws or answers with no decision. */\nfunction watchedApprover(approve: Approver, failed: { host: boolean }): Approver {\n\treturn async (request, signal) => {\n\t\ttry {\n\t\t\tconst answer = await approve(request, signal);\n\t\t\treadDecision(answer);\n\t\t\treturn answer;\n\t\t} catch (error) {\n\t\t\t// One that gives up on a cancellation did not fail.\n\t\t\tif (!signal.aborted) failed.host = true;\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n/** `ask`, noting in `failed` when it throws or answers in a shape no agent accepts. */\nfunction watchedAsker(ask: Asker, failed: { host: boolean }): Asker {\n\treturn async (questions, signal) => {\n\t\ttry {\n\t\t\tconst answers = await ask(questions, signal);\n\t\t\tif (!readAnswers(answers, questions)) failed.host = true;\n\t\t\treturn answers;\n\t\t} catch (error) {\n\t\t\tif (!signal.aborted) failed.host = true;\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agentAsTool.js","sourceRoot":"","sources":["../../../src/tools/infrastructure/agentAsTool.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport type { Agent, RunOptions } from '#src/agent/domain/agent';\nimport { type Approver, readDecision, type ToolRisk } from '#src/agent/domain/approval';\nimport { type Asker, readAnswers } from '#src/agent/domain/question';\nimport {\n\tInvalidAgentConfigError,\n\tRecoverableError,\n\tUnrecoverableError,\n\twithSpentTokens,\n} from '#src/shared/domain/errors';\nimport { isAbortError } from '#src/shared/domain/isAbortError';\nimport { classifyHostFailure } from '#src/shared/domain/providerFailure';\nimport type { ToolDefinition } from '#src/llm/domain/tool';\nimport { type DelegatedAnswer, RunEndingToolError } from '../domain/preparedCall.ts';\nimport type { ToolCallContext } from '../domain/readRegistry.ts';\nimport { defineDelegatingTool } from './defineTool.ts';\nimport { cutAnswer, failureOf, subagentOptions } from './subagents.ts';\n\ndeclare const delegationToolBrand: unique symbol;\n\n/**\n * A tool from `agentAsTool`, which hands a task to another agent. It goes to an agent from\n * `createLLMAgent` beside its other tools; what it does inside is the harness's.\n */\nexport type DelegationTool = ToolDefinition & { readonly [delegationToolBrand]: true };\n\n/** How deep agents may delegate unless a tool says otherwise: planner → coder → committer. */\nexport const defaultMaxDepth = 2;\n\nexport interface AgentAsToolOptions {\n\t/** The name the model calls it by, such as `commit`. */\n\tname: string;\n\t/** What the agent does and when to hand it a task, for the model that may call it. */\n\tdescription: string;\n\t/**\n\t * A new agent for each call, such as one from `createLLMAgent`: it starts from the task alone\n\t * and never shares a conversation with another call.\n\t */\n\tcreateAgent: () => Agent;\n\t/**\n\t * How the call itself is judged before it runs. `mutating` unless given: handing over a task\n\t * asks no one, and the agent's own `destructive` calls are approved through the run's\n\t * `approve`, as the calling agent's would be. `destructive` asks before every task is handed\n\t * over.\n\t */\n\trisk?: ToolRisk;\n\t/**\n\t * How many delegations deep the agent may run, 1 for one the top-level agent calls. A call\n\t * that would go deeper is refused, and the model is told why. Defaults to 2.\n\t */\n\tmaxDepth?: number;\n}\n\n/**\n * Offers an agent to another agent as a tool. The calling model writes the task, and the call\n * answers at once: the agent works on it in the background, as part of the caller's run, while\n * the caller keeps working. Its answer reaches the caller's model in a message of its own once it\n * finishes, and nothing else of its work does:\n *\n * - its changes go into the same run of the workspace's history, so one undo reverts both, and\n * each agent keeps its own tools' access policy and its own reads;\n * - what it spends counts in the caller's `tokens`, a failed attempt included;\n * - its progress reaches the consumer as `subagent` events of the call, and a transcript it gives\n * names the call in `delegation`;\n * - it is asked and approved through the run's `ask` and `approve`. Delegating never grants\n * `autoApprove`: the agent has it only if the `createAgent` option gave it.\n *\n * The caller's run ends only once every agent it sent has finished. Every change and command of\n * the run is made one at a time, so the history stays exact, but agents working at once can see\n * each other's unfinished work. An agent that fails answers with why, for the model to act on; a\n * cancellation, or a run's approver or asker that failed inside it, ends the run and stops every\n * agent still working.\n *\n * Only for agents on the model APIs, from `createLLMAgent`: an Agent SDK agent from the\n * `createAgent` factory runs as its own run, outside these guarantees.\n *\n * @throws {InvalidAgentConfigError} when `maxDepth` is not a positive integer.\n */\nexport function agentAsTool({\n\tname,\n\tdescription,\n\tcreateAgent,\n\trisk = 'mutating',\n\tmaxDepth = defaultMaxDepth,\n}: AgentAsToolOptions): DelegationTool {\n\tif (!Number.isInteger(maxDepth) || maxDepth < 1) {\n\t\tthrow new InvalidAgentConfigError(\n\t\t\t`maxDepth of \"${name}\" must be a positive integer; got ${String(maxDepth)}`,\n\t\t);\n\t}\n\tconst tool = defineDelegatingTool({\n\t\tname,\n\t\tdescription,\n\t\tinput: z.object({\n\t\t\ttask: z\n\t\t\t\t.string()\n\t\t\t\t.describe(\n\t\t\t\t\t'The whole task. The agent starts from it alone, so say what to do and what to report back.',\n\t\t\t\t),\n\t\t}),\n\t\tsummarize: ({ task }) => task,\n\t\tdelegate: ({ task }, _, call) => {\n\t\t\tconst asked = task.trim();\n\t\t\tif (asked === '') return Promise.reject(new Error('The task needs some text.'));\n\t\t\tif (call.depth >= maxDepth) {\n\t\t\t\treturn Promise.reject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`\"${name}\" may run at most ${String(maxDepth)} delegations deep, and this agent already runs ${String(call.depth)} deep. Do the work yourself, or answer with what you have.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn Promise.resolve({\n\t\t\t\trisk,\n\t\t\t\t// What the agent changes is in the history, but it may run tools of the consumer's\n\t\t\t\t// that change what the history never sees.\n\t\t\t\tunrecorded: true,\n\t\t\t\tstart: signal => [{ name, subagent: 1, task: asked, answer: hand(asked, signal, call) }],\n\t\t\t});\n\t\t},\n\t});\n\n\tasync function hand(\n\t\ttask: string,\n\t\tsignal: AbortSignal,\n\t\tcall: ToolCallContext,\n\t): Promise<DelegatedAnswer> {\n\t\t// The run's approver and asker are host code: one that fails inside the agent ends the\n\t\t// run, not just the agent's task.\n\t\tconst failed = { host: false };\n\t\tconst options = subagentOptions(call, {\n\t\t\ttool: name,\n\t\t\tname,\n\t\t\tsubagent: 1,\n\t\t\ttask,\n\t\t\toptions: {\n\t\t\t\tsignal,\n\t\t\t\t...(call.approve ? { approve: watchedApprover(call.approve, failed) } : {}),\n\t\t\t\t...(call.ask ? { ask: watchedAsker(call.ask, failed) } : {}),\n\t\t\t} satisfies RunOptions,\n\t\t});\n\n\t\tlet agent: Agent;\n\t\ttry {\n\t\t\tagent = createAgent();\n\t\t} catch (error) {\n\t\t\tthrow new RunEndingToolError(\n\t\t\t\tclassifyHostFailure(error, `The agent for \"${name}\" could not be created`),\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tconst { response, tokens } = await agent.run(task, options);\n\t\t\tcall.spend(tokens, tokens === undefined);\n\t\t\treturn { text: cutAnswer(response || 'It finished without an answer.') };\n\t\t} catch (error) {\n\t\t\tif (isAbortError(error)) throw error;\n\t\t\tconst classified = error instanceof RecoverableError || error instanceof UnrecoverableError;\n\t\t\t// Its failure carries what it spent, which the run's failure keeps.\n\t\t\tif (classified && failed.host) throw new RunEndingToolError(error);\n\t\t\tif (!classified) {\n\t\t\t\t// It broke the contract of `Agent`, so what it spent is unknown, not nothing.\n\t\t\t\tthrow new RunEndingToolError(\n\t\t\t\t\twithSpentTokens(\n\t\t\t\t\t\tclassifyHostFailure(error, `The agent for \"${name}\" failed`),\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tcall.spend(error.tokens, error.usageUnreported);\n\t\t\treturn { text: `The agent failed: ${failureOf(error)}`, failed: true };\n\t\t}\n\t}\n\n\t// A file tool's kind of brand: the harness built it, and only `createLLMAgent` takes it.\n\treturn tool as unknown as DelegationTool;\n}\n\n/** `approve`, noting in `failed` when it throws or answers with no decision. */\nfunction watchedApprover(approve: Approver, failed: { host: boolean }): Approver {\n\treturn async (request, signal) => {\n\t\ttry {\n\t\t\tconst answer = await approve(request, signal);\n\t\t\treadDecision(answer);\n\t\t\treturn answer;\n\t\t} catch (error) {\n\t\t\t// One that gives up on a cancellation did not fail.\n\t\t\tif (!signal.aborted) failed.host = true;\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n/** `ask`, noting in `failed` when it throws or answers in a shape no agent accepts. */\nfunction watchedAsker(ask: Asker, failed: { host: boolean }): Asker {\n\treturn async (questions, signal) => {\n\t\ttry {\n\t\t\tconst answers = await ask(questions, signal);\n\t\t\tif (!readAnswers(answers, questions)) failed.host = true;\n\t\t\treturn answers;\n\t\t} catch (error) {\n\t\t\tif (!signal.aborted) failed.host = true;\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { ToolRisk } from '#src/agent/domain/approval';
|
|
3
|
-
import type { PreparedCall, PreparingTool } from '../domain/preparedCall.ts';
|
|
3
|
+
import type { DelegatingTool, PreparedCall, PreparedDelegation, PreparingTool } from '../domain/preparedCall.ts';
|
|
4
4
|
import type { ToolCallContext } from '../domain/readRegistry.ts';
|
|
5
5
|
import { type Tool } from '../domain/tool.ts';
|
|
6
6
|
/**
|
|
@@ -35,3 +35,16 @@ export declare function definePreparingTool<Schema extends z.ZodObject>({ name,
|
|
|
35
35
|
summarize?: (input: z.infer<Schema>) => string;
|
|
36
36
|
prepare: (input: z.infer<Schema>, signal: AbortSignal, call: ToolCallContext) => Promise<PreparedCall>;
|
|
37
37
|
}): PreparingTool;
|
|
38
|
+
/**
|
|
39
|
+
* Builds a harness tool whose calls hand tasks to agents working in the background, from a Zod
|
|
40
|
+
* schema: input that fails validation is refused before any task is handed over. Internal.
|
|
41
|
+
*
|
|
42
|
+
* @throws {InvalidAgentConfigError} when the schema falls outside what strict mode supports.
|
|
43
|
+
*/
|
|
44
|
+
export declare function defineDelegatingTool<Schema extends z.ZodObject>({ name, description, input, summarize, delegate, }: {
|
|
45
|
+
name: string;
|
|
46
|
+
description: string;
|
|
47
|
+
input: Schema;
|
|
48
|
+
summarize?: (input: z.infer<Schema>) => string;
|
|
49
|
+
delegate: (input: z.infer<Schema>, signal: AbortSignal, call: ToolCallContext) => Promise<PreparedDelegation>;
|
|
50
|
+
}): DelegatingTool;
|
|
@@ -129,4 +129,28 @@ export function definePreparingTool({ name, description, input, summarize, prepa
|
|
|
129
129
|
},
|
|
130
130
|
};
|
|
131
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Builds a harness tool whose calls hand tasks to agents working in the background, from a Zod
|
|
134
|
+
* schema: input that fails validation is refused before any task is handed over. Internal.
|
|
135
|
+
*
|
|
136
|
+
* @throws {InvalidAgentConfigError} when the schema falls outside what strict mode supports.
|
|
137
|
+
*/
|
|
138
|
+
export function defineDelegatingTool({ name, description, input, summarize, delegate, }) {
|
|
139
|
+
return {
|
|
140
|
+
name,
|
|
141
|
+
description,
|
|
142
|
+
inputSchema: strictSchema(input, name),
|
|
143
|
+
...(summarize
|
|
144
|
+
? {
|
|
145
|
+
summarize: validatedSummarizer(input, summarize),
|
|
146
|
+
}
|
|
147
|
+
: {}),
|
|
148
|
+
delegate: (raw, signal, call) => {
|
|
149
|
+
const parsed = input.safeParse(raw);
|
|
150
|
+
if (!parsed.success)
|
|
151
|
+
return Promise.reject(new Error(z.prettifyError(parsed.error)));
|
|
152
|
+
return delegate(parsed.data, signal, call);
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
132
156
|
//# sourceMappingURL=defineTool.js.map
|