@theokit/sdk 2.20.0 → 2.22.0
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/CHANGELOG.md +148 -0
- package/dist/a2a/index.cjs +673 -317
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.d.cts +2 -1
- package/dist/a2a/index.d.ts +2 -1
- package/dist/a2a/index.js +674 -318
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/subagent.d.cts +70 -1
- package/dist/a2a/subagent.d.ts +70 -1
- package/dist/a2a/types.d.cts +7 -0
- package/dist/a2a/types.d.ts +7 -0
- package/dist/agent-builder.d.ts +2 -1
- package/dist/agent-generate.d.ts +12 -0
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +5 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/theokit-client.d.cts +6 -0
- package/dist/client/theokit-client.d.ts +6 -0
- package/dist/client/types.d.cts +2 -0
- package/dist/client/types.d.ts +2 -0
- package/dist/{cron-B8fqui49.d.cts → cron-7CruUd_0.d.ts} +53 -3
- package/dist/{cron-D2yLOrk2.d.ts → cron-Bpt_1khA.d.cts} +53 -3
- package/dist/cron.cjs +654 -389
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.d.cts +3 -2
- package/dist/cron.d.ts +3 -2
- package/dist/cron.js +655 -390
- package/dist/cron.js.map +1 -1
- package/dist/{errors-5lj1EWgs.d.ts → errors-BuwwkrAk.d.ts} +2 -2
- package/dist/{errors-CE-lMBi2.d.cts → errors-CkCaIqVP.d.cts} +2 -2
- package/dist/errors.d.cts +3 -2
- package/dist/eval.cjs +654 -389
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +654 -389
- package/dist/eval.js.map +1 -1
- package/dist/generate-object.d.ts +4 -3
- package/dist/index.cjs +800 -392
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +259 -17
- package/dist/index.d.ts +259 -17
- package/dist/index.js +798 -394
- package/dist/index.js.map +1 -1
- package/dist/internal/agent-loop/loop-types.d.ts +2 -0
- package/dist/internal/agent-loop/tool-result-guard.d.ts +1 -0
- package/dist/internal/llm/tool-result-content.d.ts +40 -0
- package/dist/internal/llm/types.d.ts +6 -1
- package/dist/internal/persistence/conversation-storage-fs.d.cts +3 -1
- package/dist/internal/persistence/conversation-storage-fs.d.ts +3 -1
- package/dist/internal/persistence/conversation-storage-memory.d.cts +3 -1
- package/dist/internal/persistence/conversation-storage-memory.d.ts +3 -1
- package/dist/internal/persistence/session-meta.d.cts +13 -0
- package/dist/internal/persistence/session-meta.d.ts +13 -0
- package/dist/internal/runtime/model-selection.d.ts +14 -0
- package/dist/internal/structured-output-helpers.d.ts +1 -1
- package/dist/permission-engine.d.ts +32 -1
- package/dist/{run-BgfBWX-z.d.cts → run-CrIulPF7.d.cts} +282 -19
- package/dist/{run-BgfBWX-z.d.ts → run-CrIulPF7.d.ts} +282 -19
- package/dist/stream-object.d.ts +2 -1
- package/dist/tool-error.d.ts +30 -0
- package/dist/types/agent-prims.d.ts +30 -8
- package/dist/types/agent.d.ts +13 -2
- package/dist/types/content-blocks.d.ts +47 -0
- package/dist/types/conversation-storage.d.ts +38 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/messages.d.ts +2 -9
- package/dist/types/run-events.d.ts +84 -0
- package/dist/types/run.d.ts +115 -1
- package/dist/types/session.d.ts +99 -0
- package/dist/types/workflow.d.ts +7 -0
- package/dist/workflow.cjs +7 -2
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +2 -0
- package/dist/workflow.d.ts +2 -0
- package/dist/workflow.js +7 -2
- package/dist/workflow.js.map +1 -1
- package/package.json +14 -34
- package/dist/internal/observability/context.d.cts +0 -23
- package/dist/internal/observability/context.d.ts +0 -23
- package/dist/internal/observability/index.cjs +0 -38
- package/dist/internal/observability/index.cjs.map +0 -1
- package/dist/internal/observability/index.d.cts +0 -8
- package/dist/internal/observability/index.d.ts +0 -8
- package/dist/internal/observability/index.js +0 -33
- package/dist/internal/observability/index.js.map +0 -1
- package/dist/internal/plugins/index.cjs +0 -363
- package/dist/internal/plugins/index.cjs.map +0 -1
- package/dist/internal/plugins/index.js +0 -357
- package/dist/internal/plugins/index.js.map +0 -1
- package/dist/internal/workflow/index.d.ts +0 -12
- package/dist/server/adapter/index.d.cts +0 -8
- package/dist/server/adapter/index.d.ts +0 -8
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internal/plugins/context.ts","../../../src/internal/plugins/lifecycle.ts","../../../src/errors.ts","../../../src/internal/plugins/manager.ts","../../../src/internal/plugins/types.ts"],"names":[],"mappings":";;;AAsCO,SAAS,mBAAA,GAGd;AACA,EAAA,MAAM,aAAA,GAAqC;AAAA,IACzC,OAAO,EAAC;AAAA,IACR,UAAU,EAAC;AAAA,IACX,KAAA,sBAAW,GAAA,EAAI;AAAA,IACf,UAAU;AAAC,GACb;AAEA,EAAA,MAAM,IAAA,GAAsB;AAAA,IAC1B,aAAa,IAAA,EAAM;AACjB,MAAA,aAAA,CAAc,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IAC/B,CAAA;AAAA,IACA,eAAA,CAAgB,IAAA,EAAM,OAAA,EAAS,IAAA,GAAuB,EAAC,EAAG;AACxD,MAAA,MAAM,KAAA,GAAsB,EAAE,IAAA,EAAM,OAAA,EAAQ;AAC5C,MAAA,IAAI,IAAA,CAAK,WAAA,KAAgB,MAAA,EAAW,KAAA,CAAM,cAAc,IAAA,CAAK,WAAA;AAC7D,MAAA,aAAA,CAAc,QAAA,CAAS,KAAK,KAAK,CAAA;AAAA,IACnC,CAAA;AAAA,IACA,EAAA,CAAG,MAAM,OAAA,EAAS;AAIhB,MAAA,IAAI,OAAO,YAAY,UAAA,EAAY;AACjC,QAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,sDAAA,EAAyD,IAAI,CAAA;AAAA,CAAK,CAAA;AACvF,QAAA;AAAA,MACF;AACA,MAAA,MAAM,WAAW,aAAA,CAAc,KAAA,CAAM,GAAA,CAAI,IAAI,KAAK,EAAC;AACnD,MAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AACrB,MAAA,aAAA,CAAc,KAAA,CAAM,GAAA,CAAI,IAAA,EAAM,QAAQ,CAAA;AAAA,IACxC,CAAA;AAAA,IACA,aAAA,CAAc,OAAA,EAAS,IAAA,GAAO,MAAA,EAAQ;AACpC,MAAA,aAAA,CAAc,QAAA,CAAS,IAAA,CAAK,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,IAC/C;AAAA,GACF;AAEA,EAAA,MAAM,GAAA,GAAM,UAAA,EAAW,GAAI,WAAA,CAAY,IAAI,CAAA,GAAI,IAAA;AAC/C,EAAA,OAAO,EAAE,KAAK,aAAA,EAAc;AAC9B;AAEA,SAAS,UAAA,GAAsB;AAC7B,EAAA,OAAO,OAAA,CAAQ,IAAI,QAAA,KAAa,YAAA;AAClC;AAEA,SAAS,YAAY,IAAA,EAAoC;AACvD,EAAA,OAAO,IAAI,MAAM,IAAA,EAAM;AAAA,IACrB,GAAA,CAAI,SAAS,IAAA,EAAM;AACjB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,wDAAA,EAAsD,MAAA,CAAO,IAAI,CAAC,CAAA,uEAAA;AAAA,OAEpE;AAAA,IACF,CAAA;AAAA,IACA,cAAA,CAAe,SAAS,IAAA,EAAM;AAC5B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2DAAA,EAAyD,MAAA,CAAO,IAAI,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,IAC1F;AAAA,GACD,CAAA;AACH;;;AChFA,eAAsB,qBAAA,CACpB,UACA,GAAA,EACe;AACf,EAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,IAAA,IAAI;AACF,MAAA,MAAO,EAAwB,GAAG,CAAA;AAAA,IACpC,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,8CAAA,EAAiD,GAAG;AAAA,CAAI,CAAA;AAAA,IAC/E;AAAA,EACF;AACF;AAEA,eAAsB,iBAAA,CACpB,UACA,OAAA,EACY;AACZ,EAAA,IAAI,OAAA,GAAU,OAAA;AACd,EAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAO,CAAA,CAA8B,OAAO,CAAA;AAGzD,MAAA,IAAI,IAAA,KAAS,QAAW,OAAA,GAAU,IAAA;AAAA,IACpC,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,wDAAA,EAA2D,GAAG;AAAA,CAAI,CAAA;AAAA,IACzF;AAAA,EACF;AACA,EAAA,OAAO,OAAA;AACT;;;ACgGO,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EACzB,IAAA,GAAe,mBAAA;AAAA,EACxB,WAAA;AAAA,EACA,IAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EAET,WAAA,CACE,OAAA,EACA,OAAA,GAMI,EAAC,EACL;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAQ,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAM,GAAI,MAAS,CAAA;AACjF,IAAA,IAAA,CAAK,WAAA,GAAc,QAAQ,WAAA,IAAe,KAAA;AAC1C,IAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,MAAA,EAAW,IAAA,CAAK,OAAO,OAAA,CAAQ,IAAA;AACpD,IAAA,IAAI,OAAA,CAAQ,cAAA,KAAmB,MAAA,EAAW,IAAA,CAAK,iBAAiB,OAAA,CAAQ,cAAA;AACxE,IAAA,IAAI,OAAA,CAAQ,QAAA,KAAa,MAAA,EAAW,IAAA,CAAK,WAAW,OAAA,CAAQ,QAAA;AAAA,EAC9D;AACF,CAAA;AAuCO,IAAM,kBAAA,GAAN,cAAiC,iBAAA,CAAkB;AAAA,EACtC,IAAA,GAAe,oBAAA;AAAA,EAEjC,WAAA,CACE,OAAA,EACA,OAAA,GAAwE,EAAC,EACzE;AACA,IAAA,KAAA,CAAM,SAAS,EAAE,GAAG,OAAA,EAAS,WAAA,EAAa,OAAO,CAAA;AAAA,EACnD;AACF,CAAA;;;ACvKO,IAAM,gBAAN,MAAoB;AAAA,EACzB,WAAA,GAAiC;AAAA,IAC/B,OAAO,EAAC;AAAA,IACR,UAAU,EAAC;AAAA,IACX,KAAA,sBAAW,GAAA,EAAI;AAAA,IACf,UAAU,EAAC;AAAA,IACX,kBAAkB,EAAC;AAAA,IACnB,iBAAiB;AAAC,GACpB;AAAA,EACA,YAAA,GAAe,KAAA;AAAA;AAAA;AAAA,EAGN,OAAA,uBAAc,GAAA,EAAiC;AAAA,EAExD,MAAM,WAAW,OAAA,EAA+C;AAC9D,IAAA,IAAI,KAAK,YAAA,EAAc;AACrB,MAAA,MAAM,IAAI,MAAM,6EAAwE,CAAA;AAAA,IAC1F;AACA,IAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AAGpB,IAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA,EAAG;AACzB,QAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,UACb,CAAA,qCAAA,EAAwC,OAAO,IAAI,CAAA;AAAA;AAAA,SACrD;AAAA,MACF;AACA,MAAA,IAAA,CAAK,GAAA,CAAI,OAAO,IAAI,CAAA;AACpB,MAAA,MAAM,IAAA,CAAK,gBAAgB,MAAM,CAAA;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,SAAS,MAAA,EAA+B;AAC5C,IAAA,IAAI,MAAA,CAAO,SAAS,SAAA,EAAW;AAC7B,MAAA,MAAM,IAAI,kBAAA;AAAA,QACR,CAAA,kDAAA,EAAqD,MAAA,CAAO,IAAI,CAAA,OAAA,EAAU,OAAO,IAAI,CAAA,EAAA,CAAA;AAAA,QACrF,EAAE,MAAM,2BAAA;AAA4B,OACtC;AAAA,IACF;AACA,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,OAAO,IAAI,CAAA;AAC1C,IAAA,IAAI,KAAA,KAAU,MAAA,EAAW,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA;AAC5C,IAAA,MAAM,EAAE,GAAA,EAAK,aAAA,EAAc,GAAI,mBAAA,EAAoB;AACnD,IAAA,MAAM,MAAA,CAAO,SAAS,GAAG,CAAA;AACzB,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,IAAA,EAAM,aAAa,CAAA;AAC3C,IAAA,IAAA,CAAK,OAAO,aAAa,CAAA;AAAA,EAC3B;AAAA,EAEA,IAAI,UAAA,GAA0C;AAC5C,IAAA,OAAO,IAAA,CAAK,WAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBAAoB,GAAA,EAAmE;AAC3F,IAAA,MAAM,WAAW,IAAA,CAAK,WAAA,CAAY,MAAM,GAAA,CAAI,eAAe,KAAK,EAAC;AACjE,IAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,MAAA,MAAM,QAAA,GAAY,MAAO,CAAA,CAAyC,GAAG,CAAA;AAGrE,MAAA,IAAI,QAAA,KAAa,MAAA,IAAc,QAAA,CAAiC,KAAA,KAAU,IAAA,EAAM;AAC9E,QAAA,OAAO,QAAA;AAAA,MACT;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAGA,SAAS,IAAA,EAAoF;AAC3F,IAAA,OAAO,KAAK,WAAA,CAAY,KAAA,CAAM,GAAA,CAAI,IAAI,KAAK,EAAC;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,mBAAA,CACJ,GAAA,EACA,qBAAA,EAC6B;AAC7B,IAAA,MAAM,WAAW,IAAA,CAAK,WAAA,CAAY,MAAM,GAAA,CAAI,eAAe,KAAK,EAAC;AACjE,IAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAClC,IAAA,MAAM,QAAkB,EAAC;AACzB,IAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAU,MAAO,CAAA,CAAyC,GAAG,CAAA;AAGnE,QAAA,IAAI,MAAA,EAAQ,eAAA,IAAmB,MAAA,CAAO,eAAA,CAAgB,SAAS,CAAA,EAAG;AAChE,UAAA,KAAA,CAAM,IAAA,CAAK,OAAO,eAAe,CAAA;AAAA,QACnC;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,UACb,4CACE,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CACjD;AAAA;AAAA,SACF;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAC/B,IAAA,IAAI,QAAA,GAAW,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA;AAEhC,IAAA,IAAI,QAAA,CAAS,SAAS,qBAAA,EAAuB;AAC3C,MAAA,QAAA,GAAW,CAAA,EAAG,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,qBAAqB,CAAC;AAAA,iBAAA,CAAA;AAAA,IACxD;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,2BAA2B,GAAA,EAA+C;AAC9E,IAAA,MAAM,WAAW,IAAA,CAAK,WAAA,CAAY,MAAM,GAAA,CAAI,sBAAsB,KAAK,EAAC;AACxE,IAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,MAAA,IAAI;AACF,QAAA,MAAO,EAAgD,GAAG,CAAA;AAAA,MAC5D,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,UACb,mDACE,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CACjD;AAAA;AAAA,SACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,iBAAA,CAAqB,IAAA,EAAgB,GAAA,EAAuB;AAChE,IAAA,KAAA,MAAW,CAAA,IAAK,KAAK,WAAA,CAAY,KAAA,CAAM,IAAI,IAAI,CAAA,IAAK,EAAC,EAAG;AACtD,MAAA,IAAI;AACF,QAAA,MAAO,EAAwB,GAAG,CAAA;AAAA,MACpC,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,UACb,CAAA,cAAA,EAAiB,IAAI,CAAA,cAAA,EAAiB,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC;AAAA;AAAA,SACxF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,aAAA,CAAiB,IAAA,EAAgB,OAAA,EAAY,GAAA,EAA0B;AAC3E,IAAA,IAAI,OAAA,GAAU,OAAA;AACd,IAAA,KAAA,MAAW,CAAA,IAAK,KAAK,WAAA,CAAY,KAAA,CAAM,IAAI,IAAI,CAAA,IAAK,EAAC,EAAG;AACtD,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAO,MAAO,CAAA,CAAoC,OAAA,EAAS,GAAG,CAAA;AACpE,QAAA,IAAI,GAAA,KAAQ,QAAW,OAAA,GAAU,GAAA;AAAA,MACnC,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,UACb,CAAA,cAAA,EAAiB,IAAI,CAAA,cAAA,EAAiB,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC;AAAA;AAAA,SACxF;AAAA,MACF;AAAA,IACF;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA,EAGA,qBAAqB,GAAA,EAAyC;AAC5D,IAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,gBAAA,EAAkB,GAAG,CAAA;AAAA,EACrD;AAAA;AAAA,EAGA,mBAAmB,GAAA,EAAoC;AACrD,IAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,cAAA,EAAgB,GAAG,CAAA;AAAA,EACnD;AAAA,EACA,oBAAoB,GAAA,EAAoC;AACtD,IAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,eAAA,EAAiB,GAAG,CAAA;AAAA,EACpD;AAAA;AAAA,EAGA,uBAAuB,GAAA,EAA6C;AAClE,IAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,kBAAA,EAAoB,GAAG,CAAA;AAAA,EACvD;AAAA,EACA,qBAAqB,GAAA,EAA6C;AAChE,IAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,gBAAA,EAAkB,GAAG,CAAA;AAAA,EACrD;AAAA;AAAA,EAGA,2BAAA,CAA+B,SAAY,GAAA,EAAmC;AAC5E,IAAA,OAAO,IAAA,CAAK,aAAA,CAAc,uBAAA,EAAyB,OAAA,EAAS,GAAG,CAAA;AAAA,EACjE;AAAA;AAAA,EAGA,0BAAA,CAA2B,QAAgB,GAAA,EAAwC;AACjF,IAAA,OAAO,IAAA,CAAK,aAAA,CAAc,sBAAA,EAAwB,MAAA,EAAQ,GAAG,CAAA;AAAA,EAC/D;AAAA,EAEA,MAAM,gBAAgB,MAAA,EAA+B;AACnD,IAAA,IAAI,MAAA,CAAO,SAAS,SAAA,EAAW;AAC7B,MAAA,MAAM,EAAE,GAAA,EAAK,aAAA,EAAc,GAAI,mBAAA,EAAoB;AACnD,MAAA,MAAM,MAAA,CAAO,SAAS,GAAG,CAAA;AACzB,MAAA,IAAA,CAAK,OAAO,aAAa,CAAA;AAAA,IAC3B,CAAA,MAAA,IAAW,MAAA,CAAO,IAAA,KAAS,gBAAA,EAAkB;AAC3C,MAAA,IAAA,CAAK,WAAA,CAAY,iBAAiB,IAAA,CAAK;AAAA,QACrC,YAAY,MAAA,CAAO,IAAA;AAAA,QACnB,SAAS,MAAA,CAAO;AAAA,OACjB,CAAA;AAAA,IACH,CAAA,MAAA,IAAW,MAAA,CAAO,IAAA,KAAS,QAAA,EAAU;AACnC,MAAA,IAAA,CAAK,WAAA,CAAY,gBAAgB,IAAA,CAAK;AAAA,QACpC,YAAY,MAAA,CAAO,IAAA;AAAA,QACnB,gBAAgB,MAAA,CAAO;AAAA,OACxB,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,OAAO,CAAA,EAA8B;AACnC,IAAA,IAAA,CAAK,WAAA,CAAY,KAAA,CAAM,IAAA,CAAK,GAAG,EAAE,KAAK,CAAA;AACtC,IAAA,IAAA,CAAK,WAAA,CAAY,QAAA,CAAS,IAAA,CAAK,GAAG,EAAE,QAAQ,CAAA;AAC5C,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,QAAQ,KAAK,CAAA,CAAE,KAAA,CAAM,SAAQ,EAAG;AAChD,MAAA,MAAM,WAAW,IAAA,CAAK,WAAA,CAAY,MAAM,GAAA,CAAI,IAAI,KAAK,EAAC;AACtD,MAAA,QAAA,CAAS,IAAA,CAAK,GAAG,QAAQ,CAAA;AACzB,MAAA,IAAA,CAAK,WAAA,CAAY,KAAA,CAAM,GAAA,CAAI,IAAA,EAAM,QAAQ,CAAA;AAAA,IAC3C;AACA,IAAA,IAAA,CAAK,WAAA,CAAY,QAAA,CAAS,IAAA,CAAK,GAAG,EAAE,QAAQ,CAAA;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS,CAAA,EAA8B;AACrC,IAAA,SAAA,CAAU,IAAA,CAAK,WAAA,CAAY,KAAA,EAAO,CAAA,CAAE,KAAK,CAAA;AACzC,IAAA,SAAA,CAAU,IAAA,CAAK,WAAA,CAAY,QAAA,EAAU,CAAA,CAAE,QAAQ,CAAA;AAC/C,IAAA,SAAA,CAAU,IAAA,CAAK,WAAA,CAAY,QAAA,EAAU,CAAA,CAAE,QAAQ,CAAA;AAC/C,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,QAAQ,KAAK,CAAA,CAAE,KAAA,CAAM,SAAQ,EAAG;AAChD,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,KAAA,CAAM,IAAI,IAAI,CAAA;AAChD,MAAA,IAAI,aAAa,MAAA,EAAW;AAC5B,MAAA,SAAA,CAAU,UAAU,QAAQ,CAAA;AAC5B,MAAA,IAAI,SAAS,MAAA,KAAW,CAAA,OAAQ,WAAA,CAAY,KAAA,CAAM,OAAO,IAAI,CAAA;AAAA,IAC/D;AAAA,EACF;AACF;AAGA,SAAS,SAAA,CAAa,KAAU,QAAA,EAAkC;AAChE,EAAA,KAAA,MAAW,QAAQ,QAAA,EAAU;AAC3B,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAA;AAC5B,IAAA,IAAI,GAAA,KAAQ,EAAA,EAAI,GAAA,CAAI,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EACnC;AACF;;;AC1IO,SAAS,aAA+B,CAAA,EAAS;AACtD,EAAA,OAAO,CAAA;AACT","file":"index.cjs","sourcesContent":["/**\n * PluginContext implementation + dev-mode seal (T1.2, ADR D99).\n *\n * `createPluginContext()` returns a fresh `{ ctx, registrations }` pair\n * for each plugin. In dev mode (`NODE_ENV !== \"production\"`) the context\n * is wrapped in a Proxy that throws on `set`/`delete` to catch plugin\n * abuse early. In production the raw impl is returned (zero overhead).\n *\n * @internal\n */\n\nimport type { CustomTool } from \"../../types/agent.js\";\nimport type {\n CommandHandler,\n CommandOptions,\n HookHandler,\n HookName,\n PluginContext,\n} from \"./types.js\";\n\ninterface CommandEntry {\n name: string;\n handler: CommandHandler;\n description?: string;\n}\n\ninterface InjectedMessage {\n content: string;\n role: \"user\" | \"system\";\n}\n\nexport interface PluginRegistrations {\n tools: CustomTool[];\n commands: CommandEntry[];\n hooks: Map<HookName, HookHandler[]>;\n injected: InjectedMessage[];\n}\n\nexport function createPluginContext(): {\n ctx: PluginContext;\n registrations: PluginRegistrations;\n} {\n const registrations: PluginRegistrations = {\n tools: [],\n commands: [],\n hooks: new Map(),\n injected: [],\n };\n\n const impl: PluginContext = {\n registerTool(tool) {\n registrations.tools.push(tool);\n },\n registerCommand(name, handler, opts: CommandOptions = {}) {\n const entry: CommandEntry = { name, handler };\n if (opts.description !== undefined) entry.description = opts.description;\n registrations.commands.push(entry);\n },\n on(hook, handler) {\n // EC-2 fix: defense-in-depth. Plugin author can bypass TS via `as any`\n // and pass null/undefined; ignore + warn rather than crash the loop\n // downstream when `runPreToolCallHooks` tries to invoke the handler.\n if (typeof handler !== \"function\") {\n process.stderr.write(`[theokit-sdk] ignoring non-function handler for hook \"${hook}\"\\n`);\n return;\n }\n const existing = registrations.hooks.get(hook) ?? [];\n existing.push(handler);\n registrations.hooks.set(hook, existing);\n },\n injectMessage(content, role = \"user\") {\n registrations.injected.push({ content, role });\n },\n };\n\n const ctx = shouldSeal() ? sealContext(impl) : impl;\n return { ctx, registrations };\n}\n\nfunction shouldSeal(): boolean {\n return process.env.NODE_ENV !== \"production\";\n}\n\nfunction sealContext(impl: PluginContext): PluginContext {\n return new Proxy(impl, {\n set(_target, prop) {\n throw new Error(\n `[theokit-sdk] PluginContext is sealed — cannot set ${String(prop)}. ` +\n `Plugins must use registerTool, registerCommand, on, or injectMessage.`,\n );\n },\n deleteProperty(_target, prop) {\n throw new Error(`[theokit-sdk] PluginContext is sealed — cannot delete ${String(prop)}.`);\n },\n });\n}\n","/**\n * Hook dispatch helpers (T1.4, extracted from manager to keep both modules\n * small).\n *\n * - `runFireAndForgetHooks` — runs all handlers, swallows + logs throws,\n * no return value (post_tool_call, on_session_start/end, etc.).\n * - `runTransformHooks` — chains handlers, each can return a new value\n * that replaces the input for the next handler. `undefined` keeps the\n * current; `null` REPLACES current with null (EC-6 explicit).\n *\n * @internal\n */\n\nimport type { HookHandler } from \"./types.js\";\n\nexport async function runFireAndForgetHooks<C>(\n handlers: ReadonlyArray<HookHandler>,\n ctx: C,\n): Promise<void> {\n for (const h of handlers) {\n try {\n await (h as (c: C) => unknown)(ctx);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[theokit-sdk] plugin hook threw (continuing): ${msg}\\n`);\n }\n }\n}\n\nexport async function runTransformHooks<T>(\n handlers: ReadonlyArray<HookHandler>,\n initial: T,\n): Promise<T> {\n let current = initial;\n for (const h of handlers) {\n try {\n const next = await (h as (c: T) => T | undefined)(current);\n // EC-6 explicit semantics: `undefined` = no-op; any other value\n // (including `null`) REPLACES current.\n if (next !== undefined) current = next;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[theokit-sdk] plugin transform hook threw (continuing): ${msg}\\n`);\n }\n }\n return current;\n}\n","import { defaultRetriableForCode } from \"./internal/default-retriable.js\";\nimport { redactSecrets } from \"./internal/security/redact.js\";\nimport type { RunOperation } from \"./types/run.js\";\n\n/**\n * Finite, machine-readable error codes for provider-originated errors\n * (ADR D66). Consumers can `switch (err.metadata?.code)` exhaustively\n * — adding a new variant is an explicit decision + test coverage.\n *\n * @public\n */\nexport type ErrorCode =\n | \"rate_limit\"\n | \"auth_failed\"\n | \"invalid_request\"\n | \"timeout\"\n | \"server_error\"\n | \"context_too_long\"\n | \"content_filtered\"\n | \"model_unavailable\"\n | \"network\"\n | \"quota_exceeded\"\n | \"unknown\";\n\n/**\n * Codes used by {@link AgentRunError} (Production-Readiness #3, ADR D311).\n *\n * Superset of {@link ErrorCode} extended with codes that do NOT originate\n * from a provider HTTP response:\n *\n * - `quota_exceeded` — billing limit hit (provider 402 or signalled error)\n * - `tool_runtime_error` — custom tool handler threw inside dispatch\n * - `aborted` — caller's `AbortSignal` fired (Phase 4)\n * - `invalid_model` — model id rejected by provider (400 \"model not found\")\n * - `safety_blocked` — provider safety filter blocked req or resp\n * - `provider_unreachable` — DNS/TCP/timeout/5xx at transport boundary\n *\n * The `& {}` tail keeps the literal-union ergonomics (autocomplete) while\n * accepting any string for forward compatibility with constructor calls\n * that pass arbitrary code values (legacy callers).\n *\n * @public\n */\n/**\n * T1.1 — closed literal union for `AgentRunError.code`. The previous\n * `(string & {})` escape hatch let arbitrary strings slip into the type\n * surface and defeated exhaustive `switch (code)` discrimination. This is\n * the canonical closed form. `AgentRunErrorCode` is re-aliased below for\n * source-level back-compat.\n *\n * Adding a new code: append the literal here AND audit every `switch (err.code)`\n * in callers. Type-checker enforces the audit via the `default: assertNever(code)`\n * convention.\n *\n * @public\n */\nexport type KnownAgentRunErrorCode =\n | ErrorCode\n | \"quota_exceeded\"\n | \"tool_runtime_error\"\n | \"aborted\"\n | \"invalid_model\"\n | \"safety_blocked\"\n | \"provider_unreachable\";\n\n/**\n * Back-compat alias of {@link KnownAgentRunErrorCode}. Pre-T1.1 callers that\n * imported `AgentRunErrorCode` keep working; new code SHOULD prefer\n * `KnownAgentRunErrorCode` to make the closed-union intent explicit.\n *\n * @public\n */\nexport type AgentRunErrorCode = KnownAgentRunErrorCode;\n\n/** Snapshot of every known code at runtime — used by the boundary coercer. */\nconst KNOWN_AGENT_RUN_ERROR_CODES = new Set<string>([\n \"rate_limit\",\n \"auth_failed\",\n \"invalid_request\",\n \"timeout\",\n \"server_error\",\n \"context_too_long\",\n \"content_filtered\",\n \"model_unavailable\",\n \"network\",\n \"unknown\",\n \"quota_exceeded\",\n \"tool_runtime_error\",\n \"aborted\",\n \"invalid_model\",\n \"safety_blocked\",\n \"provider_unreachable\",\n]);\n\n/**\n * T1.1 boundary helper — coerce an arbitrary string (typically arriving from\n * a downstream `RunErrorDetail.code` or a deserialized cloud response) into a\n * `KnownAgentRunErrorCode`. Unknown strings collapse to `\"unknown\"` so the\n * closed type contract holds without forcing every caller to switch.\n *\n * @internal\n */\nexport function coerceToKnownAgentRunErrorCode(code: string | undefined): KnownAgentRunErrorCode {\n if (code !== undefined && KNOWN_AGENT_RUN_ERROR_CODES.has(code)) {\n return code as KnownAgentRunErrorCode;\n }\n return \"unknown\";\n}\n\n/**\n * Structured context for errors that originated from a provider HTTP\n * call (ADR D65). Lets callers retry with the right backoff (`retryAfter`),\n * surface actionable diagnostics (`provider`, `endpoint`), and inspect the\n * raw response body when needed (`raw`, capped at ~2KB by the mapper).\n *\n * @public\n */\nexport interface ErrorMetadata {\n /** Provider canonical name (e.g., `\"anthropic\"`, `\"openai\"`, `\"openrouter\"`, `\"gemini\"`). */\n provider: string;\n /** HTTP endpoint that failed (e.g., `\"/v1/messages\"`, `\"/v1/chat/completions\"`). */\n endpoint: string;\n /** Machine-readable error code (finite enum). */\n code: ErrorCode;\n /** HTTP status code if applicable. */\n statusCode?: number;\n /** Seconds to wait before retry, per provider's `retry-after` header (numeric form only). */\n retryAfter?: number;\n /** Raw response body for debugging (truncated to ~2KB by the mapper). */\n raw?: unknown;\n}\n\n/**\n * Base class for all errors thrown by `@theokit/sdk`.\n *\n * Use `isRetryable` to drive retry/backoff logic. `code` and `protoErrorCode`\n * are populated for server-originated errors when available. `metadata`\n * (ADR D65) carries structured `{ provider, endpoint, code, ... }` when\n * the error originated from a provider HTTP call.\n *\n * @public\n */\nexport class TheokitAgentError extends Error {\n override readonly name: string = \"TheokitAgentError\";\n readonly isRetryable: boolean;\n readonly code?: string;\n readonly protoErrorCode?: string;\n readonly metadata?: ErrorMetadata;\n\n constructor(\n message: string,\n options: {\n isRetryable?: boolean;\n code?: string;\n protoErrorCode?: string;\n cause?: unknown;\n metadata?: ErrorMetadata;\n } = {},\n ) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined);\n this.isRetryable = options.isRetryable ?? false;\n if (options.code !== undefined) this.code = options.code;\n if (options.protoErrorCode !== undefined) this.protoErrorCode = options.protoErrorCode;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n}\n\n/**\n * Invalid API key, not logged in, insufficient permissions.\n *\n * @public\n */\nexport class AuthenticationError extends TheokitAgentError {\n override readonly name: string = \"AuthenticationError\";\n\n constructor(\n message: string,\n options: { code?: string; cause?: unknown; metadata?: ErrorMetadata } = {},\n ) {\n super(message, { ...options, isRetryable: false });\n }\n}\n\n/**\n * Too many requests or usage limits exceeded.\n *\n * @public\n */\nexport class RateLimitError extends TheokitAgentError {\n override readonly name: string = \"RateLimitError\";\n\n constructor(\n message: string,\n options: { code?: string; cause?: unknown; metadata?: ErrorMetadata } = {},\n ) {\n super(message, { ...options, isRetryable: true });\n }\n}\n\n/**\n * Invalid model, bad request parameters, malformed options.\n *\n * @public\n */\nexport class ConfigurationError extends TheokitAgentError {\n override readonly name: string = \"ConfigurationError\";\n\n constructor(\n message: string,\n options: { code?: string; cause?: unknown; metadata?: ErrorMetadata } = {},\n ) {\n super(message, { ...options, isRetryable: false });\n }\n}\n\n/**\n * Thrown when creating a cloud agent for a repo whose SCM provider is not\n * connected. Use `helpUrl` to point the user at the right reconnect flow.\n *\n * @public\n */\nexport class IntegrationNotConnectedError extends ConfigurationError {\n override readonly name: string = \"IntegrationNotConnectedError\";\n readonly provider: string;\n readonly helpUrl: string;\n\n constructor(\n message: string,\n options: {\n provider: string;\n helpUrl: string;\n code?: string;\n cause?: unknown;\n metadata?: ErrorMetadata;\n },\n ) {\n super(message, options);\n this.provider = options.provider;\n this.helpUrl = options.helpUrl;\n }\n}\n\n/**\n * Service unavailable, timeout, transport-level failure.\n *\n * @public\n */\nexport class NetworkError extends TheokitAgentError {\n override readonly name: string = \"NetworkError\";\n\n constructor(\n message: string,\n options: { code?: string; cause?: unknown; metadata?: ErrorMetadata } = {},\n ) {\n super(message, { ...options, isRetryable: true });\n }\n}\n\n/**\n * Catch-all for unclassified server or runtime errors.\n *\n * @public\n */\nexport class UnknownAgentError extends TheokitAgentError {\n override readonly name: string = \"UnknownAgentError\";\n\n constructor(\n message: string,\n options: { code?: string; cause?: unknown; metadata?: ErrorMetadata } = {},\n ) {\n super(message, { ...options, isRetryable: false });\n }\n}\n\n/**\n * Thrown by `Agent.prompt` (and helpers that go through `run.wait()`) when\n * the option `{ throwOnError: true }` is set and the run terminates with\n * `status: 'error'`. Carries the structured `RunResult.error` fields so\n * callers can `catch` once and branch on `code` / `provider` instead of\n * unwrapping the run.\n *\n * Extends {@link TheokitAgentError} per ADR D65 — no new hierarchy.\n *\n * @example\n * try {\n * await Agent.prompt(msg, { apiKey, model, throwOnError: true });\n * } catch (err) {\n * if (err instanceof AgentRunError && err.code === 'auth_failed') {\n * // bad key\n * }\n * }\n *\n * @public\n */\nexport class AgentRunError extends TheokitAgentError {\n override readonly name: string = \"AgentRunError\";\n readonly provider?: string;\n readonly raw?: string;\n /** Provider's request id (`x-request-id` / `request-id` header). Useful for support tickets. */\n readonly requestId?: string;\n /** SDK conversation id this error was raised inside. */\n readonly conversationId?: string;\n\n constructor(\n message: string,\n options: {\n code: AgentRunErrorCode;\n provider?: string;\n raw?: string;\n requestId?: string;\n conversationId?: string;\n retriable?: boolean;\n cause?: unknown;\n metadata?: ErrorMetadata;\n },\n ) {\n super(message, {\n code: options.code,\n cause: options.cause,\n metadata: options.metadata,\n // D311: most AgentRunErrors are not retriable (auth, validation, abort).\n // Provider mappers (D314) override per-status — explicit `retriable` wins\n // over the implicit default when supplied.\n isRetryable: options.retriable ?? defaultRetriableForCode(options.code),\n });\n if (options.provider !== undefined) this.provider = options.provider;\n if (options.raw !== undefined) this.raw = options.raw;\n if (options.requestId !== undefined) this.requestId = options.requestId;\n if (options.conversationId !== undefined) this.conversationId = options.conversationId;\n }\n\n /**\n * Production-Readiness #3 (ADR D311): alias for `isRetryable` exposed as\n * `retriable` to match the handoff contract. Future v2 will deprecate\n * `isRetryable` in favor of this.\n */\n get retriable(): boolean {\n return this.isRetryable;\n }\n\n /**\n * D312: provider's `Retry-After` header in **milliseconds**. Mappers store\n * the header value (seconds) in `metadata.retryAfter`; this getter\n * multiplies by 1000 so the result composes with `Date.now()`/`setTimeout`.\n *\n * Returns `undefined` when no hint was provided. `0` is a legitimate value\n * — use `=== undefined` check rather than truthy check.\n */\n get retryAfterMs(): number | undefined {\n if (this.metadata?.retryAfter === undefined) return undefined;\n return this.metadata.retryAfter * 1000;\n }\n\n /**\n * D313 + T1.5: alias for `metadata.raw`. Provider response body for\n * debugging. T1.5 wraps the value in `redactSecrets` at the getter\n * boundary so secret-shaped substrings (`sk-...`, Bearer JWTs, etc.) are\n * stripped before reaching the caller. Available but NEVER serialized\n * into `.message` (anti-leak invariant).\n */\n get providerError(): unknown {\n const raw = this.metadata?.raw;\n if (raw === undefined) return undefined;\n if (typeof raw === \"string\") return redactSecrets(raw);\n // Non-string raw (object/buffer) — stringify then redact.\n try {\n return redactSecrets(JSON.stringify(raw));\n } catch {\n return redactSecrets(String(raw));\n }\n }\n\n /**\n * T1.5 — sanitized JSON form. `metadata.raw` is OMITTED by default; opt\n * in via `THEOKIT_DEBUG_RAW_ERRORS=1` to surface the (redacted) raw\n * payload for diagnostics. Every other field stays accessible.\n *\n * The single env-var gate is read each call so operators can toggle at\n * runtime without restarting the process.\n */\n toJSON(): Record<string, unknown> {\n const json: Record<string, unknown> = {\n name: this.name,\n message: this.message,\n isRetryable: this.isRetryable,\n };\n addOptionalFields(json, this);\n const safeMeta = sanitizeMetadata(this.metadata);\n if (safeMeta !== undefined) json.metadata = safeMeta;\n return json;\n }\n}\n\nfunction addOptionalFields(json: Record<string, unknown>, err: AgentRunError): void {\n if (err.code !== undefined) json.code = err.code;\n if (err.provider !== undefined) json.provider = err.provider;\n if (err.requestId !== undefined) json.requestId = err.requestId;\n if (err.conversationId !== undefined) json.conversationId = err.conversationId;\n if (err.raw !== undefined) json.raw = redactSecrets(err.raw);\n}\n\nfunction sanitizeMetadata(meta: ErrorMetadata | undefined): ErrorMetadata | undefined {\n if (meta === undefined) return undefined;\n const { raw, ...rest } = meta;\n const debugRaw = process.env.THEOKIT_DEBUG_RAW_ERRORS === \"1\";\n if (debugRaw && raw !== undefined) {\n const redactedRaw =\n typeof raw === \"string\" ? redactSecrets(raw) : redactSecrets(safeStringify(raw));\n return { ...rest, raw: redactedRaw } as ErrorMetadata;\n }\n return rest as ErrorMetadata;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n/**\n * Is this error transient (worth retrying)?\n *\n * Returns the SDK's own retryability verdict: every {@link TheokitAgentError}\n * subclass computes `isRetryable` at construction (rate-limit / network /\n * credential-pool-exhausted are retryable; auth / configuration / unsupported\n * are not), so this predicate is a single source of truth rather than a\n * re-derivation. Non-SDK errors return `false` conservatively — wrap a foreign\n * error in the appropriate SDK error first if you want it considered transient.\n * It never inspects `err.message`.\n *\n * @example\n * try {\n * await agent.send(message, { throwOnError: true });\n * } catch (err) {\n * if (isTransientError(err)) return retryWithBackoff();\n * throw err;\n * }\n *\n * @public\n */\nexport function isTransientError(err: unknown): boolean {\n return err instanceof TheokitAgentError && err.isRetryable === true;\n}\n\n/**\n * Thrown when a {@link Run} or agent operation is not available on the current\n * runtime. Check first with `run.supports(operation)`.\n *\n * Extends {@link TheokitAgentError} (so error-catching code that branches on\n * `instanceof TheokitAgentError` continues to work) but is never retryable —\n * an unsupported operation will not become supported on retry.\n *\n * @public\n */\nexport class UnsupportedRunOperationError extends TheokitAgentError {\n override readonly name: string = \"UnsupportedRunOperationError\";\n readonly operation: RunOperation;\n\n constructor(\n message: string,\n operation: RunOperation,\n options: { code?: string; cause?: unknown } = {},\n ) {\n super(message, {\n ...options,\n isRetryable: false,\n code: options.code ?? \"unsupported_run_operation\",\n });\n this.operation = operation;\n }\n}\n\n/**\n * Thrown when every credential in a per-provider pool is in cooldown\n * and no healthy key is available (ADR D133). The caller's\n * {@link import(\"./internal/llm/fallback-client.js\").FallbackLlmClient}\n * catches this and tries the next provider in the fallback chain.\n *\n * `metadata.nextRetryAt` (epoch ms) tells callers when the soonest\n * pool entry resumes — useful for manual retry scheduling.\n *\n * @public\n */\nexport class CredentialPoolExhaustedError extends TheokitAgentError {\n override readonly name: string = \"CredentialPoolExhaustedError\";\n readonly provider: string;\n readonly nextRetryAt: number | undefined;\n\n constructor(\n message: string,\n options: {\n provider: string;\n nextRetryAt?: number;\n code?: string;\n cause?: unknown;\n metadata?: ErrorMetadata;\n },\n ) {\n super(message, {\n ...options,\n isRetryable: true,\n code: options.code ?? \"credential_pool_exhausted\",\n });\n this.provider = options.provider;\n this.nextRetryAt = options.nextRetryAt;\n }\n}\n\n/**\n * Finite error codes specific to memory adapter operations (ADR D141).\n *\n * @public\n */\nexport type MemoryAdapterErrorCode =\n | \"auth_failed\"\n | \"rate_limited\"\n | \"not_found\"\n | \"network\"\n | \"invalid_input\"\n | \"unknown\";\n\n/**\n * Error raised by `@theokit-memory-*` adapters. Carries `adapterId`\n * so callers can branch on which provider failed (ADR D141).\n *\n * @public\n */\nexport class MemoryAdapterError extends TheokitAgentError {\n override readonly name: string = \"MemoryAdapterError\";\n readonly adapterId: string;\n\n constructor(\n message: string,\n options: {\n adapterId: string;\n code: MemoryAdapterErrorCode;\n cause?: unknown;\n metadata?: ErrorMetadata;\n },\n ) {\n super(message, {\n isRetryable: options.code === \"rate_limited\" || options.code === \"network\",\n code: options.code,\n ...(options.cause !== undefined ? { cause: options.cause } : {}),\n ...(options.metadata !== undefined ? { metadata: options.metadata } : {}),\n });\n this.adapterId = options.adapterId;\n }\n}\n\n/**\n * Thrown when a user-supplied task ID violates the grammar\n * `^[a-z0-9][a-z0-9_-]*$` (D368) OR starts with a reserved adapter\n * prefix (`wf-` / `b-` / `cron-`, EC-5).\n *\n * @public\n */\nexport class InvalidTaskIdError extends TheokitAgentError {\n override readonly name: string = \"InvalidTaskIdError\";\n readonly taskId: string;\n\n constructor(message: string, taskId: string, options: { cause?: unknown } = {}) {\n super(message, {\n ...options,\n isRetryable: false,\n code: \"invalid_task_id\",\n });\n this.taskId = taskId;\n }\n}\n\n/**\n * Thrown when `Task.subscribe(id)` is called for a task that has been\n * evicted, never submitted, or evicted after retention (D373).\n *\n * @public\n */\nexport class TaskNotFoundError extends TheokitAgentError {\n override readonly name: string = \"TaskNotFoundError\";\n readonly taskId: string;\n\n constructor(taskId: string, options: { cause?: unknown } = {}) {\n super(`Task not found: ${taskId}`, {\n ...options,\n isRetryable: false,\n code: \"task_not_found\",\n });\n this.taskId = taskId;\n }\n}\n\n/**\n * Thrown when `CloudAgent` is asked to wrap a task (D370). Cloud\n * task observability is deferred until Theo PaaS GA.\n *\n * @public\n */\nexport class UnsupportedTaskOperationError extends TheokitAgentError {\n override readonly name: string = \"UnsupportedTaskOperationError\";\n readonly operation: string;\n\n constructor(operation: string, options: { cause?: unknown } = {}) {\n super(\n `Task operation \"${operation}\" is not supported on CloudAgent (pre-release; see ADR D370)`,\n {\n ...options,\n isRetryable: false,\n code: \"task_op_unsupported\",\n },\n );\n this.operation = operation;\n }\n}\n\n/**\n * Thrown by `Budget` enforcement (ADR D386) when a `mode: \"block\"`\n * budget would be exceeded by the upcoming LLM call. Caller pega\n * tipado para retry-after-window-reset or surface to the user.\n *\n * @public\n */\nexport class BudgetExceededError extends TheokitAgentError {\n override readonly name: string = \"BudgetExceededError\";\n readonly budgetName: string;\n readonly window: import(\"./types/budget.js\").BudgetWindow;\n readonly spentUsd: number;\n readonly limitUsd: number;\n readonly mode: import(\"./types/budget.js\").BudgetMode;\n\n constructor(args: {\n budgetName: string;\n window: import(\"./types/budget.js\").BudgetWindow;\n spentUsd: number;\n limitUsd: number;\n mode: import(\"./types/budget.js\").BudgetMode;\n cause?: unknown;\n }) {\n super(\n `Budget \"${args.budgetName}\" exceeded for window ${args.window}: spent $${args.spentUsd.toFixed(4)} > limit $${args.limitUsd.toFixed(4)}`,\n {\n ...(args.cause !== undefined ? { cause: args.cause } : {}),\n isRetryable: false,\n code: \"budget_exceeded\",\n },\n );\n this.budgetName = args.budgetName;\n this.window = args.window;\n this.spentUsd = args.spentUsd;\n this.limitUsd = args.limitUsd;\n this.mode = args.mode;\n }\n}\n\n/**\n * Thrown when `CloudAgent.send({ budget })` is invoked (D388). Cloud\n * budget surface waits for Theo PaaS GA.\n *\n * @public\n */\n/**\n * T1.6 — Thrown when a consumer calls `agent.send()` or any method\n * on an agent that has already been `dispose()`d. Pre-T1.6 this was\n * a generic `new Error(\"Agent has been disposed\")` — consumers\n * couldn't catch it without string-matching the message.\n *\n * @public\n */\nexport class AgentDisposedError extends TheokitAgentError {\n override readonly name: string = \"AgentDisposedError\";\n readonly agentId: string;\n\n constructor(agentId: string) {\n super(`Agent \"${agentId}\" has been disposed. Create a new agent or use Agent.resume().`, {\n isRetryable: false,\n code: \"agent_disposed\",\n });\n this.agentId = agentId;\n }\n}\n\nexport class UnsupportedBudgetOperationError extends TheokitAgentError {\n override readonly name: string = \"UnsupportedBudgetOperationError\";\n readonly operation: string;\n\n constructor(operation: string, options: { cause?: unknown } = {}) {\n super(\n `Budget operation \"${operation}\" is not supported on CloudAgent (pre-release; see ADR D388)`,\n {\n ...options,\n isRetryable: false,\n code: \"budget_op_unsupported\",\n },\n );\n this.operation = operation;\n }\n}\n","/**\n * PluginManager — constructs PluginContext per plugin, invokes register()\n * once, aggregates registrations + provider profiles + memory factories\n * (T1.3, ADRs D97-D101).\n *\n * @internal\n */\n\nimport { ConfigurationError } from \"../../errors.js\";\nimport type { ProviderProfile } from \"../providers/types.js\";\nimport { createPluginContext, type PluginRegistrations } from \"./context.js\";\nimport type {\n HookHandler,\n HookName,\n LlmCallContext,\n MemoryProviderFactory,\n Plugin,\n PostAssistantReplyContext,\n PostToolCallContext,\n PreToolCallContext,\n PreToolCallDecision,\n PreUserSendContext,\n PreUserSendResult,\n SessionLifecycleContext,\n TransformContext,\n} from \"./types.js\";\n\nexport interface ProviderEntry {\n pluginName: string;\n profile: ProviderProfile;\n}\n\nexport interface MemoryEntry {\n pluginName: string;\n createProvider: MemoryProviderFactory;\n}\n\nexport interface AggregatedPlugins {\n tools: PluginRegistrations[\"tools\"];\n commands: PluginRegistrations[\"commands\"];\n hooks: PluginRegistrations[\"hooks\"];\n injected: PluginRegistrations[\"injected\"];\n providerProfiles: ProviderEntry[];\n memoryProviders: MemoryEntry[];\n}\n\nexport class PluginManager {\n #aggregated: AggregatedPlugins = {\n tools: [],\n commands: [],\n hooks: new Map(),\n injected: [],\n providerProfiles: [],\n memoryProviders: [],\n };\n #initialized = false;\n // #68 — registrations of plugins added post-init via `register()`, keyed by\n // plugin name so a re-register REPLACES (not appends) the prior hooks.\n readonly #byName = new Map<string, PluginRegistrations>();\n\n async initialize(plugins: ReadonlyArray<Plugin>): Promise<void> {\n if (this.#initialized) {\n throw new Error(\"PluginManager.initialize called twice — register only once per process\");\n }\n this.#initialized = true;\n // EC-4: surface duplicate plugin names so operators notice. Two plugins\n // with the same name are usually a mistake (npm install with override).\n const seen = new Set<string>();\n for (const plugin of plugins) {\n if (seen.has(plugin.name)) {\n process.stderr.write(\n `[theokit-sdk] duplicate plugin name \"${plugin.name}\" — both will register independently\\n`,\n );\n }\n seen.add(plugin.name);\n await this.#dispatchPlugin(plugin);\n }\n }\n\n /**\n * #68 — register a single `general` plugin AFTER `initialize()` has run.\n *\n * The bulk `initialize()` is single-shot (one call per process); late\n * registration is a distinct, named operation used by adapters that install\n * a plugin per-session/per-request (e.g. the ACP permission veto, which is\n * installed once the permission mode + connection are known — after the\n * agent's own plugins were already initialized).\n *\n * Idempotent by plugin NAME: re-registering a plugin with the same name\n * REPLACES its prior hooks/tools instead of appending duplicates (the ACP\n * permission plugin is re-installed on every prompt).\n *\n * Only `general` plugins may be registered late — model-provider / memory\n * plugins are resolved during the bulk init and cannot be added afterwards.\n */\n async register(plugin: Plugin): Promise<void> {\n if (plugin.kind !== \"general\") {\n throw new ConfigurationError(\n `late register supports general plugins only (got \"${plugin.kind}\" for \"${plugin.name}\")`,\n { code: \"plugin_late_register_kind\" },\n );\n }\n const prior = this.#byName.get(plugin.name);\n if (prior !== undefined) this.#unmerge(prior);\n const { ctx, registrations } = createPluginContext();\n await plugin.register(ctx);\n this.#byName.set(plugin.name, registrations);\n this.#merge(registrations);\n }\n\n get aggregated(): Readonly<AggregatedPlugins> {\n return this.#aggregated;\n }\n\n /**\n * Run all `pre_tool_call` hooks; first decision with `block: true` wins.\n * D101: veto pattern — return `{ block: true, message }` makes the loop\n * surface a tool_result with `isError: false, content: message` so the\n * LLM can self-correct.\n */\n async runPreToolCallHooks(ctx: PreToolCallContext): Promise<PreToolCallDecision | undefined> {\n const handlers = this.#aggregated.hooks.get(\"pre_tool_call\") ?? [];\n for (const h of handlers) {\n const decision = (await (h as (c: PreToolCallContext) => unknown)(ctx)) as\n | PreToolCallDecision\n | undefined;\n if (decision !== undefined && (decision as { block?: boolean }).block === true) {\n return decision as PreToolCallDecision;\n }\n }\n return undefined;\n }\n\n /** Aggregated handlers for a given hook (read-only view). @internal */\n hooksFor(name: Parameters<AggregatedPlugins[\"hooks\"][\"get\"]>[0]): ReadonlyArray<HookHandler> {\n return this.#aggregated.hooks.get(name) ?? [];\n }\n\n /**\n * Run all `pre_user_send` hooks; concatenate non-empty `recalledContext`\n * outputs with `\\n\\n` and cap total length at `maxRecallContextBytes`\n * (EC-A). Per-handler failures are caught + logged to stderr (EC-8) so a\n * single broken adapter never blocks the LLM call (graceful degrade).\n *\n * Returns the assembled context (or undefined if empty after cap).\n *\n * @internal\n */\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: per-handler try/catch + EC-A cap + EC-8 isolation are 3 concerns that share state (parts buffer); splitting fragments the single-pass aggregation.\n async runPreUserSendHooks(\n ctx: PreUserSendContext,\n maxRecallContextBytes: number,\n ): Promise<string | undefined> {\n const handlers = this.#aggregated.hooks.get(\"pre_user_send\") ?? [];\n if (handlers.length === 0) return undefined;\n const parts: string[] = [];\n for (const h of handlers) {\n try {\n const result = (await (h as (c: PreUserSendContext) => unknown)(ctx)) as\n | PreUserSendResult\n | undefined;\n if (result?.recalledContext && result.recalledContext.length > 0) {\n parts.push(result.recalledContext);\n }\n } catch (err) {\n process.stderr.write(\n `[theokit-sdk] pre_user_send hook failed: ${\n err instanceof Error ? err.message : String(err)\n }\\n`,\n );\n }\n }\n if (parts.length === 0) return undefined;\n let combined = parts.join(\"\\n\\n\");\n // EC-A: cap to prevent context-window blowout.\n if (combined.length > maxRecallContextBytes) {\n combined = `${combined.slice(0, maxRecallContextBytes)}\\n…[truncated]`;\n }\n return combined;\n }\n\n /**\n * Run all `post_assistant_reply` hooks. Fire-and-forget: errors are\n * surfaced to stderr (EC-O) so a slow/broken sync never blocks the\n * caller's `wait()`. Returns a Promise that callers may optionally\n * await for tests; production code typically `void`s it.\n *\n * @internal\n */\n async runPostAssistantReplyHooks(ctx: PostAssistantReplyContext): Promise<void> {\n const handlers = this.#aggregated.hooks.get(\"post_assistant_reply\") ?? [];\n for (const h of handlers) {\n try {\n await (h as (c: PostAssistantReplyContext) => unknown)(ctx);\n } catch (err) {\n process.stderr.write(\n `[theokit-sdk] post_assistant_reply hook failed: ${\n err instanceof Error ? err.message : String(err)\n }\\n`,\n );\n }\n }\n }\n\n // #65 — the previously-dead hooks, now wired. Fire-and-forget hooks run\n // in order (per-handler errors logged, never thrown); transform hooks fold\n // over the payload (a handler returning a value replaces it).\n\n /** @internal */\n async #runFireAndForget<C>(name: HookName, ctx: C): Promise<void> {\n for (const h of this.#aggregated.hooks.get(name) ?? []) {\n try {\n await (h as (c: C) => unknown)(ctx);\n } catch (err) {\n process.stderr.write(\n `[theokit-sdk] ${name} hook failed: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n }\n }\n }\n\n /** @internal — fold: each handler may return a replacement payload; a throw keeps the prior value. */\n async #runTransform<P>(name: HookName, payload: P, ctx: unknown): Promise<P> {\n let current = payload;\n for (const h of this.#aggregated.hooks.get(name) ?? []) {\n try {\n const out = (await (h as (p: P, c: unknown) => unknown)(current, ctx)) as P | undefined;\n if (out !== undefined) current = out;\n } catch (err) {\n process.stderr.write(\n `[theokit-sdk] ${name} hook failed: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n }\n }\n return current;\n }\n\n /** #65 — fired after a tool call completes. @internal */\n runPostToolCallHooks(ctx: PostToolCallContext): Promise<void> {\n return this.#runFireAndForget(\"post_tool_call\", ctx);\n }\n\n /** #65 — fired before / after each LLM turn. @internal */\n runPreLlmCallHooks(ctx: LlmCallContext): Promise<void> {\n return this.#runFireAndForget(\"pre_llm_call\", ctx);\n }\n runPostLlmCallHooks(ctx: LlmCallContext): Promise<void> {\n return this.#runFireAndForget(\"post_llm_call\", ctx);\n }\n\n /** #65 — fired at run start / end. @internal */\n runOnSessionStartHooks(ctx: SessionLifecycleContext): Promise<void> {\n return this.#runFireAndForget(\"on_session_start\", ctx);\n }\n runOnSessionEndHooks(ctx: SessionLifecycleContext): Promise<void> {\n return this.#runFireAndForget(\"on_session_end\", ctx);\n }\n\n /** #65/#57 — transform tool results before they reach the LLM (the #57 seam). @internal */\n runTransformToolResultHooks<T>(results: T, ctx: TransformContext): Promise<T> {\n return this.#runTransform(\"transform_tool_result\", results, ctx);\n }\n\n /** #65 — transform the LLM output text before it is consumed. @internal */\n runTransformLlmOutputHooks(output: string, ctx: TransformContext): Promise<string> {\n return this.#runTransform(\"transform_llm_output\", output, ctx);\n }\n\n async #dispatchPlugin(plugin: Plugin): Promise<void> {\n if (plugin.kind === \"general\") {\n const { ctx, registrations } = createPluginContext();\n await plugin.register(ctx);\n this.#merge(registrations);\n } else if (plugin.kind === \"model-provider\") {\n this.#aggregated.providerProfiles.push({\n pluginName: plugin.name,\n profile: plugin.profile,\n });\n } else if (plugin.kind === \"memory\") {\n this.#aggregated.memoryProviders.push({\n pluginName: plugin.name,\n createProvider: plugin.createProvider,\n });\n }\n }\n\n #merge(r: PluginRegistrations): void {\n this.#aggregated.tools.push(...r.tools);\n this.#aggregated.commands.push(...r.commands);\n for (const [hook, handlers] of r.hooks.entries()) {\n const existing = this.#aggregated.hooks.get(hook) ?? [];\n existing.push(...handlers);\n this.#aggregated.hooks.set(hook, existing);\n }\n this.#aggregated.injected.push(...r.injected);\n }\n\n /**\n * #68 — inverse of #merge: remove a prior registration's contributions from\n * the aggregated view by object identity. Used by `register()` to replace a\n * same-named plugin's hooks/tools instead of accumulating duplicates.\n */\n #unmerge(r: PluginRegistrations): void {\n removeAll(this.#aggregated.tools, r.tools);\n removeAll(this.#aggregated.commands, r.commands);\n removeAll(this.#aggregated.injected, r.injected);\n for (const [hook, handlers] of r.hooks.entries()) {\n const existing = this.#aggregated.hooks.get(hook);\n if (existing === undefined) continue;\n removeAll(existing, handlers);\n if (existing.length === 0) this.#aggregated.hooks.delete(hook);\n }\n }\n}\n\n/** Remove each element of `toRemove` from `arr` in place (by identity). */\nfunction removeAll<T>(arr: T[], toRemove: ReadonlyArray<T>): void {\n for (const item of toRemove) {\n const idx = arr.indexOf(item);\n if (idx !== -1) arr.splice(idx, 1);\n }\n}\n","/**\n * Plugin contract types (T1.1, ADRs D97-D101).\n *\n * Discriminated union by `kind`:\n * - `\"general\"` — registers tools/hooks/commands via `register(ctx)`.\n * - `\"model-provider\"` — declares a `ProviderProfile` consumed by router.\n * - `\"memory\"` — supplies a memory provider factory.\n *\n * Hooks are a fixed enum (D100) to prevent sprawl; `pre_tool_call` supports\n * veto via `{ block: true, message }` (D101) so plugins can implement safety\n * guards without crashing the agent loop.\n *\n * @public\n */\n\nimport type { CustomTool } from \"../../types/agent.js\";\nimport type { MemoryAdapter } from \"../../types/memory-adapter.js\";\nimport type { ProviderProfile } from \"../providers/types.js\";\n\nexport type HookName =\n | \"pre_tool_call\"\n | \"post_tool_call\"\n | \"pre_llm_call\"\n | \"post_llm_call\"\n | \"on_session_start\"\n | \"on_session_end\"\n | \"transform_tool_result\"\n | \"transform_llm_output\"\n // Memory adapter hooks (ADRs D141 / D145).\n | \"pre_user_send\"\n | \"post_assistant_reply\";\n\nexport interface PreToolCallContext {\n name: string;\n args: Record<string, unknown>;\n agentId: string;\n runId: string;\n}\n\nexport interface PreToolCallDecision {\n block: true;\n message: string;\n}\n\n/**\n * #65 — a 2nd argument passed to a tool handler, carrying the run's cancellation\n * signal (ties into #58) so a cooperative tool can stop when the run is\n * cancelled. Optional and additive — existing single-arg handlers are unaffected.\n * (requestConfirmation/requestCredential are a documented follow-up.)\n *\n * @public\n */\nexport interface ToolContext {\n signal?: AbortSignal;\n}\n\n/** #65 — context for the `post_tool_call` hook (fired after a tool runs). @public */\nexport interface PostToolCallContext {\n name: string;\n args: Record<string, unknown>;\n result: { stdout: string; stderr: string; exitCode?: number | null };\n agentId: string;\n runId: string;\n}\n\n/** #65 — context for the `pre_llm_call` / `post_llm_call` hooks. @public */\nexport interface LlmCallContext {\n agentId: string;\n runId: string;\n /** Iteration index (0-based) of the current turn, when available. */\n iteration?: number;\n}\n\n/** #65 — context for the `on_session_start` / `on_session_end` hooks. @public */\nexport interface SessionLifecycleContext {\n agentId: string;\n runId: string;\n}\n\n/** #65 — context for the `transform_tool_result` / `transform_llm_output` hooks. @public */\nexport interface TransformContext {\n agentId: string;\n runId: string;\n}\n\n/**\n * Context passed to `pre_user_send` hook handlers (ADR D145).\n *\n * @public\n */\nexport interface PreUserSendContext {\n prompt: string;\n agentId: string;\n runId: string;\n /** Caller-supplied memory context, flowing through from `AgentOptions.memoryContext`. */\n memoryContext?: import(\"../../types/memory-adapter.js\").MemoryContext;\n /** Forwarded `AbortSignal` so adapter recall HTTP can be cancelled mid-flight (EC-H). */\n signal?: AbortSignal;\n}\n\n/**\n * Optional result returned by `pre_user_send` handlers. The agent loop\n * concatenates `recalledContext` from all handlers and injects it as a\n * `<memory-context>...</memory-context>` block before the user prompt.\n *\n * @public\n */\nexport interface PreUserSendResult {\n recalledContext?: string;\n}\n\n/**\n * Context passed to `post_assistant_reply` hook handlers (ADR D145).\n * Fire-and-forget — exceptions are caught and surfaced to stderr; the\n * caller's `wait()` never blocks on this dispatch.\n *\n * @public\n */\nexport interface PostAssistantReplyContext {\n prompt: string;\n reply: string;\n agentId: string;\n runId: string;\n memoryContext?: import(\"../../types/memory-adapter.js\").MemoryContext;\n}\n\nexport type HookHandler = (ctx: unknown) => unknown | Promise<unknown>;\n\nexport type CommandHandler = (args: Record<string, unknown>) => Promise<string> | string;\n\nexport interface CommandOptions {\n description?: string;\n}\n\nexport interface PluginContext {\n /** Register a custom tool. Equivalent to passing in `AgentOptions.tools`. */\n registerTool(tool: CustomTool): void;\n /** Register a slash-command-style handler. Consumed by CLI/bot wrappers; NOT used by the agent loop. */\n registerCommand(name: string, handler: CommandHandler, opts?: CommandOptions): void;\n /** Attach a hook handler. `pre_tool_call` supports veto via `PreToolCallDecision`. */\n on(hook: HookName, handler: HookHandler): void;\n /** Inject a user/system message into the next agent turn. v1 supports only `on_session_start` context. */\n injectMessage(content: string, role?: \"user\" | \"system\"): void;\n}\n\ninterface BasePlugin {\n name: string;\n version: string;\n}\n\n/**\n * Memory provider factory shape (ADR D141). Returns a `MemoryAdapter`\n * (sync) or a Promise resolving to one (lazy HTTP probe / config load).\n *\n * Adapters live in `@theokit-memory-*` packages; the SDK never imports\n * them. Factory rejection is caught by the plugin manager and surfaced\n * as `ConfigurationError(code: \"plugin_factory_failed\")` (EC-F) — never\n * an unhandled rejection.\n *\n * @internal\n */\nexport type MemoryProviderFactory = (cwd: string) => MemoryAdapter | Promise<MemoryAdapter>;\n\nexport type Plugin =\n | (BasePlugin & {\n kind: \"general\";\n register: (ctx: PluginContext) => void | Promise<void>;\n })\n | (BasePlugin & {\n kind: \"model-provider\";\n profile: ProviderProfile;\n })\n | (BasePlugin & {\n kind: \"memory\";\n createProvider: MemoryProviderFactory;\n });\n\n/**\n * Identity helper for plugin authors. TS-only convenience — preserves\n * inferred type without forcing manual `Plugin` annotation.\n *\n * @public\n */\nexport function definePlugin<P extends Plugin>(p: P): P {\n return p;\n}\n"]}
|
|
@@ -1,357 +0,0 @@
|
|
|
1
|
-
// src/internal/plugins/context.ts
|
|
2
|
-
function createPluginContext() {
|
|
3
|
-
const registrations = {
|
|
4
|
-
tools: [],
|
|
5
|
-
commands: [],
|
|
6
|
-
hooks: /* @__PURE__ */ new Map(),
|
|
7
|
-
injected: []
|
|
8
|
-
};
|
|
9
|
-
const impl = {
|
|
10
|
-
registerTool(tool) {
|
|
11
|
-
registrations.tools.push(tool);
|
|
12
|
-
},
|
|
13
|
-
registerCommand(name, handler, opts = {}) {
|
|
14
|
-
const entry = { name, handler };
|
|
15
|
-
if (opts.description !== void 0) entry.description = opts.description;
|
|
16
|
-
registrations.commands.push(entry);
|
|
17
|
-
},
|
|
18
|
-
on(hook, handler) {
|
|
19
|
-
if (typeof handler !== "function") {
|
|
20
|
-
process.stderr.write(`[theokit-sdk] ignoring non-function handler for hook "${hook}"
|
|
21
|
-
`);
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const existing = registrations.hooks.get(hook) ?? [];
|
|
25
|
-
existing.push(handler);
|
|
26
|
-
registrations.hooks.set(hook, existing);
|
|
27
|
-
},
|
|
28
|
-
injectMessage(content, role = "user") {
|
|
29
|
-
registrations.injected.push({ content, role });
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
const ctx = shouldSeal() ? sealContext(impl) : impl;
|
|
33
|
-
return { ctx, registrations };
|
|
34
|
-
}
|
|
35
|
-
function shouldSeal() {
|
|
36
|
-
return process.env.NODE_ENV !== "production";
|
|
37
|
-
}
|
|
38
|
-
function sealContext(impl) {
|
|
39
|
-
return new Proxy(impl, {
|
|
40
|
-
set(_target, prop) {
|
|
41
|
-
throw new Error(
|
|
42
|
-
`[theokit-sdk] PluginContext is sealed \u2014 cannot set ${String(prop)}. Plugins must use registerTool, registerCommand, on, or injectMessage.`
|
|
43
|
-
);
|
|
44
|
-
},
|
|
45
|
-
deleteProperty(_target, prop) {
|
|
46
|
-
throw new Error(`[theokit-sdk] PluginContext is sealed \u2014 cannot delete ${String(prop)}.`);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// src/internal/plugins/lifecycle.ts
|
|
52
|
-
async function runFireAndForgetHooks(handlers, ctx) {
|
|
53
|
-
for (const h of handlers) {
|
|
54
|
-
try {
|
|
55
|
-
await h(ctx);
|
|
56
|
-
} catch (err) {
|
|
57
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
58
|
-
process.stderr.write(`[theokit-sdk] plugin hook threw (continuing): ${msg}
|
|
59
|
-
`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
async function runTransformHooks(handlers, initial) {
|
|
64
|
-
let current = initial;
|
|
65
|
-
for (const h of handlers) {
|
|
66
|
-
try {
|
|
67
|
-
const next = await h(current);
|
|
68
|
-
if (next !== void 0) current = next;
|
|
69
|
-
} catch (err) {
|
|
70
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
71
|
-
process.stderr.write(`[theokit-sdk] plugin transform hook threw (continuing): ${msg}
|
|
72
|
-
`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return current;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// src/errors.ts
|
|
79
|
-
var TheokitAgentError = class extends Error {
|
|
80
|
-
name = "TheokitAgentError";
|
|
81
|
-
isRetryable;
|
|
82
|
-
code;
|
|
83
|
-
protoErrorCode;
|
|
84
|
-
metadata;
|
|
85
|
-
constructor(message, options = {}) {
|
|
86
|
-
super(message, options.cause !== void 0 ? { cause: options.cause } : void 0);
|
|
87
|
-
this.isRetryable = options.isRetryable ?? false;
|
|
88
|
-
if (options.code !== void 0) this.code = options.code;
|
|
89
|
-
if (options.protoErrorCode !== void 0) this.protoErrorCode = options.protoErrorCode;
|
|
90
|
-
if (options.metadata !== void 0) this.metadata = options.metadata;
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
var ConfigurationError = class extends TheokitAgentError {
|
|
94
|
-
name = "ConfigurationError";
|
|
95
|
-
constructor(message, options = {}) {
|
|
96
|
-
super(message, { ...options, isRetryable: false });
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
// src/internal/plugins/manager.ts
|
|
101
|
-
var PluginManager = class {
|
|
102
|
-
#aggregated = {
|
|
103
|
-
tools: [],
|
|
104
|
-
commands: [],
|
|
105
|
-
hooks: /* @__PURE__ */ new Map(),
|
|
106
|
-
injected: [],
|
|
107
|
-
providerProfiles: [],
|
|
108
|
-
memoryProviders: []
|
|
109
|
-
};
|
|
110
|
-
#initialized = false;
|
|
111
|
-
// #68 — registrations of plugins added post-init via `register()`, keyed by
|
|
112
|
-
// plugin name so a re-register REPLACES (not appends) the prior hooks.
|
|
113
|
-
#byName = /* @__PURE__ */ new Map();
|
|
114
|
-
async initialize(plugins) {
|
|
115
|
-
if (this.#initialized) {
|
|
116
|
-
throw new Error("PluginManager.initialize called twice \u2014 register only once per process");
|
|
117
|
-
}
|
|
118
|
-
this.#initialized = true;
|
|
119
|
-
const seen = /* @__PURE__ */ new Set();
|
|
120
|
-
for (const plugin of plugins) {
|
|
121
|
-
if (seen.has(plugin.name)) {
|
|
122
|
-
process.stderr.write(
|
|
123
|
-
`[theokit-sdk] duplicate plugin name "${plugin.name}" \u2014 both will register independently
|
|
124
|
-
`
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
seen.add(plugin.name);
|
|
128
|
-
await this.#dispatchPlugin(plugin);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* #68 — register a single `general` plugin AFTER `initialize()` has run.
|
|
133
|
-
*
|
|
134
|
-
* The bulk `initialize()` is single-shot (one call per process); late
|
|
135
|
-
* registration is a distinct, named operation used by adapters that install
|
|
136
|
-
* a plugin per-session/per-request (e.g. the ACP permission veto, which is
|
|
137
|
-
* installed once the permission mode + connection are known — after the
|
|
138
|
-
* agent's own plugins were already initialized).
|
|
139
|
-
*
|
|
140
|
-
* Idempotent by plugin NAME: re-registering a plugin with the same name
|
|
141
|
-
* REPLACES its prior hooks/tools instead of appending duplicates (the ACP
|
|
142
|
-
* permission plugin is re-installed on every prompt).
|
|
143
|
-
*
|
|
144
|
-
* Only `general` plugins may be registered late — model-provider / memory
|
|
145
|
-
* plugins are resolved during the bulk init and cannot be added afterwards.
|
|
146
|
-
*/
|
|
147
|
-
async register(plugin) {
|
|
148
|
-
if (plugin.kind !== "general") {
|
|
149
|
-
throw new ConfigurationError(
|
|
150
|
-
`late register supports general plugins only (got "${plugin.kind}" for "${plugin.name}")`,
|
|
151
|
-
{ code: "plugin_late_register_kind" }
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
const prior = this.#byName.get(plugin.name);
|
|
155
|
-
if (prior !== void 0) this.#unmerge(prior);
|
|
156
|
-
const { ctx, registrations } = createPluginContext();
|
|
157
|
-
await plugin.register(ctx);
|
|
158
|
-
this.#byName.set(plugin.name, registrations);
|
|
159
|
-
this.#merge(registrations);
|
|
160
|
-
}
|
|
161
|
-
get aggregated() {
|
|
162
|
-
return this.#aggregated;
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Run all `pre_tool_call` hooks; first decision with `block: true` wins.
|
|
166
|
-
* D101: veto pattern — return `{ block: true, message }` makes the loop
|
|
167
|
-
* surface a tool_result with `isError: false, content: message` so the
|
|
168
|
-
* LLM can self-correct.
|
|
169
|
-
*/
|
|
170
|
-
async runPreToolCallHooks(ctx) {
|
|
171
|
-
const handlers = this.#aggregated.hooks.get("pre_tool_call") ?? [];
|
|
172
|
-
for (const h of handlers) {
|
|
173
|
-
const decision = await h(ctx);
|
|
174
|
-
if (decision !== void 0 && decision.block === true) {
|
|
175
|
-
return decision;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return void 0;
|
|
179
|
-
}
|
|
180
|
-
/** Aggregated handlers for a given hook (read-only view). @internal */
|
|
181
|
-
hooksFor(name) {
|
|
182
|
-
return this.#aggregated.hooks.get(name) ?? [];
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Run all `pre_user_send` hooks; concatenate non-empty `recalledContext`
|
|
186
|
-
* outputs with `\n\n` and cap total length at `maxRecallContextBytes`
|
|
187
|
-
* (EC-A). Per-handler failures are caught + logged to stderr (EC-8) so a
|
|
188
|
-
* single broken adapter never blocks the LLM call (graceful degrade).
|
|
189
|
-
*
|
|
190
|
-
* Returns the assembled context (or undefined if empty after cap).
|
|
191
|
-
*
|
|
192
|
-
* @internal
|
|
193
|
-
*/
|
|
194
|
-
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: per-handler try/catch + EC-A cap + EC-8 isolation are 3 concerns that share state (parts buffer); splitting fragments the single-pass aggregation.
|
|
195
|
-
async runPreUserSendHooks(ctx, maxRecallContextBytes) {
|
|
196
|
-
const handlers = this.#aggregated.hooks.get("pre_user_send") ?? [];
|
|
197
|
-
if (handlers.length === 0) return void 0;
|
|
198
|
-
const parts = [];
|
|
199
|
-
for (const h of handlers) {
|
|
200
|
-
try {
|
|
201
|
-
const result = await h(ctx);
|
|
202
|
-
if (result?.recalledContext && result.recalledContext.length > 0) {
|
|
203
|
-
parts.push(result.recalledContext);
|
|
204
|
-
}
|
|
205
|
-
} catch (err) {
|
|
206
|
-
process.stderr.write(
|
|
207
|
-
`[theokit-sdk] pre_user_send hook failed: ${err instanceof Error ? err.message : String(err)}
|
|
208
|
-
`
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
if (parts.length === 0) return void 0;
|
|
213
|
-
let combined = parts.join("\n\n");
|
|
214
|
-
if (combined.length > maxRecallContextBytes) {
|
|
215
|
-
combined = `${combined.slice(0, maxRecallContextBytes)}
|
|
216
|
-
\u2026[truncated]`;
|
|
217
|
-
}
|
|
218
|
-
return combined;
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Run all `post_assistant_reply` hooks. Fire-and-forget: errors are
|
|
222
|
-
* surfaced to stderr (EC-O) so a slow/broken sync never blocks the
|
|
223
|
-
* caller's `wait()`. Returns a Promise that callers may optionally
|
|
224
|
-
* await for tests; production code typically `void`s it.
|
|
225
|
-
*
|
|
226
|
-
* @internal
|
|
227
|
-
*/
|
|
228
|
-
async runPostAssistantReplyHooks(ctx) {
|
|
229
|
-
const handlers = this.#aggregated.hooks.get("post_assistant_reply") ?? [];
|
|
230
|
-
for (const h of handlers) {
|
|
231
|
-
try {
|
|
232
|
-
await h(ctx);
|
|
233
|
-
} catch (err) {
|
|
234
|
-
process.stderr.write(
|
|
235
|
-
`[theokit-sdk] post_assistant_reply hook failed: ${err instanceof Error ? err.message : String(err)}
|
|
236
|
-
`
|
|
237
|
-
);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// #65 — the previously-dead hooks, now wired. Fire-and-forget hooks run
|
|
242
|
-
// in order (per-handler errors logged, never thrown); transform hooks fold
|
|
243
|
-
// over the payload (a handler returning a value replaces it).
|
|
244
|
-
/** @internal */
|
|
245
|
-
async #runFireAndForget(name, ctx) {
|
|
246
|
-
for (const h of this.#aggregated.hooks.get(name) ?? []) {
|
|
247
|
-
try {
|
|
248
|
-
await h(ctx);
|
|
249
|
-
} catch (err) {
|
|
250
|
-
process.stderr.write(
|
|
251
|
-
`[theokit-sdk] ${name} hook failed: ${err instanceof Error ? err.message : String(err)}
|
|
252
|
-
`
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
/** @internal — fold: each handler may return a replacement payload; a throw keeps the prior value. */
|
|
258
|
-
async #runTransform(name, payload, ctx) {
|
|
259
|
-
let current = payload;
|
|
260
|
-
for (const h of this.#aggregated.hooks.get(name) ?? []) {
|
|
261
|
-
try {
|
|
262
|
-
const out = await h(current, ctx);
|
|
263
|
-
if (out !== void 0) current = out;
|
|
264
|
-
} catch (err) {
|
|
265
|
-
process.stderr.write(
|
|
266
|
-
`[theokit-sdk] ${name} hook failed: ${err instanceof Error ? err.message : String(err)}
|
|
267
|
-
`
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
return current;
|
|
272
|
-
}
|
|
273
|
-
/** #65 — fired after a tool call completes. @internal */
|
|
274
|
-
runPostToolCallHooks(ctx) {
|
|
275
|
-
return this.#runFireAndForget("post_tool_call", ctx);
|
|
276
|
-
}
|
|
277
|
-
/** #65 — fired before / after each LLM turn. @internal */
|
|
278
|
-
runPreLlmCallHooks(ctx) {
|
|
279
|
-
return this.#runFireAndForget("pre_llm_call", ctx);
|
|
280
|
-
}
|
|
281
|
-
runPostLlmCallHooks(ctx) {
|
|
282
|
-
return this.#runFireAndForget("post_llm_call", ctx);
|
|
283
|
-
}
|
|
284
|
-
/** #65 — fired at run start / end. @internal */
|
|
285
|
-
runOnSessionStartHooks(ctx) {
|
|
286
|
-
return this.#runFireAndForget("on_session_start", ctx);
|
|
287
|
-
}
|
|
288
|
-
runOnSessionEndHooks(ctx) {
|
|
289
|
-
return this.#runFireAndForget("on_session_end", ctx);
|
|
290
|
-
}
|
|
291
|
-
/** #65/#57 — transform tool results before they reach the LLM (the #57 seam). @internal */
|
|
292
|
-
runTransformToolResultHooks(results, ctx) {
|
|
293
|
-
return this.#runTransform("transform_tool_result", results, ctx);
|
|
294
|
-
}
|
|
295
|
-
/** #65 — transform the LLM output text before it is consumed. @internal */
|
|
296
|
-
runTransformLlmOutputHooks(output, ctx) {
|
|
297
|
-
return this.#runTransform("transform_llm_output", output, ctx);
|
|
298
|
-
}
|
|
299
|
-
async #dispatchPlugin(plugin) {
|
|
300
|
-
if (plugin.kind === "general") {
|
|
301
|
-
const { ctx, registrations } = createPluginContext();
|
|
302
|
-
await plugin.register(ctx);
|
|
303
|
-
this.#merge(registrations);
|
|
304
|
-
} else if (plugin.kind === "model-provider") {
|
|
305
|
-
this.#aggregated.providerProfiles.push({
|
|
306
|
-
pluginName: plugin.name,
|
|
307
|
-
profile: plugin.profile
|
|
308
|
-
});
|
|
309
|
-
} else if (plugin.kind === "memory") {
|
|
310
|
-
this.#aggregated.memoryProviders.push({
|
|
311
|
-
pluginName: plugin.name,
|
|
312
|
-
createProvider: plugin.createProvider
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
#merge(r) {
|
|
317
|
-
this.#aggregated.tools.push(...r.tools);
|
|
318
|
-
this.#aggregated.commands.push(...r.commands);
|
|
319
|
-
for (const [hook, handlers] of r.hooks.entries()) {
|
|
320
|
-
const existing = this.#aggregated.hooks.get(hook) ?? [];
|
|
321
|
-
existing.push(...handlers);
|
|
322
|
-
this.#aggregated.hooks.set(hook, existing);
|
|
323
|
-
}
|
|
324
|
-
this.#aggregated.injected.push(...r.injected);
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* #68 — inverse of #merge: remove a prior registration's contributions from
|
|
328
|
-
* the aggregated view by object identity. Used by `register()` to replace a
|
|
329
|
-
* same-named plugin's hooks/tools instead of accumulating duplicates.
|
|
330
|
-
*/
|
|
331
|
-
#unmerge(r) {
|
|
332
|
-
removeAll(this.#aggregated.tools, r.tools);
|
|
333
|
-
removeAll(this.#aggregated.commands, r.commands);
|
|
334
|
-
removeAll(this.#aggregated.injected, r.injected);
|
|
335
|
-
for (const [hook, handlers] of r.hooks.entries()) {
|
|
336
|
-
const existing = this.#aggregated.hooks.get(hook);
|
|
337
|
-
if (existing === void 0) continue;
|
|
338
|
-
removeAll(existing, handlers);
|
|
339
|
-
if (existing.length === 0) this.#aggregated.hooks.delete(hook);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
};
|
|
343
|
-
function removeAll(arr, toRemove) {
|
|
344
|
-
for (const item of toRemove) {
|
|
345
|
-
const idx = arr.indexOf(item);
|
|
346
|
-
if (idx !== -1) arr.splice(idx, 1);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// src/internal/plugins/types.ts
|
|
351
|
-
function definePlugin(p) {
|
|
352
|
-
return p;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
export { PluginManager, createPluginContext, definePlugin, runFireAndForgetHooks, runTransformHooks };
|
|
356
|
-
//# sourceMappingURL=index.js.map
|
|
357
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internal/plugins/context.ts","../../../src/internal/plugins/lifecycle.ts","../../../src/errors.ts","../../../src/internal/plugins/manager.ts","../../../src/internal/plugins/types.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * PluginContext implementation + dev-mode seal (T1.2, ADR D99).\n *\n * `createPluginContext()` returns a fresh `{ ctx, registrations }` pair\n * for each plugin. In dev mode (`NODE_ENV !== \"production\"`) the context\n * is wrapped in a Proxy that throws on `set`/`delete` to catch plugin\n * abuse early. In production the raw impl is returned (zero overhead).\n *\n * @internal\n */\n\nimport type { CustomTool } from \"../../types/agent.js\";\nimport type {\n CommandHandler,\n CommandOptions,\n HookHandler,\n HookName,\n PluginContext,\n} from \"./types.js\";\n\ninterface CommandEntry {\n name: string;\n handler: CommandHandler;\n description?: string;\n}\n\ninterface InjectedMessage {\n content: string;\n role: \"user\" | \"system\";\n}\n\nexport interface PluginRegistrations {\n tools: CustomTool[];\n commands: CommandEntry[];\n hooks: Map<HookName, HookHandler[]>;\n injected: InjectedMessage[];\n}\n\nexport function createPluginContext(): {\n ctx: PluginContext;\n registrations: PluginRegistrations;\n} {\n const registrations: PluginRegistrations = {\n tools: [],\n commands: [],\n hooks: new Map(),\n injected: [],\n };\n\n const impl: PluginContext = {\n registerTool(tool) {\n registrations.tools.push(tool);\n },\n registerCommand(name, handler, opts: CommandOptions = {}) {\n const entry: CommandEntry = { name, handler };\n if (opts.description !== undefined) entry.description = opts.description;\n registrations.commands.push(entry);\n },\n on(hook, handler) {\n // EC-2 fix: defense-in-depth. Plugin author can bypass TS via `as any`\n // and pass null/undefined; ignore + warn rather than crash the loop\n // downstream when `runPreToolCallHooks` tries to invoke the handler.\n if (typeof handler !== \"function\") {\n process.stderr.write(`[theokit-sdk] ignoring non-function handler for hook \"${hook}\"\\n`);\n return;\n }\n const existing = registrations.hooks.get(hook) ?? [];\n existing.push(handler);\n registrations.hooks.set(hook, existing);\n },\n injectMessage(content, role = \"user\") {\n registrations.injected.push({ content, role });\n },\n };\n\n const ctx = shouldSeal() ? sealContext(impl) : impl;\n return { ctx, registrations };\n}\n\nfunction shouldSeal(): boolean {\n return process.env.NODE_ENV !== \"production\";\n}\n\nfunction sealContext(impl: PluginContext): PluginContext {\n return new Proxy(impl, {\n set(_target, prop) {\n throw new Error(\n `[theokit-sdk] PluginContext is sealed — cannot set ${String(prop)}. ` +\n `Plugins must use registerTool, registerCommand, on, or injectMessage.`,\n );\n },\n deleteProperty(_target, prop) {\n throw new Error(`[theokit-sdk] PluginContext is sealed — cannot delete ${String(prop)}.`);\n },\n });\n}\n","/**\n * Hook dispatch helpers (T1.4, extracted from manager to keep both modules\n * small).\n *\n * - `runFireAndForgetHooks` — runs all handlers, swallows + logs throws,\n * no return value (post_tool_call, on_session_start/end, etc.).\n * - `runTransformHooks` — chains handlers, each can return a new value\n * that replaces the input for the next handler. `undefined` keeps the\n * current; `null` REPLACES current with null (EC-6 explicit).\n *\n * @internal\n */\n\nimport type { HookHandler } from \"./types.js\";\n\nexport async function runFireAndForgetHooks<C>(\n handlers: ReadonlyArray<HookHandler>,\n ctx: C,\n): Promise<void> {\n for (const h of handlers) {\n try {\n await (h as (c: C) => unknown)(ctx);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[theokit-sdk] plugin hook threw (continuing): ${msg}\\n`);\n }\n }\n}\n\nexport async function runTransformHooks<T>(\n handlers: ReadonlyArray<HookHandler>,\n initial: T,\n): Promise<T> {\n let current = initial;\n for (const h of handlers) {\n try {\n const next = await (h as (c: T) => T | undefined)(current);\n // EC-6 explicit semantics: `undefined` = no-op; any other value\n // (including `null`) REPLACES current.\n if (next !== undefined) current = next;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[theokit-sdk] plugin transform hook threw (continuing): ${msg}\\n`);\n }\n }\n return current;\n}\n","import { defaultRetriableForCode } from \"./internal/default-retriable.js\";\nimport { redactSecrets } from \"./internal/security/redact.js\";\nimport type { RunOperation } from \"./types/run.js\";\n\n/**\n * Finite, machine-readable error codes for provider-originated errors\n * (ADR D66). Consumers can `switch (err.metadata?.code)` exhaustively\n * — adding a new variant is an explicit decision + test coverage.\n *\n * @public\n */\nexport type ErrorCode =\n | \"rate_limit\"\n | \"auth_failed\"\n | \"invalid_request\"\n | \"timeout\"\n | \"server_error\"\n | \"context_too_long\"\n | \"content_filtered\"\n | \"model_unavailable\"\n | \"network\"\n | \"quota_exceeded\"\n | \"unknown\";\n\n/**\n * Codes used by {@link AgentRunError} (Production-Readiness #3, ADR D311).\n *\n * Superset of {@link ErrorCode} extended with codes that do NOT originate\n * from a provider HTTP response:\n *\n * - `quota_exceeded` — billing limit hit (provider 402 or signalled error)\n * - `tool_runtime_error` — custom tool handler threw inside dispatch\n * - `aborted` — caller's `AbortSignal` fired (Phase 4)\n * - `invalid_model` — model id rejected by provider (400 \"model not found\")\n * - `safety_blocked` — provider safety filter blocked req or resp\n * - `provider_unreachable` — DNS/TCP/timeout/5xx at transport boundary\n *\n * The `& {}` tail keeps the literal-union ergonomics (autocomplete) while\n * accepting any string for forward compatibility with constructor calls\n * that pass arbitrary code values (legacy callers).\n *\n * @public\n */\n/**\n * T1.1 — closed literal union for `AgentRunError.code`. The previous\n * `(string & {})` escape hatch let arbitrary strings slip into the type\n * surface and defeated exhaustive `switch (code)` discrimination. This is\n * the canonical closed form. `AgentRunErrorCode` is re-aliased below for\n * source-level back-compat.\n *\n * Adding a new code: append the literal here AND audit every `switch (err.code)`\n * in callers. Type-checker enforces the audit via the `default: assertNever(code)`\n * convention.\n *\n * @public\n */\nexport type KnownAgentRunErrorCode =\n | ErrorCode\n | \"quota_exceeded\"\n | \"tool_runtime_error\"\n | \"aborted\"\n | \"invalid_model\"\n | \"safety_blocked\"\n | \"provider_unreachable\";\n\n/**\n * Back-compat alias of {@link KnownAgentRunErrorCode}. Pre-T1.1 callers that\n * imported `AgentRunErrorCode` keep working; new code SHOULD prefer\n * `KnownAgentRunErrorCode` to make the closed-union intent explicit.\n *\n * @public\n */\nexport type AgentRunErrorCode = KnownAgentRunErrorCode;\n\n/** Snapshot of every known code at runtime — used by the boundary coercer. */\nconst KNOWN_AGENT_RUN_ERROR_CODES = new Set<string>([\n \"rate_limit\",\n \"auth_failed\",\n \"invalid_request\",\n \"timeout\",\n \"server_error\",\n \"context_too_long\",\n \"content_filtered\",\n \"model_unavailable\",\n \"network\",\n \"unknown\",\n \"quota_exceeded\",\n \"tool_runtime_error\",\n \"aborted\",\n \"invalid_model\",\n \"safety_blocked\",\n \"provider_unreachable\",\n]);\n\n/**\n * T1.1 boundary helper — coerce an arbitrary string (typically arriving from\n * a downstream `RunErrorDetail.code` or a deserialized cloud response) into a\n * `KnownAgentRunErrorCode`. Unknown strings collapse to `\"unknown\"` so the\n * closed type contract holds without forcing every caller to switch.\n *\n * @internal\n */\nexport function coerceToKnownAgentRunErrorCode(code: string | undefined): KnownAgentRunErrorCode {\n if (code !== undefined && KNOWN_AGENT_RUN_ERROR_CODES.has(code)) {\n return code as KnownAgentRunErrorCode;\n }\n return \"unknown\";\n}\n\n/**\n * Structured context for errors that originated from a provider HTTP\n * call (ADR D65). Lets callers retry with the right backoff (`retryAfter`),\n * surface actionable diagnostics (`provider`, `endpoint`), and inspect the\n * raw response body when needed (`raw`, capped at ~2KB by the mapper).\n *\n * @public\n */\nexport interface ErrorMetadata {\n /** Provider canonical name (e.g., `\"anthropic\"`, `\"openai\"`, `\"openrouter\"`, `\"gemini\"`). */\n provider: string;\n /** HTTP endpoint that failed (e.g., `\"/v1/messages\"`, `\"/v1/chat/completions\"`). */\n endpoint: string;\n /** Machine-readable error code (finite enum). */\n code: ErrorCode;\n /** HTTP status code if applicable. */\n statusCode?: number;\n /** Seconds to wait before retry, per provider's `retry-after` header (numeric form only). */\n retryAfter?: number;\n /** Raw response body for debugging (truncated to ~2KB by the mapper). */\n raw?: unknown;\n}\n\n/**\n * Base class for all errors thrown by `@theokit/sdk`.\n *\n * Use `isRetryable` to drive retry/backoff logic. `code` and `protoErrorCode`\n * are populated for server-originated errors when available. `metadata`\n * (ADR D65) carries structured `{ provider, endpoint, code, ... }` when\n * the error originated from a provider HTTP call.\n *\n * @public\n */\nexport class TheokitAgentError extends Error {\n override readonly name: string = \"TheokitAgentError\";\n readonly isRetryable: boolean;\n readonly code?: string;\n readonly protoErrorCode?: string;\n readonly metadata?: ErrorMetadata;\n\n constructor(\n message: string,\n options: {\n isRetryable?: boolean;\n code?: string;\n protoErrorCode?: string;\n cause?: unknown;\n metadata?: ErrorMetadata;\n } = {},\n ) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined);\n this.isRetryable = options.isRetryable ?? false;\n if (options.code !== undefined) this.code = options.code;\n if (options.protoErrorCode !== undefined) this.protoErrorCode = options.protoErrorCode;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n}\n\n/**\n * Invalid API key, not logged in, insufficient permissions.\n *\n * @public\n */\nexport class AuthenticationError extends TheokitAgentError {\n override readonly name: string = \"AuthenticationError\";\n\n constructor(\n message: string,\n options: { code?: string; cause?: unknown; metadata?: ErrorMetadata } = {},\n ) {\n super(message, { ...options, isRetryable: false });\n }\n}\n\n/**\n * Too many requests or usage limits exceeded.\n *\n * @public\n */\nexport class RateLimitError extends TheokitAgentError {\n override readonly name: string = \"RateLimitError\";\n\n constructor(\n message: string,\n options: { code?: string; cause?: unknown; metadata?: ErrorMetadata } = {},\n ) {\n super(message, { ...options, isRetryable: true });\n }\n}\n\n/**\n * Invalid model, bad request parameters, malformed options.\n *\n * @public\n */\nexport class ConfigurationError extends TheokitAgentError {\n override readonly name: string = \"ConfigurationError\";\n\n constructor(\n message: string,\n options: { code?: string; cause?: unknown; metadata?: ErrorMetadata } = {},\n ) {\n super(message, { ...options, isRetryable: false });\n }\n}\n\n/**\n * Thrown when creating a cloud agent for a repo whose SCM provider is not\n * connected. Use `helpUrl` to point the user at the right reconnect flow.\n *\n * @public\n */\nexport class IntegrationNotConnectedError extends ConfigurationError {\n override readonly name: string = \"IntegrationNotConnectedError\";\n readonly provider: string;\n readonly helpUrl: string;\n\n constructor(\n message: string,\n options: {\n provider: string;\n helpUrl: string;\n code?: string;\n cause?: unknown;\n metadata?: ErrorMetadata;\n },\n ) {\n super(message, options);\n this.provider = options.provider;\n this.helpUrl = options.helpUrl;\n }\n}\n\n/**\n * Service unavailable, timeout, transport-level failure.\n *\n * @public\n */\nexport class NetworkError extends TheokitAgentError {\n override readonly name: string = \"NetworkError\";\n\n constructor(\n message: string,\n options: { code?: string; cause?: unknown; metadata?: ErrorMetadata } = {},\n ) {\n super(message, { ...options, isRetryable: true });\n }\n}\n\n/**\n * Catch-all for unclassified server or runtime errors.\n *\n * @public\n */\nexport class UnknownAgentError extends TheokitAgentError {\n override readonly name: string = \"UnknownAgentError\";\n\n constructor(\n message: string,\n options: { code?: string; cause?: unknown; metadata?: ErrorMetadata } = {},\n ) {\n super(message, { ...options, isRetryable: false });\n }\n}\n\n/**\n * Thrown by `Agent.prompt` (and helpers that go through `run.wait()`) when\n * the option `{ throwOnError: true }` is set and the run terminates with\n * `status: 'error'`. Carries the structured `RunResult.error` fields so\n * callers can `catch` once and branch on `code` / `provider` instead of\n * unwrapping the run.\n *\n * Extends {@link TheokitAgentError} per ADR D65 — no new hierarchy.\n *\n * @example\n * try {\n * await Agent.prompt(msg, { apiKey, model, throwOnError: true });\n * } catch (err) {\n * if (err instanceof AgentRunError && err.code === 'auth_failed') {\n * // bad key\n * }\n * }\n *\n * @public\n */\nexport class AgentRunError extends TheokitAgentError {\n override readonly name: string = \"AgentRunError\";\n readonly provider?: string;\n readonly raw?: string;\n /** Provider's request id (`x-request-id` / `request-id` header). Useful for support tickets. */\n readonly requestId?: string;\n /** SDK conversation id this error was raised inside. */\n readonly conversationId?: string;\n\n constructor(\n message: string,\n options: {\n code: AgentRunErrorCode;\n provider?: string;\n raw?: string;\n requestId?: string;\n conversationId?: string;\n retriable?: boolean;\n cause?: unknown;\n metadata?: ErrorMetadata;\n },\n ) {\n super(message, {\n code: options.code,\n cause: options.cause,\n metadata: options.metadata,\n // D311: most AgentRunErrors are not retriable (auth, validation, abort).\n // Provider mappers (D314) override per-status — explicit `retriable` wins\n // over the implicit default when supplied.\n isRetryable: options.retriable ?? defaultRetriableForCode(options.code),\n });\n if (options.provider !== undefined) this.provider = options.provider;\n if (options.raw !== undefined) this.raw = options.raw;\n if (options.requestId !== undefined) this.requestId = options.requestId;\n if (options.conversationId !== undefined) this.conversationId = options.conversationId;\n }\n\n /**\n * Production-Readiness #3 (ADR D311): alias for `isRetryable` exposed as\n * `retriable` to match the handoff contract. Future v2 will deprecate\n * `isRetryable` in favor of this.\n */\n get retriable(): boolean {\n return this.isRetryable;\n }\n\n /**\n * D312: provider's `Retry-After` header in **milliseconds**. Mappers store\n * the header value (seconds) in `metadata.retryAfter`; this getter\n * multiplies by 1000 so the result composes with `Date.now()`/`setTimeout`.\n *\n * Returns `undefined` when no hint was provided. `0` is a legitimate value\n * — use `=== undefined` check rather than truthy check.\n */\n get retryAfterMs(): number | undefined {\n if (this.metadata?.retryAfter === undefined) return undefined;\n return this.metadata.retryAfter * 1000;\n }\n\n /**\n * D313 + T1.5: alias for `metadata.raw`. Provider response body for\n * debugging. T1.5 wraps the value in `redactSecrets` at the getter\n * boundary so secret-shaped substrings (`sk-...`, Bearer JWTs, etc.) are\n * stripped before reaching the caller. Available but NEVER serialized\n * into `.message` (anti-leak invariant).\n */\n get providerError(): unknown {\n const raw = this.metadata?.raw;\n if (raw === undefined) return undefined;\n if (typeof raw === \"string\") return redactSecrets(raw);\n // Non-string raw (object/buffer) — stringify then redact.\n try {\n return redactSecrets(JSON.stringify(raw));\n } catch {\n return redactSecrets(String(raw));\n }\n }\n\n /**\n * T1.5 — sanitized JSON form. `metadata.raw` is OMITTED by default; opt\n * in via `THEOKIT_DEBUG_RAW_ERRORS=1` to surface the (redacted) raw\n * payload for diagnostics. Every other field stays accessible.\n *\n * The single env-var gate is read each call so operators can toggle at\n * runtime without restarting the process.\n */\n toJSON(): Record<string, unknown> {\n const json: Record<string, unknown> = {\n name: this.name,\n message: this.message,\n isRetryable: this.isRetryable,\n };\n addOptionalFields(json, this);\n const safeMeta = sanitizeMetadata(this.metadata);\n if (safeMeta !== undefined) json.metadata = safeMeta;\n return json;\n }\n}\n\nfunction addOptionalFields(json: Record<string, unknown>, err: AgentRunError): void {\n if (err.code !== undefined) json.code = err.code;\n if (err.provider !== undefined) json.provider = err.provider;\n if (err.requestId !== undefined) json.requestId = err.requestId;\n if (err.conversationId !== undefined) json.conversationId = err.conversationId;\n if (err.raw !== undefined) json.raw = redactSecrets(err.raw);\n}\n\nfunction sanitizeMetadata(meta: ErrorMetadata | undefined): ErrorMetadata | undefined {\n if (meta === undefined) return undefined;\n const { raw, ...rest } = meta;\n const debugRaw = process.env.THEOKIT_DEBUG_RAW_ERRORS === \"1\";\n if (debugRaw && raw !== undefined) {\n const redactedRaw =\n typeof raw === \"string\" ? redactSecrets(raw) : redactSecrets(safeStringify(raw));\n return { ...rest, raw: redactedRaw } as ErrorMetadata;\n }\n return rest as ErrorMetadata;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n/**\n * Is this error transient (worth retrying)?\n *\n * Returns the SDK's own retryability verdict: every {@link TheokitAgentError}\n * subclass computes `isRetryable` at construction (rate-limit / network /\n * credential-pool-exhausted are retryable; auth / configuration / unsupported\n * are not), so this predicate is a single source of truth rather than a\n * re-derivation. Non-SDK errors return `false` conservatively — wrap a foreign\n * error in the appropriate SDK error first if you want it considered transient.\n * It never inspects `err.message`.\n *\n * @example\n * try {\n * await agent.send(message, { throwOnError: true });\n * } catch (err) {\n * if (isTransientError(err)) return retryWithBackoff();\n * throw err;\n * }\n *\n * @public\n */\nexport function isTransientError(err: unknown): boolean {\n return err instanceof TheokitAgentError && err.isRetryable === true;\n}\n\n/**\n * Thrown when a {@link Run} or agent operation is not available on the current\n * runtime. Check first with `run.supports(operation)`.\n *\n * Extends {@link TheokitAgentError} (so error-catching code that branches on\n * `instanceof TheokitAgentError` continues to work) but is never retryable —\n * an unsupported operation will not become supported on retry.\n *\n * @public\n */\nexport class UnsupportedRunOperationError extends TheokitAgentError {\n override readonly name: string = \"UnsupportedRunOperationError\";\n readonly operation: RunOperation;\n\n constructor(\n message: string,\n operation: RunOperation,\n options: { code?: string; cause?: unknown } = {},\n ) {\n super(message, {\n ...options,\n isRetryable: false,\n code: options.code ?? \"unsupported_run_operation\",\n });\n this.operation = operation;\n }\n}\n\n/**\n * Thrown when every credential in a per-provider pool is in cooldown\n * and no healthy key is available (ADR D133). The caller's\n * {@link import(\"./internal/llm/fallback-client.js\").FallbackLlmClient}\n * catches this and tries the next provider in the fallback chain.\n *\n * `metadata.nextRetryAt` (epoch ms) tells callers when the soonest\n * pool entry resumes — useful for manual retry scheduling.\n *\n * @public\n */\nexport class CredentialPoolExhaustedError extends TheokitAgentError {\n override readonly name: string = \"CredentialPoolExhaustedError\";\n readonly provider: string;\n readonly nextRetryAt: number | undefined;\n\n constructor(\n message: string,\n options: {\n provider: string;\n nextRetryAt?: number;\n code?: string;\n cause?: unknown;\n metadata?: ErrorMetadata;\n },\n ) {\n super(message, {\n ...options,\n isRetryable: true,\n code: options.code ?? \"credential_pool_exhausted\",\n });\n this.provider = options.provider;\n this.nextRetryAt = options.nextRetryAt;\n }\n}\n\n/**\n * Finite error codes specific to memory adapter operations (ADR D141).\n *\n * @public\n */\nexport type MemoryAdapterErrorCode =\n | \"auth_failed\"\n | \"rate_limited\"\n | \"not_found\"\n | \"network\"\n | \"invalid_input\"\n | \"unknown\";\n\n/**\n * Error raised by `@theokit-memory-*` adapters. Carries `adapterId`\n * so callers can branch on which provider failed (ADR D141).\n *\n * @public\n */\nexport class MemoryAdapterError extends TheokitAgentError {\n override readonly name: string = \"MemoryAdapterError\";\n readonly adapterId: string;\n\n constructor(\n message: string,\n options: {\n adapterId: string;\n code: MemoryAdapterErrorCode;\n cause?: unknown;\n metadata?: ErrorMetadata;\n },\n ) {\n super(message, {\n isRetryable: options.code === \"rate_limited\" || options.code === \"network\",\n code: options.code,\n ...(options.cause !== undefined ? { cause: options.cause } : {}),\n ...(options.metadata !== undefined ? { metadata: options.metadata } : {}),\n });\n this.adapterId = options.adapterId;\n }\n}\n\n/**\n * Thrown when a user-supplied task ID violates the grammar\n * `^[a-z0-9][a-z0-9_-]*$` (D368) OR starts with a reserved adapter\n * prefix (`wf-` / `b-` / `cron-`, EC-5).\n *\n * @public\n */\nexport class InvalidTaskIdError extends TheokitAgentError {\n override readonly name: string = \"InvalidTaskIdError\";\n readonly taskId: string;\n\n constructor(message: string, taskId: string, options: { cause?: unknown } = {}) {\n super(message, {\n ...options,\n isRetryable: false,\n code: \"invalid_task_id\",\n });\n this.taskId = taskId;\n }\n}\n\n/**\n * Thrown when `Task.subscribe(id)` is called for a task that has been\n * evicted, never submitted, or evicted after retention (D373).\n *\n * @public\n */\nexport class TaskNotFoundError extends TheokitAgentError {\n override readonly name: string = \"TaskNotFoundError\";\n readonly taskId: string;\n\n constructor(taskId: string, options: { cause?: unknown } = {}) {\n super(`Task not found: ${taskId}`, {\n ...options,\n isRetryable: false,\n code: \"task_not_found\",\n });\n this.taskId = taskId;\n }\n}\n\n/**\n * Thrown when `CloudAgent` is asked to wrap a task (D370). Cloud\n * task observability is deferred until Theo PaaS GA.\n *\n * @public\n */\nexport class UnsupportedTaskOperationError extends TheokitAgentError {\n override readonly name: string = \"UnsupportedTaskOperationError\";\n readonly operation: string;\n\n constructor(operation: string, options: { cause?: unknown } = {}) {\n super(\n `Task operation \"${operation}\" is not supported on CloudAgent (pre-release; see ADR D370)`,\n {\n ...options,\n isRetryable: false,\n code: \"task_op_unsupported\",\n },\n );\n this.operation = operation;\n }\n}\n\n/**\n * Thrown by `Budget` enforcement (ADR D386) when a `mode: \"block\"`\n * budget would be exceeded by the upcoming LLM call. Caller pega\n * tipado para retry-after-window-reset or surface to the user.\n *\n * @public\n */\nexport class BudgetExceededError extends TheokitAgentError {\n override readonly name: string = \"BudgetExceededError\";\n readonly budgetName: string;\n readonly window: import(\"./types/budget.js\").BudgetWindow;\n readonly spentUsd: number;\n readonly limitUsd: number;\n readonly mode: import(\"./types/budget.js\").BudgetMode;\n\n constructor(args: {\n budgetName: string;\n window: import(\"./types/budget.js\").BudgetWindow;\n spentUsd: number;\n limitUsd: number;\n mode: import(\"./types/budget.js\").BudgetMode;\n cause?: unknown;\n }) {\n super(\n `Budget \"${args.budgetName}\" exceeded for window ${args.window}: spent $${args.spentUsd.toFixed(4)} > limit $${args.limitUsd.toFixed(4)}`,\n {\n ...(args.cause !== undefined ? { cause: args.cause } : {}),\n isRetryable: false,\n code: \"budget_exceeded\",\n },\n );\n this.budgetName = args.budgetName;\n this.window = args.window;\n this.spentUsd = args.spentUsd;\n this.limitUsd = args.limitUsd;\n this.mode = args.mode;\n }\n}\n\n/**\n * Thrown when `CloudAgent.send({ budget })` is invoked (D388). Cloud\n * budget surface waits for Theo PaaS GA.\n *\n * @public\n */\n/**\n * T1.6 — Thrown when a consumer calls `agent.send()` or any method\n * on an agent that has already been `dispose()`d. Pre-T1.6 this was\n * a generic `new Error(\"Agent has been disposed\")` — consumers\n * couldn't catch it without string-matching the message.\n *\n * @public\n */\nexport class AgentDisposedError extends TheokitAgentError {\n override readonly name: string = \"AgentDisposedError\";\n readonly agentId: string;\n\n constructor(agentId: string) {\n super(`Agent \"${agentId}\" has been disposed. Create a new agent or use Agent.resume().`, {\n isRetryable: false,\n code: \"agent_disposed\",\n });\n this.agentId = agentId;\n }\n}\n\nexport class UnsupportedBudgetOperationError extends TheokitAgentError {\n override readonly name: string = \"UnsupportedBudgetOperationError\";\n readonly operation: string;\n\n constructor(operation: string, options: { cause?: unknown } = {}) {\n super(\n `Budget operation \"${operation}\" is not supported on CloudAgent (pre-release; see ADR D388)`,\n {\n ...options,\n isRetryable: false,\n code: \"budget_op_unsupported\",\n },\n );\n this.operation = operation;\n }\n}\n","/**\n * PluginManager — constructs PluginContext per plugin, invokes register()\n * once, aggregates registrations + provider profiles + memory factories\n * (T1.3, ADRs D97-D101).\n *\n * @internal\n */\n\nimport { ConfigurationError } from \"../../errors.js\";\nimport type { ProviderProfile } from \"../providers/types.js\";\nimport { createPluginContext, type PluginRegistrations } from \"./context.js\";\nimport type {\n HookHandler,\n HookName,\n LlmCallContext,\n MemoryProviderFactory,\n Plugin,\n PostAssistantReplyContext,\n PostToolCallContext,\n PreToolCallContext,\n PreToolCallDecision,\n PreUserSendContext,\n PreUserSendResult,\n SessionLifecycleContext,\n TransformContext,\n} from \"./types.js\";\n\nexport interface ProviderEntry {\n pluginName: string;\n profile: ProviderProfile;\n}\n\nexport interface MemoryEntry {\n pluginName: string;\n createProvider: MemoryProviderFactory;\n}\n\nexport interface AggregatedPlugins {\n tools: PluginRegistrations[\"tools\"];\n commands: PluginRegistrations[\"commands\"];\n hooks: PluginRegistrations[\"hooks\"];\n injected: PluginRegistrations[\"injected\"];\n providerProfiles: ProviderEntry[];\n memoryProviders: MemoryEntry[];\n}\n\nexport class PluginManager {\n #aggregated: AggregatedPlugins = {\n tools: [],\n commands: [],\n hooks: new Map(),\n injected: [],\n providerProfiles: [],\n memoryProviders: [],\n };\n #initialized = false;\n // #68 — registrations of plugins added post-init via `register()`, keyed by\n // plugin name so a re-register REPLACES (not appends) the prior hooks.\n readonly #byName = new Map<string, PluginRegistrations>();\n\n async initialize(plugins: ReadonlyArray<Plugin>): Promise<void> {\n if (this.#initialized) {\n throw new Error(\"PluginManager.initialize called twice — register only once per process\");\n }\n this.#initialized = true;\n // EC-4: surface duplicate plugin names so operators notice. Two plugins\n // with the same name are usually a mistake (npm install with override).\n const seen = new Set<string>();\n for (const plugin of plugins) {\n if (seen.has(plugin.name)) {\n process.stderr.write(\n `[theokit-sdk] duplicate plugin name \"${plugin.name}\" — both will register independently\\n`,\n );\n }\n seen.add(plugin.name);\n await this.#dispatchPlugin(plugin);\n }\n }\n\n /**\n * #68 — register a single `general` plugin AFTER `initialize()` has run.\n *\n * The bulk `initialize()` is single-shot (one call per process); late\n * registration is a distinct, named operation used by adapters that install\n * a plugin per-session/per-request (e.g. the ACP permission veto, which is\n * installed once the permission mode + connection are known — after the\n * agent's own plugins were already initialized).\n *\n * Idempotent by plugin NAME: re-registering a plugin with the same name\n * REPLACES its prior hooks/tools instead of appending duplicates (the ACP\n * permission plugin is re-installed on every prompt).\n *\n * Only `general` plugins may be registered late — model-provider / memory\n * plugins are resolved during the bulk init and cannot be added afterwards.\n */\n async register(plugin: Plugin): Promise<void> {\n if (plugin.kind !== \"general\") {\n throw new ConfigurationError(\n `late register supports general plugins only (got \"${plugin.kind}\" for \"${plugin.name}\")`,\n { code: \"plugin_late_register_kind\" },\n );\n }\n const prior = this.#byName.get(plugin.name);\n if (prior !== undefined) this.#unmerge(prior);\n const { ctx, registrations } = createPluginContext();\n await plugin.register(ctx);\n this.#byName.set(plugin.name, registrations);\n this.#merge(registrations);\n }\n\n get aggregated(): Readonly<AggregatedPlugins> {\n return this.#aggregated;\n }\n\n /**\n * Run all `pre_tool_call` hooks; first decision with `block: true` wins.\n * D101: veto pattern — return `{ block: true, message }` makes the loop\n * surface a tool_result with `isError: false, content: message` so the\n * LLM can self-correct.\n */\n async runPreToolCallHooks(ctx: PreToolCallContext): Promise<PreToolCallDecision | undefined> {\n const handlers = this.#aggregated.hooks.get(\"pre_tool_call\") ?? [];\n for (const h of handlers) {\n const decision = (await (h as (c: PreToolCallContext) => unknown)(ctx)) as\n | PreToolCallDecision\n | undefined;\n if (decision !== undefined && (decision as { block?: boolean }).block === true) {\n return decision as PreToolCallDecision;\n }\n }\n return undefined;\n }\n\n /** Aggregated handlers for a given hook (read-only view). @internal */\n hooksFor(name: Parameters<AggregatedPlugins[\"hooks\"][\"get\"]>[0]): ReadonlyArray<HookHandler> {\n return this.#aggregated.hooks.get(name) ?? [];\n }\n\n /**\n * Run all `pre_user_send` hooks; concatenate non-empty `recalledContext`\n * outputs with `\\n\\n` and cap total length at `maxRecallContextBytes`\n * (EC-A). Per-handler failures are caught + logged to stderr (EC-8) so a\n * single broken adapter never blocks the LLM call (graceful degrade).\n *\n * Returns the assembled context (or undefined if empty after cap).\n *\n * @internal\n */\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: per-handler try/catch + EC-A cap + EC-8 isolation are 3 concerns that share state (parts buffer); splitting fragments the single-pass aggregation.\n async runPreUserSendHooks(\n ctx: PreUserSendContext,\n maxRecallContextBytes: number,\n ): Promise<string | undefined> {\n const handlers = this.#aggregated.hooks.get(\"pre_user_send\") ?? [];\n if (handlers.length === 0) return undefined;\n const parts: string[] = [];\n for (const h of handlers) {\n try {\n const result = (await (h as (c: PreUserSendContext) => unknown)(ctx)) as\n | PreUserSendResult\n | undefined;\n if (result?.recalledContext && result.recalledContext.length > 0) {\n parts.push(result.recalledContext);\n }\n } catch (err) {\n process.stderr.write(\n `[theokit-sdk] pre_user_send hook failed: ${\n err instanceof Error ? err.message : String(err)\n }\\n`,\n );\n }\n }\n if (parts.length === 0) return undefined;\n let combined = parts.join(\"\\n\\n\");\n // EC-A: cap to prevent context-window blowout.\n if (combined.length > maxRecallContextBytes) {\n combined = `${combined.slice(0, maxRecallContextBytes)}\\n…[truncated]`;\n }\n return combined;\n }\n\n /**\n * Run all `post_assistant_reply` hooks. Fire-and-forget: errors are\n * surfaced to stderr (EC-O) so a slow/broken sync never blocks the\n * caller's `wait()`. Returns a Promise that callers may optionally\n * await for tests; production code typically `void`s it.\n *\n * @internal\n */\n async runPostAssistantReplyHooks(ctx: PostAssistantReplyContext): Promise<void> {\n const handlers = this.#aggregated.hooks.get(\"post_assistant_reply\") ?? [];\n for (const h of handlers) {\n try {\n await (h as (c: PostAssistantReplyContext) => unknown)(ctx);\n } catch (err) {\n process.stderr.write(\n `[theokit-sdk] post_assistant_reply hook failed: ${\n err instanceof Error ? err.message : String(err)\n }\\n`,\n );\n }\n }\n }\n\n // #65 — the previously-dead hooks, now wired. Fire-and-forget hooks run\n // in order (per-handler errors logged, never thrown); transform hooks fold\n // over the payload (a handler returning a value replaces it).\n\n /** @internal */\n async #runFireAndForget<C>(name: HookName, ctx: C): Promise<void> {\n for (const h of this.#aggregated.hooks.get(name) ?? []) {\n try {\n await (h as (c: C) => unknown)(ctx);\n } catch (err) {\n process.stderr.write(\n `[theokit-sdk] ${name} hook failed: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n }\n }\n }\n\n /** @internal — fold: each handler may return a replacement payload; a throw keeps the prior value. */\n async #runTransform<P>(name: HookName, payload: P, ctx: unknown): Promise<P> {\n let current = payload;\n for (const h of this.#aggregated.hooks.get(name) ?? []) {\n try {\n const out = (await (h as (p: P, c: unknown) => unknown)(current, ctx)) as P | undefined;\n if (out !== undefined) current = out;\n } catch (err) {\n process.stderr.write(\n `[theokit-sdk] ${name} hook failed: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n }\n }\n return current;\n }\n\n /** #65 — fired after a tool call completes. @internal */\n runPostToolCallHooks(ctx: PostToolCallContext): Promise<void> {\n return this.#runFireAndForget(\"post_tool_call\", ctx);\n }\n\n /** #65 — fired before / after each LLM turn. @internal */\n runPreLlmCallHooks(ctx: LlmCallContext): Promise<void> {\n return this.#runFireAndForget(\"pre_llm_call\", ctx);\n }\n runPostLlmCallHooks(ctx: LlmCallContext): Promise<void> {\n return this.#runFireAndForget(\"post_llm_call\", ctx);\n }\n\n /** #65 — fired at run start / end. @internal */\n runOnSessionStartHooks(ctx: SessionLifecycleContext): Promise<void> {\n return this.#runFireAndForget(\"on_session_start\", ctx);\n }\n runOnSessionEndHooks(ctx: SessionLifecycleContext): Promise<void> {\n return this.#runFireAndForget(\"on_session_end\", ctx);\n }\n\n /** #65/#57 — transform tool results before they reach the LLM (the #57 seam). @internal */\n runTransformToolResultHooks<T>(results: T, ctx: TransformContext): Promise<T> {\n return this.#runTransform(\"transform_tool_result\", results, ctx);\n }\n\n /** #65 — transform the LLM output text before it is consumed. @internal */\n runTransformLlmOutputHooks(output: string, ctx: TransformContext): Promise<string> {\n return this.#runTransform(\"transform_llm_output\", output, ctx);\n }\n\n async #dispatchPlugin(plugin: Plugin): Promise<void> {\n if (plugin.kind === \"general\") {\n const { ctx, registrations } = createPluginContext();\n await plugin.register(ctx);\n this.#merge(registrations);\n } else if (plugin.kind === \"model-provider\") {\n this.#aggregated.providerProfiles.push({\n pluginName: plugin.name,\n profile: plugin.profile,\n });\n } else if (plugin.kind === \"memory\") {\n this.#aggregated.memoryProviders.push({\n pluginName: plugin.name,\n createProvider: plugin.createProvider,\n });\n }\n }\n\n #merge(r: PluginRegistrations): void {\n this.#aggregated.tools.push(...r.tools);\n this.#aggregated.commands.push(...r.commands);\n for (const [hook, handlers] of r.hooks.entries()) {\n const existing = this.#aggregated.hooks.get(hook) ?? [];\n existing.push(...handlers);\n this.#aggregated.hooks.set(hook, existing);\n }\n this.#aggregated.injected.push(...r.injected);\n }\n\n /**\n * #68 — inverse of #merge: remove a prior registration's contributions from\n * the aggregated view by object identity. Used by `register()` to replace a\n * same-named plugin's hooks/tools instead of accumulating duplicates.\n */\n #unmerge(r: PluginRegistrations): void {\n removeAll(this.#aggregated.tools, r.tools);\n removeAll(this.#aggregated.commands, r.commands);\n removeAll(this.#aggregated.injected, r.injected);\n for (const [hook, handlers] of r.hooks.entries()) {\n const existing = this.#aggregated.hooks.get(hook);\n if (existing === undefined) continue;\n removeAll(existing, handlers);\n if (existing.length === 0) this.#aggregated.hooks.delete(hook);\n }\n }\n}\n\n/** Remove each element of `toRemove` from `arr` in place (by identity). */\nfunction removeAll<T>(arr: T[], toRemove: ReadonlyArray<T>): void {\n for (const item of toRemove) {\n const idx = arr.indexOf(item);\n if (idx !== -1) arr.splice(idx, 1);\n }\n}\n","/**\n * Plugin contract types (T1.1, ADRs D97-D101).\n *\n * Discriminated union by `kind`:\n * - `\"general\"` — registers tools/hooks/commands via `register(ctx)`.\n * - `\"model-provider\"` — declares a `ProviderProfile` consumed by router.\n * - `\"memory\"` — supplies a memory provider factory.\n *\n * Hooks are a fixed enum (D100) to prevent sprawl; `pre_tool_call` supports\n * veto via `{ block: true, message }` (D101) so plugins can implement safety\n * guards without crashing the agent loop.\n *\n * @public\n */\n\nimport type { CustomTool } from \"../../types/agent.js\";\nimport type { MemoryAdapter } from \"../../types/memory-adapter.js\";\nimport type { ProviderProfile } from \"../providers/types.js\";\n\nexport type HookName =\n | \"pre_tool_call\"\n | \"post_tool_call\"\n | \"pre_llm_call\"\n | \"post_llm_call\"\n | \"on_session_start\"\n | \"on_session_end\"\n | \"transform_tool_result\"\n | \"transform_llm_output\"\n // Memory adapter hooks (ADRs D141 / D145).\n | \"pre_user_send\"\n | \"post_assistant_reply\";\n\nexport interface PreToolCallContext {\n name: string;\n args: Record<string, unknown>;\n agentId: string;\n runId: string;\n}\n\nexport interface PreToolCallDecision {\n block: true;\n message: string;\n}\n\n/**\n * #65 — a 2nd argument passed to a tool handler, carrying the run's cancellation\n * signal (ties into #58) so a cooperative tool can stop when the run is\n * cancelled. Optional and additive — existing single-arg handlers are unaffected.\n * (requestConfirmation/requestCredential are a documented follow-up.)\n *\n * @public\n */\nexport interface ToolContext {\n signal?: AbortSignal;\n}\n\n/** #65 — context for the `post_tool_call` hook (fired after a tool runs). @public */\nexport interface PostToolCallContext {\n name: string;\n args: Record<string, unknown>;\n result: { stdout: string; stderr: string; exitCode?: number | null };\n agentId: string;\n runId: string;\n}\n\n/** #65 — context for the `pre_llm_call` / `post_llm_call` hooks. @public */\nexport interface LlmCallContext {\n agentId: string;\n runId: string;\n /** Iteration index (0-based) of the current turn, when available. */\n iteration?: number;\n}\n\n/** #65 — context for the `on_session_start` / `on_session_end` hooks. @public */\nexport interface SessionLifecycleContext {\n agentId: string;\n runId: string;\n}\n\n/** #65 — context for the `transform_tool_result` / `transform_llm_output` hooks. @public */\nexport interface TransformContext {\n agentId: string;\n runId: string;\n}\n\n/**\n * Context passed to `pre_user_send` hook handlers (ADR D145).\n *\n * @public\n */\nexport interface PreUserSendContext {\n prompt: string;\n agentId: string;\n runId: string;\n /** Caller-supplied memory context, flowing through from `AgentOptions.memoryContext`. */\n memoryContext?: import(\"../../types/memory-adapter.js\").MemoryContext;\n /** Forwarded `AbortSignal` so adapter recall HTTP can be cancelled mid-flight (EC-H). */\n signal?: AbortSignal;\n}\n\n/**\n * Optional result returned by `pre_user_send` handlers. The agent loop\n * concatenates `recalledContext` from all handlers and injects it as a\n * `<memory-context>...</memory-context>` block before the user prompt.\n *\n * @public\n */\nexport interface PreUserSendResult {\n recalledContext?: string;\n}\n\n/**\n * Context passed to `post_assistant_reply` hook handlers (ADR D145).\n * Fire-and-forget — exceptions are caught and surfaced to stderr; the\n * caller's `wait()` never blocks on this dispatch.\n *\n * @public\n */\nexport interface PostAssistantReplyContext {\n prompt: string;\n reply: string;\n agentId: string;\n runId: string;\n memoryContext?: import(\"../../types/memory-adapter.js\").MemoryContext;\n}\n\nexport type HookHandler = (ctx: unknown) => unknown | Promise<unknown>;\n\nexport type CommandHandler = (args: Record<string, unknown>) => Promise<string> | string;\n\nexport interface CommandOptions {\n description?: string;\n}\n\nexport interface PluginContext {\n /** Register a custom tool. Equivalent to passing in `AgentOptions.tools`. */\n registerTool(tool: CustomTool): void;\n /** Register a slash-command-style handler. Consumed by CLI/bot wrappers; NOT used by the agent loop. */\n registerCommand(name: string, handler: CommandHandler, opts?: CommandOptions): void;\n /** Attach a hook handler. `pre_tool_call` supports veto via `PreToolCallDecision`. */\n on(hook: HookName, handler: HookHandler): void;\n /** Inject a user/system message into the next agent turn. v1 supports only `on_session_start` context. */\n injectMessage(content: string, role?: \"user\" | \"system\"): void;\n}\n\ninterface BasePlugin {\n name: string;\n version: string;\n}\n\n/**\n * Memory provider factory shape (ADR D141). Returns a `MemoryAdapter`\n * (sync) or a Promise resolving to one (lazy HTTP probe / config load).\n *\n * Adapters live in `@theokit-memory-*` packages; the SDK never imports\n * them. Factory rejection is caught by the plugin manager and surfaced\n * as `ConfigurationError(code: \"plugin_factory_failed\")` (EC-F) — never\n * an unhandled rejection.\n *\n * @internal\n */\nexport type MemoryProviderFactory = (cwd: string) => MemoryAdapter | Promise<MemoryAdapter>;\n\nexport type Plugin =\n | (BasePlugin & {\n kind: \"general\";\n register: (ctx: PluginContext) => void | Promise<void>;\n })\n | (BasePlugin & {\n kind: \"model-provider\";\n profile: ProviderProfile;\n })\n | (BasePlugin & {\n kind: \"memory\";\n createProvider: MemoryProviderFactory;\n });\n\n/**\n * Identity helper for plugin authors. TS-only convenience — preserves\n * inferred type without forcing manual `Plugin` annotation.\n *\n * @public\n */\nexport function definePlugin<P extends Plugin>(p: P): P {\n return p;\n}\n"]}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Internal barrel for the workflow executor + helpers. Public API lives
|
|
3
|
-
* in `../../workflow.ts`.
|
|
4
|
-
*
|
|
5
|
-
* @internal
|
|
6
|
-
*/
|
|
7
|
-
export { dispatchStep, executeWorkflow, resumeWorkflow } from "./executor.js";
|
|
8
|
-
export { mintRunId } from "./run-id.js";
|
|
9
|
-
export { acquireSingleFlight } from "./single-flight.js";
|
|
10
|
-
export type { WorkflowSnapshotStore } from "./snapshot-store.js";
|
|
11
|
-
export { __resetSnapshotStoresForTests, getSnapshotStoreFor } from "./snapshot-store.js";
|
|
12
|
-
export { __resetTelemetryCacheForTests, startWorkflowRunSpan, startWorkflowStepSpan, } from "./telemetry.js";
|