@kb-labs/agent-entry 2.119.0-canary.e120bc0ee → 2.119.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.
Files changed (57) hide show
  1. package/dist/cli/commands/diff.js.map +1 -1
  2. package/dist/cli/commands/history.js.map +1 -1
  3. package/dist/cli/commands/quality-report.js.map +1 -1
  4. package/dist/cli/commands/rollback.js.map +1 -1
  5. package/dist/cli/commands/run.js.map +1 -1
  6. package/dist/cli/commands/trace-context.js.map +1 -1
  7. package/dist/cli/commands/trace-diagnose.js.map +1 -1
  8. package/dist/cli/commands/trace-event-normalizer.js.map +1 -1
  9. package/dist/cli/commands/trace-filter.js.map +1 -1
  10. package/dist/cli/commands/trace-iteration.js.map +1 -1
  11. package/dist/cli/commands/trace-stats.js.map +1 -1
  12. package/dist/index.js +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/manifest.js +1 -1
  15. package/dist/manifest.js.map +1 -1
  16. package/dist/rest/handlers/approve-handler.js.map +1 -1
  17. package/dist/rest/handlers/approve-session-plan-handler.js.map +1 -1
  18. package/dist/rest/handlers/correct-handler.js.map +1 -1
  19. package/dist/rest/handlers/create-session-handler.js.map +1 -1
  20. package/dist/rest/handlers/execute-session-plan-handler.js.map +1 -1
  21. package/dist/rest/handlers/generate-spec-handler.js.map +1 -1
  22. package/dist/rest/handlers/get-file-diff-handler.js.map +1 -1
  23. package/dist/rest/handlers/get-session-handler.js.map +1 -1
  24. package/dist/rest/handlers/get-session-plan-handler.js.map +1 -1
  25. package/dist/rest/handlers/get-session-turns-handler.js.map +1 -1
  26. package/dist/rest/handlers/get-spec-handler.js.map +1 -1
  27. package/dist/rest/handlers/list-file-changes-handler.js.map +1 -1
  28. package/dist/rest/handlers/list-sessions-handler.js.map +1 -1
  29. package/dist/rest/handlers/rollback-handler.js.map +1 -1
  30. package/dist/rest/handlers/run-handler.js.map +1 -1
  31. package/dist/rest/handlers/sessions-handler.js.map +1 -1
  32. package/dist/rest/handlers/status-handler.js.map +1 -1
  33. package/dist/rest/handlers/stop-handler.js.map +1 -1
  34. package/dist/ws/session-stream-handler.js.map +1 -1
  35. package/package.json +14 -14
  36. package/dist/manifest.json +0 -685
  37. package/dist/widgets/117.js +0 -32
  38. package/dist/widgets/165.js +0 -1
  39. package/dist/widgets/326.js +0 -1
  40. package/dist/widgets/370.js +0 -1
  41. package/dist/widgets/405.js +0 -1
  42. package/dist/widgets/46.js +0 -445
  43. package/dist/widgets/50.js +0 -1
  44. package/dist/widgets/546.js +0 -1
  45. package/dist/widgets/648.js +0 -1
  46. package/dist/widgets/669.js +0 -1
  47. package/dist/widgets/707.js +0 -1
  48. package/dist/widgets/775.js +0 -1
  49. package/dist/widgets/78.js +0 -1
  50. package/dist/widgets/832.js +0 -96
  51. package/dist/widgets/875.js +0 -25
  52. package/dist/widgets/945.js +0 -1
  53. package/dist/widgets/968.js +0 -9
  54. package/dist/widgets/__federation_expose_AgentsPage.js +0 -1
  55. package/dist/widgets/mf-manifest.json +0 -229
  56. package/dist/widgets/mf-stats.json +0 -256
  57. package/dist/widgets/remoteEntry.js +0 -7
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/rest/run-manager.ts","../../../src/rest/handlers/run-handler.ts"],"names":["useCache"],"mappings":";;;;;;;;;;;AAYA,IAAM,YAAA,GAAe,YAAA;AACrB,IAAM,SAAA,GAAY,IAAA;AAqDlB,IAAM,iBAAN,MAAqB;AAAA;AAAA,EAEX,UAAA,uBAAyC,GAAA,EAAI;AAAA;AAAA,EAG7C,gBAAA,uBAAkE,GAAA,EAAI;AAAA;AAAA;AAAA;AAAA,EAK9E,aAAA,GAAwB;AACtB,IAAA,OAAO,CAAA,IAAA,EAAO,IAAA,CAAK,GAAA,EAAK,IAAI,IAAA,CAAK,MAAA,EAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAA,CACJ,KAAA,EACA,IAAA,EACA,OACA,cAAA,EACoB;AACpB,IAAA,MAAM,GAAA,GAAA,iBAAM,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAEnC,IAAA,MAAM,GAAA,GAAiB;AAAA,MACrB,KAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,KAAA;AAAA,MACA,cAAA;AAAA,MACA,SAAA,EAAW;AAAA,KACb;AAGA,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AAG9B,IAAA,MAAM,IAAA,CAAK,YAAY,GAAG,CAAA;AAE1B,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAA,EAAsC;AACxC,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,KAAA,EAAiC;AAE5C,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA,EAAG;AAC9B,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA;AACvC,IAAA,OAAO,KAAA,KAAU,IAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,KAAA,EAAyC;AACtD,IAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,IAAA,IAAI,CAAC,KAAA,EAAO;AAAC,MAAA,OAAO,IAAA;AAAA,IAAK;AAEzB,IAAA,OAAO,MAAM,GAAA,CAAc,CAAA,EAAG,YAAY,CAAA,EAAG,KAAK,CAAA,CAAE,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAA,CAAa,KAAA,EAAe,MAAA,EAAmB,KAAA,EAA0C;AAC7F,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AACrC,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,GAAA,CAAI,MAAA,GAAS,MAAA;AACb,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,MAAA,CAAO,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,MAC1B;AACA,MAAA,MAAM,IAAA,CAAK,YAAY,GAAG,CAAA;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YAAY,GAAA,EAA+B;AACvD,IAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,IAAA,IAAI,CAAC,KAAA,EAAO;AAAC,MAAA;AAAA,IAAO;AAEpB,IAAA,MAAM,KAAA,GAAkB;AAAA,MACtB,OAAO,GAAA,CAAI,KAAA;AAAA,MACX,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,QAAQ,GAAA,CAAI,MAAA;AAAA,MACZ,WAAW,GAAA,CAAI,SAAA;AAAA,MACf,aAAa,GAAA,CAAI,WAAA;AAAA,MACjB,YAAY,GAAA,CAAI,UAAA;AAAA,MAChB,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,OAAO,GAAA,CAAI;AAAA,KACb;AAEA,IAAA,MAAM,KAAA,CAAM,IAAI,CAAA,EAAG,YAAY,GAAG,GAAA,CAAI,KAAK,CAAA,CAAA,EAAI,KAAA,EAAO,SAAS,CAAA;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,sBAAA,CAAuB,WAAmB,MAAA,EAA2B;AACnE,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AAAE,MAAA;AAAA,IAAQ;AACnC,IAAA,IAAA,CAAK,uBAAuB,SAAA,EAAW,EAAE,IAAA,EAAM,QAAA,EAAU,QAAQ,CAAA;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,qBAAA,CAAsB,WAAmB,OAAA,EAA0F;AACjI,IAAA,IAAA,CAAK,uBAAuB,SAAA,EAAW,EAAE,MAAM,eAAA,EAAiB,GAAG,SAAS,CAAA;AAAA,EAC9E;AAAA,EAEQ,sBAAA,CAAuB,WAAmB,OAAA,EAAwC;AACxF,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,SAAS,CAAA;AACrD,IAAA,IAAI,CAAC,SAAA,EAAW;AAAE,MAAA;AAAA,IAAQ;AAC1B,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,OAAO,CAAA;AAAA,MAClB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAA,CAAmB,WAAmB,QAAA,EAAyC;AAC7E,IAAA,IAAI,CAAC,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,SAAS,CAAA,EAAG;AACzC,MAAA,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,SAAA,kBAAW,IAAI,KAAK,CAAA;AAAA,IAChD;AACA,IAAA,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,SAAS,CAAA,CAAG,IAAI,QAAQ,CAAA;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAA,CAAsB,WAAmB,QAAA,EAAyC;AAChF,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,SAAS,CAAA;AACrD,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AACzB,MAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACxB,QAAA,IAAA,CAAK,gBAAA,CAAiB,OAAO,SAAS,CAAA;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAA2F;AACzF,IAAA,OAAO,KAAA,CAAM,KAAK,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,CAAE,IAAI,CAAA,CAAA,MAAM;AAAA,MACpD,OAAO,CAAA,CAAE,KAAA;AAAA,MACT,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,QAAQ,CAAA,CAAE,MAAA;AAAA,MACV,WAAW,CAAA,CAAE;AAAA,KACf,CAAE,CAAA;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,KAAA,EAAwB;AAClC,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AACrC,IAAA,IAAI,CAAC,GAAA,IAAO,GAAA,CAAI,WAAW,SAAA,IAAa,CAAC,IAAI,KAAA,EAAO;AAClD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,GAAA,CAAI,MAAM,WAAA,EAAY;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAAgB;AACd,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,GAAG,CAAA,IAAK,KAAK,UAAA,EAAY;AAC1C,MAAA,IAAI,GAAA,CAAI,WAAW,WAAA,IAAe,GAAA,CAAI,WAAW,QAAA,IAAY,GAAA,CAAI,WAAW,SAAA,EAAW;AAErF,QAAA,IAAA,CAAK,UAAA,CAAW,OAAO,KAAK,CAAA;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AACF,CAAA;AAQA,IAAM,UAAA,GAAa,0BAAA;AACnB,IAAI,CAAE,UAAA,CAAuC,UAAU,CAAA,EAAG;AACxD,EAAC,UAAA,CAAuC,UAAU,CAAA,GAAI,IAAI,cAAA,EAAe;AAC3E;AACO,IAAM,UAAA,GAAc,WAAuC,UAAU,CAAA;;;AC3Q5E,iBAAA,EAAkB;AAalB,IAAM,kBAAA,GAAqB,6EAAA;AAE3B,SAAS,0BAA0B,IAAA,EAAuB;AACxD,EAAA,OAAO,kBAAA,CAAmB,KAAK,IAAI,CAAA;AACrC;AAEA,SAAS,WAAW,GAAA,EAAsB;AACxC,EAAA,IAAI;AACF,IAAA,OAAO,EAAA,CAAG,WAAW,GAAG,CAAA;AAAA,EAC1B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,qBAAA,CAAsB,SAAiB,MAAA,EAAmC;AACjF,EAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AAGpC,EAAA,MAAM,QAAA,GAAW,CAAA,CAAE,KAAA,CAAM,yBAAyB,CAAA;AAClD,EAAA,IAAI,QAAA,GAAW,CAAC,CAAA,EAAG;AACjB,IAAA,MAAA,CAAO,GAAA,CAAI,QAAA,CAAS,CAAC,CAAA,EAAA,CAAI,MAAA,CAAO,GAAA,CAAI,QAAA,CAAS,CAAC,CAAC,CAAA,IAAK,CAAA,IAAK,CAAC,CAAA;AAAA,EAC5D;AAGA,EAAA,IAAI,CAAA,CAAE,UAAA,CAAW,WAAW,CAAA,EAAG;AAC7B,IAAA,IAAI,sBAAsB,IAAA,CAAK,CAAC,KAAK,oDAAA,CAAqD,IAAA,CAAK,CAAC,CAAA,EAAG;AACjG,MAAA,MAAA,CAAO,IAAI,gBAAA,EAAA,CAAmB,MAAA,CAAO,IAAI,gBAAgB,CAAA,IAAK,KAAK,CAAC,CAAA;AAAA,IACtE;AACA,IAAA,IAAI,qBAAqB,IAAA,CAAK,CAAC,KAAK,uBAAA,CAAwB,IAAA,CAAK,CAAC,CAAA,EAAG;AACnE,MAAA,MAAA,CAAO,IAAI,cAAA,EAAA,CAAiB,MAAA,CAAO,IAAI,cAAc,CAAA,IAAK,KAAK,CAAC,CAAA;AAAA,IAClE;AAAA,EACF;AACF;AAEA,eAAe,uBAAA,CACb,cAAA,EACA,SAAA,EACA,cAAA,EACwB;AACxB,EAAA,MAAM,MAAA,GAAS,MAAM,cAAA,CAAe,gBAAA,CAAiB,SAAS,CAAA;AAC9D,EAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AAClB,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAAY;AACtC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI,KAAA,CAAM,IAAA,KAAS,WAAA,IAAe,KAAA,CAAM,KAAA,EAAO;AAC7C,MAAA,aAAA,CAAc,GAAA,CAAI,MAAM,KAAK,CAAA;AAAA,IAC/B;AAAA,EACF;AACA,EAAA,MAAM,YAAY,KAAA,CAAM,IAAA,CAAK,aAAa,CAAA,CAAE,GAAG,EAAE,CAAA;AACjD,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAoB;AAC3C,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI,KAAA,CAAM,UAAU,SAAA,EAAW;AAC7B,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,CAAM,SAAS,YAAA,EAAc;AAC/B,MAAA,MAAM,KAAA,GAAS,KAAA,CAAM,IAAA,EAAM,KAAA,IAAiD,EAAC;AAC7E,MAAA,MAAM,KAAK,KAAA,CAAM,IAAA;AACjB,MAAA,MAAM,KAAK,KAAA,CAAM,SAAA;AACjB,MAAA,IAAI,OAAO,OAAO,QAAA,EAAU;AAAC,QAAA,qBAAA,CAAsB,IAAI,UAAU,CAAA;AAAA,MAAE;AACnE,MAAA,IAAI,OAAO,OAAO,QAAA,EAAU;AAAC,QAAA,qBAAA,CAAsB,IAAI,UAAU,CAAA;AAAA,MAAE;AAAA,IACrE;AAEA,IAAA,IAAI,KAAA,CAAM,SAAS,UAAA,EAAY;AAC7B,MAAA,MAAM,QAAA,GAAY,KAAA,CAAM,IAAA,EAAM,QAAA,IAAoD,EAAC;AACnF,MAAA,MAAM,IAAI,QAAA,CAAS,IAAA;AACnB,MAAA,IAAI,OAAO,MAAM,QAAA,EAAU;AAAC,QAAA,qBAAA,CAAsB,GAAG,UAAU,CAAA;AAAA,MAAE;AAAA,IACnE;AAAA,EACF;AAEA,EAAA,MAAM,SAAS,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,OAAA,EAAS,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAC,CAAA;AAC1E,EAAA,MAAM,GAAA,GAAM,OAAO,CAAC,CAAA;AACpB,EAAA,IAAI,CAAC,GAAA,IAAO,GAAA,CAAI,CAAC,IAAI,CAAA,EAAG;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,cAAc,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,GAAA,CAAI,CAAC,CAAC,CAAA;AACpD,EAAA,OAAO,UAAA,CAAW,WAAW,CAAA,GAAI,WAAA,GAAc,IAAA;AACjD;AAEA,IAAO,sBAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EACsB;AACtB,IAAA,IAAI;AACJ,MAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AAEnB,MAAA,IAAI,CAAC,MAAM,IAAA,EAAM;AACf,QAAA,MAAM,IAAI,MAAM,kBAAkB,CAAA;AAAA,MACpC;AAEA,MAAA,MAAM,YAAY,YAAA,EAAa;AAC/B,MAAA,MAAM,KAAA,GAAQ,WAAW,aAAA,EAAc;AACvC,MAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAG3B,MAAA,IAAI,YAAY,IAAA,CAAK,SAAA;AACrB,MAAA,IAAI,UAAA,GAAa,IAAA,CAAK,UAAA,IAAc,GAAA,CAAI,GAAA;AACxC,MAAA,IAAI,cAAA,GAAiB,IAAI,cAAA,CAAe,UAAU,CAAA;AAClD,MAAA,IAAI,CAAC,SAAA,EAAW;AAEd,QAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,aAAA,CAAc;AAAA,UACjD,IAAA,EAAM,SAAA;AAAA,UACN,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,OAAA,EAAS,KAAK,OAAA,IAAW;AAAA,SAC1B,CAAA;AACD,QAAA,SAAA,GAAY,OAAA,CAAQ,EAAA;AACpB,QAAA,GAAA,CAAI,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,CAAA,kCAAA,EAAqC,SAAS,CAAA,CAAE,CAAA;AAAA,MAC3E,CAAA,MAAO;AAEL,QAAA,MAAM,eAAA,GAAkB,MAAM,cAAA,CAAe,WAAA,CAAY,SAAS,CAAA;AAClE,QAAA,IAAI,eAAA,GAAkB,eAAA;AAGtB,QAAA,IAAI,CAAC,eAAA,IAAmB,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA,EAAG;AAC3C,UAAA,MAAM,eAAA,GAAkB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAClD,UAAA,MAAM,eAAA,GAAkB,MAAM,eAAA,CAAgB,WAAA,CAAY,SAAS,CAAA;AACnE,UAAA,IAAI,eAAA,EAAiB;AACnB,YAAA,cAAA,GAAiB,eAAA;AACjB,YAAA,eAAA,GAAkB,eAAA;AAAA,UACpB;AAAA,QACF;AAEA,QAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,MAAA,EAAS,GAAA,CAAI,GAAG,CAAA,CAAA,CAAG,CAAA;AAAA,QACpE;AAGA,QAAA,UAAA,GAAa,IAAA,CAAK,UAAA,IAAc,eAAA,CAAgB,UAAA,IAAc,UAAA;AAG9D,QAAA,IAAI,CAAC,IAAA,CAAK,UAAA,IAAc,yBAAA,CAA0B,IAAA,CAAK,IAAI,CAAA,EAAG;AAC5D,UAAA,MAAM,QAAA,GAAW,MAAM,uBAAA,CAAwB,cAAA,EAAgB,WAAW,eAAA,CAAgB,UAAA,IAAc,IAAI,GAAG,CAAA;AAC/G,UAAA,IAAI,QAAA,IAAY,aAAa,UAAA,EAAY;AACvC,YAAA,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,2CAA2C,UAAU,CAAA,IAAA,EAAO,QAAQ,CAAA,CAAE,CAAA;AAC/F,YAAA,UAAA,GAAa,QAAA;AAAA,UACf;AAAA,QACF;AAGA,QAAA,cAAA,GAAiB,IAAI,eAAe,UAAU,CAAA;AAC9C,QAAA,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,oCAAoC,SAAS,CAAA,aAAA,EAAgB,UAAU,CAAA,CAAA,CAAG,CAAA;AAAA,MACrG;AAEA,MAAA,GAAA,CAAI,QAAA,CAAS,OAAO,IAAA,CAAK,CAAA,2BAAA,EAA8B,KAAK,CAAA,WAAA,EAAc,IAAA,CAAK,IAAI,CAAA,CAAE,CAAA;AAGrF,MAAA,MAAM,QAAA,GAAW,MAAM,cAAA,CAAe,cAAA,CAAe,WAAW,IAAA,CAAK,IAAA,EAAM,KAAA,EAAO,IAAA,CAAK,QAAQ,CAAA;AAG/F,MAAA,MAAM,SAAA,EAAW,KAAA,CAAM,sBAAA,CAAuB,WAAA,EAAa;AAAA,QACzD,KAAA;AAAA,QACA,SAAA;AAAA,QACA,UAAA,EAAY,KAAK,IAAA,CAAK,MAAA;AAAA,QACtB,IAAA,EAAM,KAAK,IAAA,IAAQ,QAAA;AAAA,QACnB,gBAAA,EAAkB,KAAK,gBAAA,IAAoB,IAAA;AAAA,QAC3C,YAAA,EAAc,KAAK,YAAA,IAAgB,MAAA;AAAA,QACnC,OAAA,EAAS,KAAK,OAAA,IAAW;AAAA,OAC1B,CAAA;AAGD,MAAA,MAAM,aAAA,GAAgB,yBAAA,CAA0B,UAAA,EAAY,SAAS,CAAA;AACrE,MAAA,MAAM,+BAA+B,yCAAA,EAA0C;AAC/E,MAAA,MAAM,eAAe,kBAAA,CAAmB;AAAA,QACtC,UAAA;AAAA,QACA,aAAa,IAAA,CAAK,IAAA;AAAA,QAClB,SAAA;AAAA,QACA,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,OAAOA,QAAAA,EAAS;AAAA,QAChB,aAAA;AAAA,QACA,8BAA8B,OAAO,EAAE,MAAM,MAAA,EAAO,KAKlD,6BAA6B,MAAA,CAAO;AAAA,UAClC,KAAA,EAAO,MAAA;AAAA,UACP,UAAU,EAAC;AAAA,UACX,IAAA,EAAM,QAAQ,IAAA,CAAK;AAAA,SACpB;AAAA,OACJ,CAAA;AACD,MAAA,MAAM,YAAA,GAAe,MAAM,SAAA,EAA8B;AAEzD,MAAA,MAAM,cAAA,GAAiB,SAAA;AACvB,MAAA,MAAM,WAAW,IAAA,CAAK,IAAA,CAAK,UAAA,EAAY,KAAA,EAAO,UAAU,aAAa,CAAA;AACrE,MAAA,MAAM,cAAc,IAAI,sBAAA,CAAuB,KAAA,EAAO,IAAI,QAAQ,CAAA;AAGlE,MAAA,MAAM,KAAA,GAAQ,IAAI,QAAA,EAAS,CACxB,SAAS,kBAAA,CAAmB,YAAY,CAAC,CAAA,CACzC,YAAA,CAAa;AAAA,QACZ,SAAA,EAAW,cAAA;AAAA,QACX,UAAA;AAAA,QACA,aAAA,EAAe,EAAA;AAAA,QACf,WAAA,EAAa,GAAA;AAAA,QACb,IAAA,EAAM,KAAK,IAAA,IAAQ,QAAA;AAAA,QACnB,aAAa,YAAA,EAAc,WAAA;AAAA,QAC3B,OAAA,EAAS,CAAC,KAAA,KAAU;AAOlB,UAAA,KAAK,cAAA,CAAe,SAAS,cAAA,EAAgB;AAAA,YAC3C,GAAG,KAAA;AAAA,YACH,SAAA,EAAW,cAAA;AAAA,YACX,KAAA;AAAA,YACA,QAAA,EAAU;AAAA,cACR,GAAG,KAAA,CAAM,QAAA;AAAA,cACT,SAAA,EAAW,cAAA;AAAA,cACX,KAAA;AAAA,cACA;AAAA;AACF,WACD,CAAA,CAAE,IAAA,CAAK,CAAC,MAAA,KAAW;AAClB,YAAA,UAAA,CAAW,sBAAA,CAAuB,gBAAgB,MAAM,CAAA;AAAA,UAC1D,CAAC,CAAA;AAAA,QACH;AAAA,OACD,CAAA;AAGH,MAAA,MAAM,GAAA,GAAM,MAAM,UAAA,CAAW,QAAA,CAAS,OAAO,IAAA,CAAK,IAAA,EAAM,OAAO,cAAc,CAAA;AAC7E,MAAA,MAAM,UAAA,CAAW,YAAA,CAAa,KAAA,EAAO,SAAS,CAAA;AAG9C,MAAA,KAAA,CAAM,YAAY;AAChB,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,OAAA,CAAQ,KAAK,IAAI,CAAA;AAC5C,UAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAChC,UAAA,MAAM,aAAA,GAAgB,YAAY,UAAA,EAAW;AAC7C,UAAA,MAAM,YAAY,QAAA,IAAW;AAE7B,UAAA,IAAI,aAAA,CAAc,SAAS,CAAA,EAAG;AAC5B,YAAA,MAAM,cAAA,CAAe,mBAAA,CAAoB,cAAA,EAAgB,KAAA,EAAO,aAAa,CAAA;AAAA,UAC/E;AAIA,UAAA,IAAI,MAAA,CAAO,WAAA,IAAe,MAAA,CAAO,WAAA,CAAY,SAAS,CAAA,EAAG;AACvD,YAAA,MAAM,cAAA,CAAe,uBAAA,CAAwB,cAAA,EAAgB,KAAA,EAAO,OAAO,WAAW,CAAA;AAAA,UACxF;AAEA,UAAA,MAAM,WAAW,YAAA,CAAa,KAAA,EAAO,MAAA,CAAO,OAAA,GAAU,cAAc,QAAA,EAAU;AAAA,YAC5E,WAAA,EAAA,iBAAa,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,YACpC,UAAA;AAAA,YACA,SAAS,MAAA,CAAO,OAAA;AAAA,YAChB,OAAO,MAAA,CAAO;AAAA,WACf,CAAA;AAQD,UAAA,MAAM,UAAA,GAAa,MAAM,cAAA,CAAe,QAAA,CAAS,cAAc,CAAA;AAC/D,UAAA,MAAM,SAAA,GAAY,UAAA,CAAW,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,WAAA,IAAe,CAAA,CAAE,QAAA,CAAS,KAAA,KAAU,KAAK,CAAA;AAC7F,UAAA,MAAM,GAAA,GAAM,MAAM,cAAA,CAAe,oBAAA,CAAqB,cAAc,CAAA;AACpE,UAAA,UAAA,CAAW,sBAAsB,cAAA,EAAgB;AAAA,YAC/C,KAAA;AAAA,YACA,SAAS,MAAA,CAAO,OAAA;AAAA,YAChB,SAAS,MAAA,CAAO,OAAA;AAAA,YAChB,UAAA;AAAA,YACA,GAAA;AAAA,YACA,IAAA,EAAM;AAAA,WACP,CAAA;AAGD,UAAA,MAAM,SAAA,EAAW,KAAA;AAAA,YACf,MAAA,CAAO,OAAA,GAAU,sBAAA,CAAuB,aAAA,GAAgB,sBAAA,CAAuB,UAAA;AAAA,YAC/E;AAAA,cACE,KAAA;AAAA,cACA,UAAA;AAAA,cACA,SAAS,MAAA,CAAO,OAAA;AAAA,cAChB,OAAA,EAAS,MAAA,CAAO,OAAA,EAAS,KAAA,CAAM,GAAG,GAAG;AAAA;AACvC,WACF;AAEA,UAAA,GAAA,CAAI,QAAA,CAAS,OAAO,IAAA,CAAK,CAAA,kBAAA,EAAqB,KAAK,CAAA,YAAA,EAAe,MAAA,CAAO,OAAO,CAAA,CAAE,CAAA;AAAA,QACpF,SAAS,KAAA,EAAO;AACd,UAAA,MAAM,WAAW,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AACtE,UAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAChC,UAAA,MAAM,aAAA,GAAgB,YAAY,UAAA,EAAW;AAC7C,UAAA,MAAM,YAAY,QAAA,IAAW;AAC7B,UAAA,IAAI,aAAA,CAAc,SAAS,CAAA,EAAG;AAC5B,YAAA,MAAM,cAAA,CAAe,mBAAA,CAAoB,cAAA,EAAgB,KAAA,EAAO,aAAa,CAAA;AAAA,UAC/E;AAEA,UAAA,MAAM,UAAA,CAAW,YAAA,CAAa,KAAA,EAAO,QAAA,EAAU;AAAA,YAC7C,WAAA,EAAA,iBAAa,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,YACpC,UAAA;AAAA,YACA,KAAA,EAAO;AAAA,WACR,CAAA;AAED,UAAA,MAAM,GAAA,GAAM,MAAM,cAAA,CAAe,oBAAA,CAAqB,cAAc,CAAA;AACpE,UAAA,UAAA,CAAW,sBAAsB,cAAA,EAAgB;AAAA,YAC/C,KAAA;AAAA,YACA,OAAA,EAAS,KAAA;AAAA,YACT,OAAA,EAAS,QAAA;AAAA,YACT,UAAA;AAAA,YACA;AAAA,WACD,CAAA;AAGD,UAAA,MAAM,SAAA,EAAW,KAAA,CAAM,sBAAA,CAAuB,UAAA,EAAY;AAAA,YACxD,KAAA;AAAA,YACA,UAAA;AAAA,YACA,KAAA,EAAO,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,GAAG;AAAA,WAC7B,CAAA;AAED,UAAA,GAAA,CAAI,SAAS,MAAA,CAAO,KAAA,CAAM,qBAAqB,KAAK,CAAA,SAAA,EAAY,QAAQ,CAAA,CAAE,CAAA;AAAA,QAC5E;AAAA,MACF,CAAA,GAAG;AAGH,MAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,cAAA,CAAe,OAAA,CAAQ,cAAc,cAAc,CAAA;AACrF,MAAA,MAAM,UAAA,GAAa,CAAA,EAAG,mBAAmB,CAAA,EAAG,MAAM,CAAA,CAAA;AAElD,MAAA,OAAO;AAAA,QACL,KAAA;AAAA,QACA,SAAA,EAAW,cAAA;AAAA,QACX,UAAA;AAAA,QACA,MAAA,EAAQ,SAAA;AAAA,QACR,WAAW,GAAA,CAAI,SAAA;AAAA,QACf;AAAA,OACF;AAAA,IACA,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"run-handler.js","sourcesContent":["/**\n * Run Manager - tracks active agent runs for REST/WS API\n *\n * Uses platform cache for persistence and in-memory Map for active agents.\n * Cache stores serializable run state, Map stores live agent references.\n */\n\nimport type { IAgentRunner } from '@kb-labs/agent-sdk';\nimport type { SessionManager } from '@kb-labs/agent-core';\nimport type { Turn, TurnDelta } from '@kb-labs/agent-contracts';\nimport { useCache } from '@kb-labs/sdk';\n\nconst CACHE_PREFIX = 'agent:run:';\nconst CACHE_TTL = 3600000; // 1 hour\n\n/**\n * Run status\n */\nexport type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';\n\n/**\n * Serializable run state (stored in cache)\n */\nexport interface RunState {\n runId: string;\n task: string;\n status: RunStatus;\n startedAt: string;\n completedAt?: string;\n durationMs?: number;\n summary?: string;\n error?: string;\n}\n\n/**\n * Active run with live agent (in-memory only)\n */\nexport interface ActiveRun extends RunState {\n agent?: IAgentRunner;\n sessionManager: SessionManager;\n}\n\n/**\n * Payload delivered to session-level listeners — the sole live-update\n * channel for a session's WS connection(s). `deltas` carries incremental\n * turn changes (see TurnDelta); `run:completed` is a terminal signal\n * carrying the finished run's outcome and, when available, the final\n * state of the assistant turn it produced.\n */\nexport type SessionBroadcastPayload =\n | { kind: 'deltas'; deltas: TurnDelta[] }\n | {\n kind: 'run:completed';\n runId: string;\n success: boolean;\n summary: string;\n durationMs: number;\n seq: number;\n turn?: Turn;\n };\n\ntype SessionListenerCallback = (payload: SessionBroadcastPayload) => void;\n\n/**\n * Run Manager implementation\n */\nclass RunManagerImpl {\n /** Live agents (not cacheable) */\n private activeRuns: Map<string, ActiveRun> = new Map();\n\n /** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */\n private sessionListeners: Map<string, Set<SessionListenerCallback>> = new Map();\n\n /**\n * Generate unique run ID\n */\n generateRunId(): string {\n return `run-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n }\n\n /**\n * Register a new run\n */\n async register(\n runId: string,\n task: string,\n agent: IAgentRunner | undefined,\n sessionManager: SessionManager,\n ): Promise<ActiveRun> {\n const now = new Date().toISOString();\n\n const run: ActiveRun = {\n runId,\n task,\n status: 'pending',\n agent,\n sessionManager,\n startedAt: now,\n };\n\n // Store in memory (for live agent)\n this.activeRuns.set(runId, run);\n\n // Store serializable state in cache\n await this.saveToCache(run);\n\n return run;\n }\n\n /**\n * Get run by ID (from memory first, then cache for state)\n */\n get(runId: string): ActiveRun | undefined {\n return this.activeRuns.get(runId);\n }\n\n /**\n * Check if run exists (in memory or cache)\n */\n async exists(runId: string): Promise<boolean> {\n // Check memory first\n if (this.activeRuns.has(runId)) {\n return true;\n }\n // Fallback to cache\n const state = await this.getState(runId);\n return state !== null;\n }\n\n /**\n * Get run state from cache (for completed runs or cross-process access)\n */\n async getState(runId: string): Promise<RunState | null> {\n const cache = useCache();\n if (!cache) {return null;}\n\n return cache.get<RunState>(`${CACHE_PREFIX}${runId}`);\n }\n\n /**\n * Update run status\n */\n async updateStatus(runId: string, status: RunStatus, extra?: Partial<RunState>): Promise<void> {\n const run = this.activeRuns.get(runId);\n if (run) {\n run.status = status;\n if (extra) {\n Object.assign(run, extra);\n }\n await this.saveToCache(run);\n }\n }\n\n /**\n * Save run state to cache\n */\n private async saveToCache(run: ActiveRun): Promise<void> {\n const cache = useCache();\n if (!cache) {return;}\n\n const state: RunState = {\n runId: run.runId,\n task: run.task,\n status: run.status,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n\n await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);\n }\n\n /**\n * Broadcast turn deltas to all session-level listeners. Callers MUST await\n * persistence (sessionManager.addEvent) before calling this, so listeners\n * never observe a delta whose underlying turn state isn't on disk yet —\n * that ordering is what makes gap-recovery / reconnect resume correct.\n */\n broadcastSessionDeltas(sessionId: string, deltas: TurnDelta[]): void {\n if (deltas.length === 0) { return; }\n this.notifySessionListeners(sessionId, { kind: 'deltas', deltas });\n }\n\n /**\n * Broadcast a run's terminal outcome to session-level listeners. Called\n * directly from the run's own completion handler (after `agent.execute()`\n * resolves) rather than derived reactively from an `agent:end` event —\n * the completion handler already has definitive success/summary/duration,\n * and this guarantees the message fires exactly once, deterministically.\n */\n broadcastRunCompleted(sessionId: string, payload: Omit<Extract<SessionBroadcastPayload, { kind: 'run:completed' }>, 'kind'>): void {\n this.notifySessionListeners(sessionId, { kind: 'run:completed', ...payload });\n }\n\n private notifySessionListeners(sessionId: string, payload: SessionBroadcastPayload): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (!listeners) { return; }\n for (const listener of listeners) {\n try {\n listener(payload);\n } catch {\n // Ignore listener errors — one bad WS connection shouldn't affect others\n }\n }\n }\n\n /**\n * Add a session-level listener — receives updates from ALL runs in this session.\n */\n addSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n if (!this.sessionListeners.has(sessionId)) {\n this.sessionListeners.set(sessionId, new Set());\n }\n this.sessionListeners.get(sessionId)!.add(callback);\n }\n\n /**\n * Remove a session-level listener.\n */\n removeSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.sessionListeners.delete(sessionId);\n }\n }\n }\n\n /**\n * List all active runs\n */\n listActive(): Array<{ runId: string; task: string; status: RunStatus; startedAt: string }> {\n return Array.from(this.activeRuns.values()).map(r => ({\n runId: r.runId,\n task: r.task,\n status: r.status,\n startedAt: r.startedAt,\n }));\n }\n\n /**\n * Request graceful stop of a running agent (and its child agents via propagated AbortSignal).\n * Agent finishes its current tool call then exits at the next iteration boundary.\n */\n requestStop(runId: string): boolean {\n const run = this.activeRuns.get(runId);\n if (!run || run.status !== 'running' || !run.agent) {\n return false;\n }\n run.agent.requestStop();\n return true;\n }\n\n /**\n * Clean up completed runs from memory (cache handles its own TTL)\n */\n cleanup(): void {\n for (const [runId, run] of this.activeRuns) {\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n // Remove from memory but keep in cache\n this.activeRuns.delete(runId);\n }\n }\n }\n}\n\n/**\n * Singleton instance — stored on globalThis so all bundled modules share one instance.\n * When tsup compiles multiple entry points, each gets its own module scope,\n * so a plain `export const RunManager = new RunManagerImpl()` creates separate instances.\n * Using globalThis ensures run-handler.js and session-stream-handler.js share one RunManager.\n */\nconst GLOBAL_KEY = '__kb_agent_run_manager__';\nif (!(globalThis as Record<string, unknown>)[GLOBAL_KEY]) {\n (globalThis as Record<string, unknown>)[GLOBAL_KEY] = new RunManagerImpl();\n}\nexport const RunManager = (globalThis as Record<string, unknown>)[GLOBAL_KEY] as RunManagerImpl;\n","/**\n * POST /run handler\n *\n * Starts a new agent run via Orchestrator\n */\n\nimport { defineHandler, rethrowForRest, useAnalytics, useCache, useConfig, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager, createCoreToolPack, bootstrapAgentSDK, createSessionMemoryBridge } from '@kb-labs/agent-core';\nimport { createDefaultResponseRequirementsSelector } from '@kb-labs/agent-runtime';\nimport { IncrementalTraceWriter } from '@kb-labs/agent-tracing';\n\n// Register SDKAgentRunner as the RunnerFactory (idempotent — runs once per process)\nbootstrapAgentSDK();\nimport { AgentSDK } from '@kb-labs/agent-sdk';\nimport { createToolRegistry } from '@kb-labs/agent-tools';\nimport type { RunRequest, RunResponse, AgentsPluginConfig, KernelState } from '@kb-labs/agent-contracts';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport {\n AGENTS_WS_BASE_PATH,\n AGENTS_WS_CHANNELS,\n AGENT_ANALYTICS_EVENTS,\n} from '@kb-labs/agent-contracts';\nimport { RunManager } from '../run-manager.js';\n\nconst FOLLOW_UP_SCOPE_RE = /\\b(глубже|подробнее|детал|слишком поверхност|deeper|more depth|details?)\\b/i;\n\nfunction isLikelyFollowUpScopeTask(task: string): boolean {\n return FOLLOW_UP_SCOPE_RE.test(task);\n}\n\nfunction pathExists(dir: string): boolean {\n try {\n return fs.existsSync(dir);\n } catch {\n return false;\n }\n}\n\nfunction scoreRepoFromToolPath(rawPath: string, scores: Map<string, number>): void {\n const p = rawPath.replace(/\\\\/g, '/');\n\n // Explicit repo prefix: kb-labs-xxx/...\n const explicit = p.match(/(^|\\/)(kb-labs-[^/]+)\\//);\n if (explicit?.[2]) {\n scores.set(explicit[2], (scores.get(explicit[2]) ?? 0) + 5);\n }\n\n // Heuristic by package naming patterns\n if (p.startsWith('packages/')) {\n if (/packages\\/agent[-/]/.test(p) || /agent-core|agent-tools|agent-cli|agent-task-runner/.test(p)) {\n scores.set('kb-labs-agents', (scores.get('kb-labs-agents') ?? 0) + 4);\n }\n if (/packages\\/mind[-/]/.test(p) || /mind-engine|mind-core/.test(p)) {\n scores.set('kb-labs-mind', (scores.get('kb-labs-mind') ?? 0) + 4);\n }\n }\n}\n\nasync function inferFollowUpWorkingDir(\n sessionManager: SessionManager,\n sessionId: string,\n baseWorkingDir: string,\n): Promise<string | null> {\n const events = await sessionManager.getSessionEvents(sessionId);\n if (!events.length) {\n return null;\n }\n\n // Find the latest completed run in this session\n const completedRuns = new Set<string>();\n for (const event of events) {\n if (event.type === 'agent:end' && event.runId) {\n completedRuns.add(event.runId);\n }\n }\n const lastRunId = Array.from(completedRuns).at(-1);\n if (!lastRunId) {\n return null;\n }\n\n const repoScores = new Map<string, number>();\n for (const event of events) {\n if (event.runId !== lastRunId) {\n continue;\n }\n\n if (event.type === 'tool:start') {\n const input = (event.data?.input as Record<string, unknown> | undefined) ?? {};\n const p1 = input.path;\n const p2 = input.directory;\n if (typeof p1 === 'string') {scoreRepoFromToolPath(p1, repoScores);}\n if (typeof p2 === 'string') {scoreRepoFromToolPath(p2, repoScores);}\n }\n\n if (event.type === 'tool:end') {\n const metadata = (event.data?.metadata as Record<string, unknown> | undefined) ?? {};\n const p = metadata.path;\n if (typeof p === 'string') {scoreRepoFromToolPath(p, repoScores);}\n }\n }\n\n const ranked = Array.from(repoScores.entries()).sort((a, b) => b[1] - a[1]);\n const top = ranked[0];\n if (!top || top[1] < 4) {\n return null;\n }\n\n const inferredDir = path.join(baseWorkingDir, top[0]);\n return pathExists(inferredDir) ? inferredDir : null;\n}\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<RunRequest>\n ): Promise<RunResponse> {\n try {\n const body = input.body as RunRequest | undefined;\n\n if (!body?.task) {\n throw new Error('Task is required');\n }\n\n const analytics = useAnalytics();\n const runId = RunManager.generateRunId();\n const startTime = Date.now();\n\n // Get or create session\n let sessionId = body.sessionId;\n let workingDir = body.workingDir || ctx.cwd;\n let sessionManager = new SessionManager(workingDir);\n if (!sessionId) {\n // Create new session\n const session = await sessionManager.createSession({\n mode: 'execute',\n task: body.task,\n agentId: body.agentId ?? 'orchestrator',\n });\n sessionId = session.id;\n ctx.platform.logger.info(`[run-handler] Created new session ${sessionId}`);\n } else {\n // Verify session exists (from current manager first)\n const existingSession = await sessionManager.loadSession(sessionId);\n let resolvedSession = existingSession;\n\n // Fallback: session may belong to a different root than current ctx.cwd\n if (!resolvedSession && pathExists(ctx.cwd)) {\n const fallbackManager = new SessionManager(ctx.cwd);\n const fallbackSession = await fallbackManager.loadSession(sessionId);\n if (fallbackSession) {\n sessionManager = fallbackManager;\n resolvedSession = fallbackSession;\n }\n }\n\n if (!resolvedSession) {\n throw new Error(`Session not found: ${sessionId} (cwd=${ctx.cwd})`);\n }\n\n // Session workingDir is primary source of truth for follow-up runs\n workingDir = body.workingDir || resolvedSession.workingDir || workingDir;\n\n // Smart follow-up anchoring: keep depth requests in the same repo/module as previous run\n if (!body.workingDir && isLikelyFollowUpScopeTask(body.task)) {\n const inferred = await inferFollowUpWorkingDir(sessionManager, sessionId, resolvedSession.workingDir || ctx.cwd);\n if (inferred && inferred !== workingDir) {\n ctx.platform.logger.info(`[run-handler] Follow-up scope inferred: ${workingDir} -> ${inferred}`);\n workingDir = inferred;\n }\n }\n\n // Rebind session manager to effective working directory\n sessionManager = new SessionManager(workingDir);\n ctx.platform.logger.info(`[run-handler] Continuing session ${sessionId} (workingDir=${workingDir})`);\n }\n\n ctx.platform.logger.info(`[run-handler] Starting run ${runId} for task: ${body.task}`);\n\n // Create user turn with task/question\n const userTurn = await sessionManager.createUserTurn(sessionId, body.task, runId, body.clientId);\n\n // Track run started\n await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_STARTED, {\n runId,\n sessionId,\n taskLength: body.task.length,\n tier: body.tier ?? 'medium',\n enableEscalation: body.enableEscalation ?? true,\n responseMode: body.responseMode ?? 'auto',\n verbose: body.verbose ?? false,\n });\n\n // Create tool registry with standard tools\n const sessionMemory = createSessionMemoryBridge(workingDir, sessionId);\n const responseRequirementsSelector = createDefaultResponseRequirementsSelector();\n const toolRegistry = createToolRegistry({\n workingDir,\n currentTask: body.task,\n sessionId,\n verbose: body.verbose,\n cache: useCache(),\n sessionMemory,\n responseRequirementsResolver: async ({ task, kernel }: {\n task?: string;\n answer: string;\n kernel: KernelState | null;\n }) =>\n responseRequirementsSelector.select({\n state: kernel,\n messages: [],\n task: task ?? body.task,\n }),\n });\n const agentsConfig = await useConfig<AgentsPluginConfig>();\n\n const finalSessionId = sessionId; // Capture for closure\n const traceDir = path.join(workingDir, '.kb', 'traces', 'incremental');\n const traceWriter = new IncrementalTraceWriter(runId, {}, traceDir);\n\n // Create agent with event broadcasting and session persistence\n const agent = new AgentSDK()\n .register(createCoreToolPack(toolRegistry))\n .createRunner({\n sessionId: finalSessionId,\n workingDir,\n maxIterations: 50,\n temperature: 0.1,\n tier: body.tier ?? 'medium',\n tokenBudget: agentsConfig?.tokenBudget,\n onEvent: (event) => {\n // Persist FIRST, broadcast only once that's confirmed — deltas are\n // computed from what was actually written, so a WS listener can\n // never observe turn state that isn't safely on disk yet. This\n // ordering (previously reversed: broadcast raced ahead of persist)\n // was the root cause of the WS stream silently lagging one event\n // behind the true state.\n void sessionManager.addEvent(finalSessionId, {\n ...event,\n sessionId: finalSessionId,\n runId,\n metadata: {\n ...event.metadata,\n sessionId: finalSessionId,\n runId,\n workingDir,\n },\n }).then((deltas) => {\n RunManager.broadcastSessionDeltas(finalSessionId, deltas);\n });\n },\n });\n\n // Register run (session-level WS listeners are registered separately via addSessionListener)\n const run = await RunManager.register(runId, body.task, agent, sessionManager);\n await RunManager.updateStatus(runId, 'running');\n\n // Start execution in background (don't await)\n void (async () => {\n try {\n const result = await agent.execute(body.task);\n const durationMs = Date.now() - startTime;\n const detailedTrace = traceWriter.getEntries() as unknown as Array<Record<string, unknown>>;\n await traceWriter.finalize?.();\n\n if (detailedTrace.length > 0) {\n await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);\n }\n\n // Attach file change summaries to the turn so the UI can show rollback/approve panel\n // Populated by ChangeTrackingMiddleware via run.meta → TaskResult.fileChanges\n if (result.fileChanges && result.fileChanges.length > 0) {\n await sessionManager.attachFileChangesToTurn(finalSessionId, runId, result.fileChanges);\n }\n\n await RunManager.updateStatus(runId, result.success ? 'completed' : 'failed', {\n completedAt: new Date().toISOString(),\n durationMs,\n summary: result.summary,\n error: result.error,\n });\n\n // The terminal WS signal fires from here — the run's own completion\n // handler, which has definitive success/summary/duration — rather\n // than being derived reactively from an agent:end event on the WS\n // side. Carries the final assistant turn (if this run produced one)\n // so the client has a guaranteed-fresh terminal state without\n // depending on delta message ordering.\n const finalTurns = await sessionManager.getTurns(finalSessionId);\n const finalTurn = finalTurns.find((t) => t.type === 'assistant' && t.metadata.runId === runId);\n const seq = await sessionManager.getCurrentSessionSeq(finalSessionId);\n RunManager.broadcastRunCompleted(finalSessionId, {\n runId,\n success: result.success,\n summary: result.summary,\n durationMs,\n seq,\n turn: finalTurn,\n });\n\n // Track completion\n await analytics?.track(\n result.success ? AGENT_ANALYTICS_EVENTS.RUN_COMPLETED : AGENT_ANALYTICS_EVENTS.RUN_FAILED,\n {\n runId,\n durationMs,\n success: result.success,\n summary: result.summary?.slice(0, 200),\n }\n );\n\n ctx.platform.logger.info(`[run-handler] Run ${runId} completed: ${result.success}`);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n const durationMs = Date.now() - startTime;\n const detailedTrace = traceWriter.getEntries() as unknown as Array<Record<string, unknown>>;\n await traceWriter.finalize?.();\n if (detailedTrace.length > 0) {\n await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);\n }\n\n await RunManager.updateStatus(runId, 'failed', {\n completedAt: new Date().toISOString(),\n durationMs,\n error: errorMsg,\n });\n\n const seq = await sessionManager.getCurrentSessionSeq(finalSessionId);\n RunManager.broadcastRunCompleted(finalSessionId, {\n runId,\n success: false,\n summary: errorMsg,\n durationMs,\n seq,\n });\n\n // Track failure\n await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_FAILED, {\n runId,\n durationMs,\n error: errorMsg.slice(0, 200),\n });\n\n ctx.platform.logger.error(`[run-handler] Run ${runId} failed: ${errorMsg}`);\n }\n })();\n\n // Return relative WS path — clients construct the full URL from their own base URL.\n const wsPath = AGENTS_WS_CHANNELS.SESSION_STREAM.replace(':sessionId', finalSessionId);\n const eventsPath = `${AGENTS_WS_BASE_PATH}${wsPath}`;\n\n return {\n runId,\n sessionId: finalSessionId,\n eventsPath,\n status: 'started',\n startedAt: run.startedAt,\n userTurn,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/run-manager.ts","../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/run-handler.ts"],"names":["useCache"],"mappings":"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","file":"run-handler.js","sourcesContent":["/**\n * Run Manager - tracks active agent runs for REST/WS API\n *\n * Uses platform cache for persistence and in-memory Map for active agents.\n * Cache stores serializable run state, Map stores live agent references.\n */\n\nimport type { IAgentRunner } from '@kb-labs/agent-sdk';\nimport type { SessionManager } from '@kb-labs/agent-core';\nimport type { Turn, TurnDelta } from '@kb-labs/agent-contracts';\nimport { useCache } from '@kb-labs/sdk';\n\nconst CACHE_PREFIX = 'agent:run:';\nconst CACHE_TTL = 3600000; // 1 hour\n\n/**\n * Run status\n */\nexport type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';\n\n/**\n * Serializable run state (stored in cache)\n */\nexport interface RunState {\n runId: string;\n task: string;\n status: RunStatus;\n startedAt: string;\n completedAt?: string;\n durationMs?: number;\n summary?: string;\n error?: string;\n}\n\n/**\n * Active run with live agent (in-memory only)\n */\nexport interface ActiveRun extends RunState {\n agent?: IAgentRunner;\n sessionManager: SessionManager;\n}\n\n/**\n * Payload delivered to session-level listeners — the sole live-update\n * channel for a session's WS connection(s). `deltas` carries incremental\n * turn changes (see TurnDelta); `run:completed` is a terminal signal\n * carrying the finished run's outcome and, when available, the final\n * state of the assistant turn it produced.\n */\nexport type SessionBroadcastPayload =\n | { kind: 'deltas'; deltas: TurnDelta[] }\n | {\n kind: 'run:completed';\n runId: string;\n success: boolean;\n summary: string;\n durationMs: number;\n seq: number;\n turn?: Turn;\n };\n\ntype SessionListenerCallback = (payload: SessionBroadcastPayload) => void;\n\n/**\n * Run Manager implementation\n */\nclass RunManagerImpl {\n /** Live agents (not cacheable) */\n private activeRuns: Map<string, ActiveRun> = new Map();\n\n /** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */\n private sessionListeners: Map<string, Set<SessionListenerCallback>> = new Map();\n\n /**\n * Generate unique run ID\n */\n generateRunId(): string {\n return `run-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n }\n\n /**\n * Register a new run\n */\n async register(\n runId: string,\n task: string,\n agent: IAgentRunner | undefined,\n sessionManager: SessionManager,\n ): Promise<ActiveRun> {\n const now = new Date().toISOString();\n\n const run: ActiveRun = {\n runId,\n task,\n status: 'pending',\n agent,\n sessionManager,\n startedAt: now,\n };\n\n // Store in memory (for live agent)\n this.activeRuns.set(runId, run);\n\n // Store serializable state in cache\n await this.saveToCache(run);\n\n return run;\n }\n\n /**\n * Get run by ID (from memory first, then cache for state)\n */\n get(runId: string): ActiveRun | undefined {\n return this.activeRuns.get(runId);\n }\n\n /**\n * Check if run exists (in memory or cache)\n */\n async exists(runId: string): Promise<boolean> {\n // Check memory first\n if (this.activeRuns.has(runId)) {\n return true;\n }\n // Fallback to cache\n const state = await this.getState(runId);\n return state !== null;\n }\n\n /**\n * Get run state from cache (for completed runs or cross-process access)\n */\n async getState(runId: string): Promise<RunState | null> {\n const cache = useCache();\n if (!cache) {return null;}\n\n return cache.get<RunState>(`${CACHE_PREFIX}${runId}`);\n }\n\n /**\n * Update run status\n */\n async updateStatus(runId: string, status: RunStatus, extra?: Partial<RunState>): Promise<void> {\n const run = this.activeRuns.get(runId);\n if (run) {\n run.status = status;\n if (extra) {\n Object.assign(run, extra);\n }\n await this.saveToCache(run);\n }\n }\n\n /**\n * Save run state to cache\n */\n private async saveToCache(run: ActiveRun): Promise<void> {\n const cache = useCache();\n if (!cache) {return;}\n\n const state: RunState = {\n runId: run.runId,\n task: run.task,\n status: run.status,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n\n await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);\n }\n\n /**\n * Broadcast turn deltas to all session-level listeners. Callers MUST await\n * persistence (sessionManager.addEvent) before calling this, so listeners\n * never observe a delta whose underlying turn state isn't on disk yet —\n * that ordering is what makes gap-recovery / reconnect resume correct.\n */\n broadcastSessionDeltas(sessionId: string, deltas: TurnDelta[]): void {\n if (deltas.length === 0) { return; }\n this.notifySessionListeners(sessionId, { kind: 'deltas', deltas });\n }\n\n /**\n * Broadcast a run's terminal outcome to session-level listeners. Called\n * directly from the run's own completion handler (after `agent.execute()`\n * resolves) rather than derived reactively from an `agent:end` event —\n * the completion handler already has definitive success/summary/duration,\n * and this guarantees the message fires exactly once, deterministically.\n */\n broadcastRunCompleted(sessionId: string, payload: Omit<Extract<SessionBroadcastPayload, { kind: 'run:completed' }>, 'kind'>): void {\n this.notifySessionListeners(sessionId, { kind: 'run:completed', ...payload });\n }\n\n private notifySessionListeners(sessionId: string, payload: SessionBroadcastPayload): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (!listeners) { return; }\n for (const listener of listeners) {\n try {\n listener(payload);\n } catch {\n // Ignore listener errors — one bad WS connection shouldn't affect others\n }\n }\n }\n\n /**\n * Add a session-level listener — receives updates from ALL runs in this session.\n */\n addSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n if (!this.sessionListeners.has(sessionId)) {\n this.sessionListeners.set(sessionId, new Set());\n }\n this.sessionListeners.get(sessionId)!.add(callback);\n }\n\n /**\n * Remove a session-level listener.\n */\n removeSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.sessionListeners.delete(sessionId);\n }\n }\n }\n\n /**\n * List all active runs\n */\n listActive(): Array<{ runId: string; task: string; status: RunStatus; startedAt: string }> {\n return Array.from(this.activeRuns.values()).map(r => ({\n runId: r.runId,\n task: r.task,\n status: r.status,\n startedAt: r.startedAt,\n }));\n }\n\n /**\n * Request graceful stop of a running agent (and its child agents via propagated AbortSignal).\n * Agent finishes its current tool call then exits at the next iteration boundary.\n */\n requestStop(runId: string): boolean {\n const run = this.activeRuns.get(runId);\n if (!run || run.status !== 'running' || !run.agent) {\n return false;\n }\n run.agent.requestStop();\n return true;\n }\n\n /**\n * Clean up completed runs from memory (cache handles its own TTL)\n */\n cleanup(): void {\n for (const [runId, run] of this.activeRuns) {\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n // Remove from memory but keep in cache\n this.activeRuns.delete(runId);\n }\n }\n }\n}\n\n/**\n * Singleton instance — stored on globalThis so all bundled modules share one instance.\n * When tsup compiles multiple entry points, each gets its own module scope,\n * so a plain `export const RunManager = new RunManagerImpl()` creates separate instances.\n * Using globalThis ensures run-handler.js and session-stream-handler.js share one RunManager.\n */\nconst GLOBAL_KEY = '__kb_agent_run_manager__';\nif (!(globalThis as Record<string, unknown>)[GLOBAL_KEY]) {\n (globalThis as Record<string, unknown>)[GLOBAL_KEY] = new RunManagerImpl();\n}\nexport const RunManager = (globalThis as Record<string, unknown>)[GLOBAL_KEY] as RunManagerImpl;\n","/**\n * POST /run handler\n *\n * Starts a new agent run via Orchestrator\n */\n\nimport { defineHandler, rethrowForRest, useAnalytics, useCache, useConfig, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager, createCoreToolPack, bootstrapAgentSDK, createSessionMemoryBridge } from '@kb-labs/agent-core';\nimport { createDefaultResponseRequirementsSelector } from '@kb-labs/agent-runtime';\nimport { IncrementalTraceWriter } from '@kb-labs/agent-tracing';\n\n// Register SDKAgentRunner as the RunnerFactory (idempotent — runs once per process)\nbootstrapAgentSDK();\nimport { AgentSDK } from '@kb-labs/agent-sdk';\nimport { createToolRegistry } from '@kb-labs/agent-tools';\nimport type { RunRequest, RunResponse, AgentsPluginConfig, KernelState } from '@kb-labs/agent-contracts';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport {\n AGENTS_WS_BASE_PATH,\n AGENTS_WS_CHANNELS,\n AGENT_ANALYTICS_EVENTS,\n} from '@kb-labs/agent-contracts';\nimport { RunManager } from '../run-manager.js';\n\nconst FOLLOW_UP_SCOPE_RE = /\\b(глубже|подробнее|детал|слишком поверхност|deeper|more depth|details?)\\b/i;\n\nfunction isLikelyFollowUpScopeTask(task: string): boolean {\n return FOLLOW_UP_SCOPE_RE.test(task);\n}\n\nfunction pathExists(dir: string): boolean {\n try {\n return fs.existsSync(dir);\n } catch {\n return false;\n }\n}\n\nfunction scoreRepoFromToolPath(rawPath: string, scores: Map<string, number>): void {\n const p = rawPath.replace(/\\\\/g, '/');\n\n // Explicit repo prefix: kb-labs-xxx/...\n const explicit = p.match(/(^|\\/)(kb-labs-[^/]+)\\//);\n if (explicit?.[2]) {\n scores.set(explicit[2], (scores.get(explicit[2]) ?? 0) + 5);\n }\n\n // Heuristic by package naming patterns\n if (p.startsWith('packages/')) {\n if (/packages\\/agent[-/]/.test(p) || /agent-core|agent-tools|agent-cli|agent-task-runner/.test(p)) {\n scores.set('kb-labs-agents', (scores.get('kb-labs-agents') ?? 0) + 4);\n }\n if (/packages\\/mind[-/]/.test(p) || /mind-engine|mind-core/.test(p)) {\n scores.set('kb-labs-mind', (scores.get('kb-labs-mind') ?? 0) + 4);\n }\n }\n}\n\nasync function inferFollowUpWorkingDir(\n sessionManager: SessionManager,\n sessionId: string,\n baseWorkingDir: string,\n): Promise<string | null> {\n const events = await sessionManager.getSessionEvents(sessionId);\n if (!events.length) {\n return null;\n }\n\n // Find the latest completed run in this session\n const completedRuns = new Set<string>();\n for (const event of events) {\n if (event.type === 'agent:end' && event.runId) {\n completedRuns.add(event.runId);\n }\n }\n const lastRunId = Array.from(completedRuns).at(-1);\n if (!lastRunId) {\n return null;\n }\n\n const repoScores = new Map<string, number>();\n for (const event of events) {\n if (event.runId !== lastRunId) {\n continue;\n }\n\n if (event.type === 'tool:start') {\n const input = (event.data?.input as Record<string, unknown> | undefined) ?? {};\n const p1 = input.path;\n const p2 = input.directory;\n if (typeof p1 === 'string') {scoreRepoFromToolPath(p1, repoScores);}\n if (typeof p2 === 'string') {scoreRepoFromToolPath(p2, repoScores);}\n }\n\n if (event.type === 'tool:end') {\n const metadata = (event.data?.metadata as Record<string, unknown> | undefined) ?? {};\n const p = metadata.path;\n if (typeof p === 'string') {scoreRepoFromToolPath(p, repoScores);}\n }\n }\n\n const ranked = Array.from(repoScores.entries()).sort((a, b) => b[1] - a[1]);\n const top = ranked[0];\n if (!top || top[1] < 4) {\n return null;\n }\n\n const inferredDir = path.join(baseWorkingDir, top[0]);\n return pathExists(inferredDir) ? inferredDir : null;\n}\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<RunRequest>\n ): Promise<RunResponse> {\n try {\n const body = input.body as RunRequest | undefined;\n\n if (!body?.task) {\n throw new Error('Task is required');\n }\n\n const analytics = useAnalytics();\n const runId = RunManager.generateRunId();\n const startTime = Date.now();\n\n // Get or create session\n let sessionId = body.sessionId;\n let workingDir = body.workingDir || ctx.cwd;\n let sessionManager = new SessionManager(workingDir);\n if (!sessionId) {\n // Create new session\n const session = await sessionManager.createSession({\n mode: 'execute',\n task: body.task,\n agentId: body.agentId ?? 'orchestrator',\n });\n sessionId = session.id;\n ctx.platform.logger.info(`[run-handler] Created new session ${sessionId}`);\n } else {\n // Verify session exists (from current manager first)\n const existingSession = await sessionManager.loadSession(sessionId);\n let resolvedSession = existingSession;\n\n // Fallback: session may belong to a different root than current ctx.cwd\n if (!resolvedSession && pathExists(ctx.cwd)) {\n const fallbackManager = new SessionManager(ctx.cwd);\n const fallbackSession = await fallbackManager.loadSession(sessionId);\n if (fallbackSession) {\n sessionManager = fallbackManager;\n resolvedSession = fallbackSession;\n }\n }\n\n if (!resolvedSession) {\n throw new Error(`Session not found: ${sessionId} (cwd=${ctx.cwd})`);\n }\n\n // Session workingDir is primary source of truth for follow-up runs\n workingDir = body.workingDir || resolvedSession.workingDir || workingDir;\n\n // Smart follow-up anchoring: keep depth requests in the same repo/module as previous run\n if (!body.workingDir && isLikelyFollowUpScopeTask(body.task)) {\n const inferred = await inferFollowUpWorkingDir(sessionManager, sessionId, resolvedSession.workingDir || ctx.cwd);\n if (inferred && inferred !== workingDir) {\n ctx.platform.logger.info(`[run-handler] Follow-up scope inferred: ${workingDir} -> ${inferred}`);\n workingDir = inferred;\n }\n }\n\n // Rebind session manager to effective working directory\n sessionManager = new SessionManager(workingDir);\n ctx.platform.logger.info(`[run-handler] Continuing session ${sessionId} (workingDir=${workingDir})`);\n }\n\n ctx.platform.logger.info(`[run-handler] Starting run ${runId} for task: ${body.task}`);\n\n // Create user turn with task/question\n const userTurn = await sessionManager.createUserTurn(sessionId, body.task, runId, body.clientId);\n\n // Track run started\n await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_STARTED, {\n runId,\n sessionId,\n taskLength: body.task.length,\n tier: body.tier ?? 'medium',\n enableEscalation: body.enableEscalation ?? true,\n responseMode: body.responseMode ?? 'auto',\n verbose: body.verbose ?? false,\n });\n\n // Create tool registry with standard tools\n const sessionMemory = createSessionMemoryBridge(workingDir, sessionId);\n const responseRequirementsSelector = createDefaultResponseRequirementsSelector();\n const toolRegistry = createToolRegistry({\n workingDir,\n currentTask: body.task,\n sessionId,\n verbose: body.verbose,\n cache: useCache(),\n sessionMemory,\n responseRequirementsResolver: async ({ task, kernel }: {\n task?: string;\n answer: string;\n kernel: KernelState | null;\n }) =>\n responseRequirementsSelector.select({\n state: kernel,\n messages: [],\n task: task ?? body.task,\n }),\n });\n const agentsConfig = await useConfig<AgentsPluginConfig>();\n\n const finalSessionId = sessionId; // Capture for closure\n const traceDir = path.join(workingDir, '.kb', 'traces', 'incremental');\n const traceWriter = new IncrementalTraceWriter(runId, {}, traceDir);\n\n // Create agent with event broadcasting and session persistence\n const agent = new AgentSDK()\n .register(createCoreToolPack(toolRegistry))\n .createRunner({\n sessionId: finalSessionId,\n workingDir,\n maxIterations: 50,\n temperature: 0.1,\n tier: body.tier ?? 'medium',\n tokenBudget: agentsConfig?.tokenBudget,\n onEvent: (event) => {\n // Persist FIRST, broadcast only once that's confirmed — deltas are\n // computed from what was actually written, so a WS listener can\n // never observe turn state that isn't safely on disk yet. This\n // ordering (previously reversed: broadcast raced ahead of persist)\n // was the root cause of the WS stream silently lagging one event\n // behind the true state.\n void sessionManager.addEvent(finalSessionId, {\n ...event,\n sessionId: finalSessionId,\n runId,\n metadata: {\n ...event.metadata,\n sessionId: finalSessionId,\n runId,\n workingDir,\n },\n }).then((deltas) => {\n RunManager.broadcastSessionDeltas(finalSessionId, deltas);\n });\n },\n });\n\n // Register run (session-level WS listeners are registered separately via addSessionListener)\n const run = await RunManager.register(runId, body.task, agent, sessionManager);\n await RunManager.updateStatus(runId, 'running');\n\n // Start execution in background (don't await)\n void (async () => {\n try {\n const result = await agent.execute(body.task);\n const durationMs = Date.now() - startTime;\n const detailedTrace = traceWriter.getEntries() as unknown as Array<Record<string, unknown>>;\n await traceWriter.finalize?.();\n\n if (detailedTrace.length > 0) {\n await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);\n }\n\n // Attach file change summaries to the turn so the UI can show rollback/approve panel\n // Populated by ChangeTrackingMiddleware via run.meta → TaskResult.fileChanges\n if (result.fileChanges && result.fileChanges.length > 0) {\n await sessionManager.attachFileChangesToTurn(finalSessionId, runId, result.fileChanges);\n }\n\n await RunManager.updateStatus(runId, result.success ? 'completed' : 'failed', {\n completedAt: new Date().toISOString(),\n durationMs,\n summary: result.summary,\n error: result.error,\n });\n\n // The terminal WS signal fires from here — the run's own completion\n // handler, which has definitive success/summary/duration — rather\n // than being derived reactively from an agent:end event on the WS\n // side. Carries the final assistant turn (if this run produced one)\n // so the client has a guaranteed-fresh terminal state without\n // depending on delta message ordering.\n const finalTurns = await sessionManager.getTurns(finalSessionId);\n const finalTurn = finalTurns.find((t) => t.type === 'assistant' && t.metadata.runId === runId);\n const seq = await sessionManager.getCurrentSessionSeq(finalSessionId);\n RunManager.broadcastRunCompleted(finalSessionId, {\n runId,\n success: result.success,\n summary: result.summary,\n durationMs,\n seq,\n turn: finalTurn,\n });\n\n // Track completion\n await analytics?.track(\n result.success ? AGENT_ANALYTICS_EVENTS.RUN_COMPLETED : AGENT_ANALYTICS_EVENTS.RUN_FAILED,\n {\n runId,\n durationMs,\n success: result.success,\n summary: result.summary?.slice(0, 200),\n }\n );\n\n ctx.platform.logger.info(`[run-handler] Run ${runId} completed: ${result.success}`);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n const durationMs = Date.now() - startTime;\n const detailedTrace = traceWriter.getEntries() as unknown as Array<Record<string, unknown>>;\n await traceWriter.finalize?.();\n if (detailedTrace.length > 0) {\n await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);\n }\n\n await RunManager.updateStatus(runId, 'failed', {\n completedAt: new Date().toISOString(),\n durationMs,\n error: errorMsg,\n });\n\n const seq = await sessionManager.getCurrentSessionSeq(finalSessionId);\n RunManager.broadcastRunCompleted(finalSessionId, {\n runId,\n success: false,\n summary: errorMsg,\n durationMs,\n seq,\n });\n\n // Track failure\n await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_FAILED, {\n runId,\n durationMs,\n error: errorMsg.slice(0, 200),\n });\n\n ctx.platform.logger.error(`[run-handler] Run ${runId} failed: ${errorMsg}`);\n }\n })();\n\n // Return relative WS path — clients construct the full URL from their own base URL.\n const wsPath = AGENTS_WS_CHANNELS.SESSION_STREAM.replace(':sessionId', finalSessionId);\n const eventsPath = `${AGENTS_WS_BASE_PATH}${wsPath}`;\n\n return {\n runId,\n sessionId: finalSessionId,\n eventsPath,\n status: 'started',\n startedAt: run.startedAt,\n userTurn,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/rest/handlers/sessions-handler.ts"],"names":[],"mappings":";;;;AAkBO,IAAM,sBAAsB,aAAA,CAAc;AAAA,EAC/C,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EAC+B;AAC/B,IAAA,IAAI;AACF,MAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AACpB,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAEjD,MAAA,MAAM,MAAA,GAAS,MAAM,cAAA,CAAe,YAAA,CAAa;AAAA,QAC/C,SAAS,KAAA,EAAO,OAAA;AAAA,QAChB,QAAQ,KAAA,EAAO,MAAA;AAAA,QACf,KAAA,EAAO,OAAO,KAAA,IAAS,EAAA;AAAA,QACvB,MAAA,EAAQ,OAAO,MAAA,IAAU;AAAA,OAC1B,CAAA;AAED,MAAA,OAAO;AAAA,QACL,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,OAAO,MAAA,CAAO;AAAA,OAChB;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC;AAKM,IAAM,oBAAoB,aAAA,CAAc;AAAA,EAC7C,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EAC6B;AAC7B,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,MAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAE1B,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,MAC1C;AAEA,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AACjD,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,cAAA,CAAe,SAAS,CAAA;AAE7D,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,MACnD;AAEA,MAAA,OAAO,EAAE,OAAA,EAAQ;AAAA,IACnB,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC;AAKM,IAAM,uBAAuB,aAAA,CAAc;AAAA,EAChD,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EACgC;AAChC,IAAA,IAAI;AACF,MAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AAEnB,MAAA,IAAI,CAAC,MAAM,OAAA,EAAS;AAClB,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AAEA,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAEjD,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,aAAA,CAAc;AAAA,QACjD,IAAA,EAAM,SAAA;AAAA,QACN,IAAA,EAAM,KAAK,IAAA,IAAQ,EAAA;AAAA,QACnB,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,MAAM,IAAA,CAAK;AAAA,OACZ,CAAA;AAED,MAAA,GAAA,CAAI,QAAA,CAAS,OAAO,IAAA,CAAK,CAAA,mCAAA,EAAsC,QAAQ,EAAE,CAAA,WAAA,EAAc,IAAA,CAAK,OAAO,CAAA,CAAE,CAAA;AAErG,MAAA,OAAO,EAAE,OAAA,EAAQ;AAAA,IACnB,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"sessions-handler.js","sourcesContent":["/**\n * Session management REST handlers\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager } from '@kb-labs/agent-core';\nimport type {\n ListSessionsRequest,\n ListSessionsResponse,\n GetSessionRequest,\n GetSessionResponse,\n CreateSessionRequest,\n CreateSessionResponse,\n} from '@kb-labs/agent-contracts';\n\n/**\n * GET /sessions - List all sessions\n */\nexport const listSessionsHandler = defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<ListSessionsRequest>\n ): Promise<ListSessionsResponse> {\n try {\n const query = input.query as ListSessionsRequest | undefined;\n const sessionManager = new SessionManager(ctx.cwd);\n\n const result = await sessionManager.listSessions({\n agentId: query?.agentId,\n status: query?.status,\n limit: query?.limit ?? 50,\n offset: query?.offset ?? 0,\n });\n\n return {\n sessions: result.sessions,\n total: result.total,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n\n/**\n * GET /sessions/:sessionId - Get session details\n */\nexport const getSessionHandler = defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<GetSessionRequest>\n ): Promise<GetSessionResponse> {\n try {\n const params = input.params as Record<string, string> | undefined;\n const sessionId = params?.sessionId;\n\n if (!sessionId) {\n throw new Error('Session ID is required');\n }\n\n const sessionManager = new SessionManager(ctx.cwd);\n const session = await sessionManager.getSessionInfo(sessionId);\n\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n return { session };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n\n/**\n * POST /sessions - Create a new session\n */\nexport const createSessionHandler = defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<CreateSessionRequest>\n ): Promise<CreateSessionResponse> {\n try {\n const body = input.body as CreateSessionRequest | undefined;\n\n if (!body?.agentId) {\n throw new Error('Agent ID is required');\n }\n\n const sessionManager = new SessionManager(ctx.cwd);\n\n const session = await sessionManager.createSession({\n mode: 'execute',\n task: body.task ?? '',\n agentId: body.agentId,\n name: body.name,\n });\n\n ctx.platform.logger.info(`[sessions-handler] Created session ${session.id} for agent ${body.agentId}`);\n\n return { session };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/sessions-handler.ts"],"names":[],"mappings":";;;;AAkBO,IAAM,sBAAsB,aAAA,CAAc;AAAA,EAC/C,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EAC+B;AAC/B,IAAA,IAAI;AACF,MAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AACpB,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAEjD,MAAA,MAAM,MAAA,GAAS,MAAM,cAAA,CAAe,YAAA,CAAa;AAAA,QAC/C,SAAS,KAAA,EAAO,OAAA;AAAA,QAChB,QAAQ,KAAA,EAAO,MAAA;AAAA,QACf,KAAA,EAAO,OAAO,KAAA,IAAS,EAAA;AAAA,QACvB,MAAA,EAAQ,OAAO,MAAA,IAAU;AAAA,OAC1B,CAAA;AAED,MAAA,OAAO;AAAA,QACL,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,OAAO,MAAA,CAAO;AAAA,OAChB;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC;AAKM,IAAM,oBAAoB,aAAA,CAAc;AAAA,EAC7C,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EAC6B;AAC7B,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,MAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAE1B,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,MAC1C;AAEA,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AACjD,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,cAAA,CAAe,SAAS,CAAA;AAE7D,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,MACnD;AAEA,MAAA,OAAO,EAAE,OAAA,EAAQ;AAAA,IACnB,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC;AAKM,IAAM,uBAAuB,aAAA,CAAc;AAAA,EAChD,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EACgC;AAChC,IAAA,IAAI;AACF,MAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AAEnB,MAAA,IAAI,CAAC,MAAM,OAAA,EAAS;AAClB,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AAEA,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAEjD,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,aAAA,CAAc;AAAA,QACjD,IAAA,EAAM,SAAA;AAAA,QACN,IAAA,EAAM,KAAK,IAAA,IAAQ,EAAA;AAAA,QACnB,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,MAAM,IAAA,CAAK;AAAA,OACZ,CAAA;AAED,MAAA,GAAA,CAAI,QAAA,CAAS,OAAO,IAAA,CAAK,CAAA,mCAAA,EAAsC,QAAQ,EAAE,CAAA,WAAA,EAAc,IAAA,CAAK,OAAO,CAAA,CAAE,CAAA;AAErG,MAAA,OAAO,EAAE,OAAA,EAAQ;AAAA,IACnB,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"sessions-handler.js","sourcesContent":["/**\n * Session management REST handlers\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager } from '@kb-labs/agent-core';\nimport type {\n ListSessionsRequest,\n ListSessionsResponse,\n GetSessionRequest,\n GetSessionResponse,\n CreateSessionRequest,\n CreateSessionResponse,\n} from '@kb-labs/agent-contracts';\n\n/**\n * GET /sessions - List all sessions\n */\nexport const listSessionsHandler = defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<ListSessionsRequest>\n ): Promise<ListSessionsResponse> {\n try {\n const query = input.query as ListSessionsRequest | undefined;\n const sessionManager = new SessionManager(ctx.cwd);\n\n const result = await sessionManager.listSessions({\n agentId: query?.agentId,\n status: query?.status,\n limit: query?.limit ?? 50,\n offset: query?.offset ?? 0,\n });\n\n return {\n sessions: result.sessions,\n total: result.total,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n\n/**\n * GET /sessions/:sessionId - Get session details\n */\nexport const getSessionHandler = defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<GetSessionRequest>\n ): Promise<GetSessionResponse> {\n try {\n const params = input.params as Record<string, string> | undefined;\n const sessionId = params?.sessionId;\n\n if (!sessionId) {\n throw new Error('Session ID is required');\n }\n\n const sessionManager = new SessionManager(ctx.cwd);\n const session = await sessionManager.getSessionInfo(sessionId);\n\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n return { session };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n\n/**\n * POST /sessions - Create a new session\n */\nexport const createSessionHandler = defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<CreateSessionRequest>\n ): Promise<CreateSessionResponse> {\n try {\n const body = input.body as CreateSessionRequest | undefined;\n\n if (!body?.agentId) {\n throw new Error('Agent ID is required');\n }\n\n const sessionManager = new SessionManager(ctx.cwd);\n\n const session = await sessionManager.createSession({\n mode: 'execute',\n task: body.task ?? '',\n agentId: body.agentId,\n name: body.name,\n });\n\n ctx.platform.logger.info(`[sessions-handler] Created session ${session.id} for agent ${body.agentId}`);\n\n return { session };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/rest/run-manager.ts","../../../src/rest/handlers/status-handler.ts"],"names":[],"mappings":"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","file":"status-handler.js","sourcesContent":["/**\n * Run Manager - tracks active agent runs for REST/WS API\n *\n * Uses platform cache for persistence and in-memory Map for active agents.\n * Cache stores serializable run state, Map stores live agent references.\n */\n\nimport type { IAgentRunner } from '@kb-labs/agent-sdk';\nimport type { SessionManager } from '@kb-labs/agent-core';\nimport type { Turn, TurnDelta } from '@kb-labs/agent-contracts';\nimport { useCache } from '@kb-labs/sdk';\n\nconst CACHE_PREFIX = 'agent:run:';\nconst CACHE_TTL = 3600000; // 1 hour\n\n/**\n * Run status\n */\nexport type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';\n\n/**\n * Serializable run state (stored in cache)\n */\nexport interface RunState {\n runId: string;\n task: string;\n status: RunStatus;\n startedAt: string;\n completedAt?: string;\n durationMs?: number;\n summary?: string;\n error?: string;\n}\n\n/**\n * Active run with live agent (in-memory only)\n */\nexport interface ActiveRun extends RunState {\n agent?: IAgentRunner;\n sessionManager: SessionManager;\n}\n\n/**\n * Payload delivered to session-level listeners — the sole live-update\n * channel for a session's WS connection(s). `deltas` carries incremental\n * turn changes (see TurnDelta); `run:completed` is a terminal signal\n * carrying the finished run's outcome and, when available, the final\n * state of the assistant turn it produced.\n */\nexport type SessionBroadcastPayload =\n | { kind: 'deltas'; deltas: TurnDelta[] }\n | {\n kind: 'run:completed';\n runId: string;\n success: boolean;\n summary: string;\n durationMs: number;\n seq: number;\n turn?: Turn;\n };\n\ntype SessionListenerCallback = (payload: SessionBroadcastPayload) => void;\n\n/**\n * Run Manager implementation\n */\nclass RunManagerImpl {\n /** Live agents (not cacheable) */\n private activeRuns: Map<string, ActiveRun> = new Map();\n\n /** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */\n private sessionListeners: Map<string, Set<SessionListenerCallback>> = new Map();\n\n /**\n * Generate unique run ID\n */\n generateRunId(): string {\n return `run-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n }\n\n /**\n * Register a new run\n */\n async register(\n runId: string,\n task: string,\n agent: IAgentRunner | undefined,\n sessionManager: SessionManager,\n ): Promise<ActiveRun> {\n const now = new Date().toISOString();\n\n const run: ActiveRun = {\n runId,\n task,\n status: 'pending',\n agent,\n sessionManager,\n startedAt: now,\n };\n\n // Store in memory (for live agent)\n this.activeRuns.set(runId, run);\n\n // Store serializable state in cache\n await this.saveToCache(run);\n\n return run;\n }\n\n /**\n * Get run by ID (from memory first, then cache for state)\n */\n get(runId: string): ActiveRun | undefined {\n return this.activeRuns.get(runId);\n }\n\n /**\n * Check if run exists (in memory or cache)\n */\n async exists(runId: string): Promise<boolean> {\n // Check memory first\n if (this.activeRuns.has(runId)) {\n return true;\n }\n // Fallback to cache\n const state = await this.getState(runId);\n return state !== null;\n }\n\n /**\n * Get run state from cache (for completed runs or cross-process access)\n */\n async getState(runId: string): Promise<RunState | null> {\n const cache = useCache();\n if (!cache) {return null;}\n\n return cache.get<RunState>(`${CACHE_PREFIX}${runId}`);\n }\n\n /**\n * Update run status\n */\n async updateStatus(runId: string, status: RunStatus, extra?: Partial<RunState>): Promise<void> {\n const run = this.activeRuns.get(runId);\n if (run) {\n run.status = status;\n if (extra) {\n Object.assign(run, extra);\n }\n await this.saveToCache(run);\n }\n }\n\n /**\n * Save run state to cache\n */\n private async saveToCache(run: ActiveRun): Promise<void> {\n const cache = useCache();\n if (!cache) {return;}\n\n const state: RunState = {\n runId: run.runId,\n task: run.task,\n status: run.status,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n\n await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);\n }\n\n /**\n * Broadcast turn deltas to all session-level listeners. Callers MUST await\n * persistence (sessionManager.addEvent) before calling this, so listeners\n * never observe a delta whose underlying turn state isn't on disk yet —\n * that ordering is what makes gap-recovery / reconnect resume correct.\n */\n broadcastSessionDeltas(sessionId: string, deltas: TurnDelta[]): void {\n if (deltas.length === 0) { return; }\n this.notifySessionListeners(sessionId, { kind: 'deltas', deltas });\n }\n\n /**\n * Broadcast a run's terminal outcome to session-level listeners. Called\n * directly from the run's own completion handler (after `agent.execute()`\n * resolves) rather than derived reactively from an `agent:end` event —\n * the completion handler already has definitive success/summary/duration,\n * and this guarantees the message fires exactly once, deterministically.\n */\n broadcastRunCompleted(sessionId: string, payload: Omit<Extract<SessionBroadcastPayload, { kind: 'run:completed' }>, 'kind'>): void {\n this.notifySessionListeners(sessionId, { kind: 'run:completed', ...payload });\n }\n\n private notifySessionListeners(sessionId: string, payload: SessionBroadcastPayload): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (!listeners) { return; }\n for (const listener of listeners) {\n try {\n listener(payload);\n } catch {\n // Ignore listener errors — one bad WS connection shouldn't affect others\n }\n }\n }\n\n /**\n * Add a session-level listener — receives updates from ALL runs in this session.\n */\n addSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n if (!this.sessionListeners.has(sessionId)) {\n this.sessionListeners.set(sessionId, new Set());\n }\n this.sessionListeners.get(sessionId)!.add(callback);\n }\n\n /**\n * Remove a session-level listener.\n */\n removeSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.sessionListeners.delete(sessionId);\n }\n }\n }\n\n /**\n * List all active runs\n */\n listActive(): Array<{ runId: string; task: string; status: RunStatus; startedAt: string }> {\n return Array.from(this.activeRuns.values()).map(r => ({\n runId: r.runId,\n task: r.task,\n status: r.status,\n startedAt: r.startedAt,\n }));\n }\n\n /**\n * Request graceful stop of a running agent (and its child agents via propagated AbortSignal).\n * Agent finishes its current tool call then exits at the next iteration boundary.\n */\n requestStop(runId: string): boolean {\n const run = this.activeRuns.get(runId);\n if (!run || run.status !== 'running' || !run.agent) {\n return false;\n }\n run.agent.requestStop();\n return true;\n }\n\n /**\n * Clean up completed runs from memory (cache handles its own TTL)\n */\n cleanup(): void {\n for (const [runId, run] of this.activeRuns) {\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n // Remove from memory but keep in cache\n this.activeRuns.delete(runId);\n }\n }\n }\n}\n\n/**\n * Singleton instance — stored on globalThis so all bundled modules share one instance.\n * When tsup compiles multiple entry points, each gets its own module scope,\n * so a plain `export const RunManager = new RunManagerImpl()` creates separate instances.\n * Using globalThis ensures run-handler.js and session-stream-handler.js share one RunManager.\n */\nconst GLOBAL_KEY = '__kb_agent_run_manager__';\nif (!(globalThis as Record<string, unknown>)[GLOBAL_KEY]) {\n (globalThis as Record<string, unknown>)[GLOBAL_KEY] = new RunManagerImpl();\n}\nexport const RunManager = (globalThis as Record<string, unknown>)[GLOBAL_KEY] as RunManagerImpl;\n","/**\n * GET /run/:runId handler\n *\n * Returns current status of a run\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport type { RunStatusResponse } from '@kb-labs/agent-contracts';\nimport { RunManager } from '../run-manager.js';\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<void>\n ): Promise<RunStatusResponse> {\n try {\n const { runId } = input.params as { runId: string };\n\n // First try to get active run from memory\n const run = RunManager.get(runId);\n\n if (!run) {\n // If not in memory, check cache for completed runs\n const state = await RunManager.getState(runId);\n\n if (!state) {\n // Return 404-like response\n return {\n runId,\n status: 'failed',\n task: '',\n startedAt: '',\n error: `Run ${runId} not found`,\n };\n }\n\n // Return cached state (no active orchestrator)\n return {\n runId: state.runId,\n status: state.status,\n task: state.task,\n startedAt: state.startedAt,\n completedAt: state.completedAt,\n durationMs: state.durationMs,\n summary: state.summary,\n error: state.error,\n };\n }\n\n return {\n runId: run.runId,\n status: run.status,\n task: run.task,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/run-manager.ts","../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/status-handler.ts"],"names":[],"mappings":"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","file":"status-handler.js","sourcesContent":["/**\n * Run Manager - tracks active agent runs for REST/WS API\n *\n * Uses platform cache for persistence and in-memory Map for active agents.\n * Cache stores serializable run state, Map stores live agent references.\n */\n\nimport type { IAgentRunner } from '@kb-labs/agent-sdk';\nimport type { SessionManager } from '@kb-labs/agent-core';\nimport type { Turn, TurnDelta } from '@kb-labs/agent-contracts';\nimport { useCache } from '@kb-labs/sdk';\n\nconst CACHE_PREFIX = 'agent:run:';\nconst CACHE_TTL = 3600000; // 1 hour\n\n/**\n * Run status\n */\nexport type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';\n\n/**\n * Serializable run state (stored in cache)\n */\nexport interface RunState {\n runId: string;\n task: string;\n status: RunStatus;\n startedAt: string;\n completedAt?: string;\n durationMs?: number;\n summary?: string;\n error?: string;\n}\n\n/**\n * Active run with live agent (in-memory only)\n */\nexport interface ActiveRun extends RunState {\n agent?: IAgentRunner;\n sessionManager: SessionManager;\n}\n\n/**\n * Payload delivered to session-level listeners — the sole live-update\n * channel for a session's WS connection(s). `deltas` carries incremental\n * turn changes (see TurnDelta); `run:completed` is a terminal signal\n * carrying the finished run's outcome and, when available, the final\n * state of the assistant turn it produced.\n */\nexport type SessionBroadcastPayload =\n | { kind: 'deltas'; deltas: TurnDelta[] }\n | {\n kind: 'run:completed';\n runId: string;\n success: boolean;\n summary: string;\n durationMs: number;\n seq: number;\n turn?: Turn;\n };\n\ntype SessionListenerCallback = (payload: SessionBroadcastPayload) => void;\n\n/**\n * Run Manager implementation\n */\nclass RunManagerImpl {\n /** Live agents (not cacheable) */\n private activeRuns: Map<string, ActiveRun> = new Map();\n\n /** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */\n private sessionListeners: Map<string, Set<SessionListenerCallback>> = new Map();\n\n /**\n * Generate unique run ID\n */\n generateRunId(): string {\n return `run-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n }\n\n /**\n * Register a new run\n */\n async register(\n runId: string,\n task: string,\n agent: IAgentRunner | undefined,\n sessionManager: SessionManager,\n ): Promise<ActiveRun> {\n const now = new Date().toISOString();\n\n const run: ActiveRun = {\n runId,\n task,\n status: 'pending',\n agent,\n sessionManager,\n startedAt: now,\n };\n\n // Store in memory (for live agent)\n this.activeRuns.set(runId, run);\n\n // Store serializable state in cache\n await this.saveToCache(run);\n\n return run;\n }\n\n /**\n * Get run by ID (from memory first, then cache for state)\n */\n get(runId: string): ActiveRun | undefined {\n return this.activeRuns.get(runId);\n }\n\n /**\n * Check if run exists (in memory or cache)\n */\n async exists(runId: string): Promise<boolean> {\n // Check memory first\n if (this.activeRuns.has(runId)) {\n return true;\n }\n // Fallback to cache\n const state = await this.getState(runId);\n return state !== null;\n }\n\n /**\n * Get run state from cache (for completed runs or cross-process access)\n */\n async getState(runId: string): Promise<RunState | null> {\n const cache = useCache();\n if (!cache) {return null;}\n\n return cache.get<RunState>(`${CACHE_PREFIX}${runId}`);\n }\n\n /**\n * Update run status\n */\n async updateStatus(runId: string, status: RunStatus, extra?: Partial<RunState>): Promise<void> {\n const run = this.activeRuns.get(runId);\n if (run) {\n run.status = status;\n if (extra) {\n Object.assign(run, extra);\n }\n await this.saveToCache(run);\n }\n }\n\n /**\n * Save run state to cache\n */\n private async saveToCache(run: ActiveRun): Promise<void> {\n const cache = useCache();\n if (!cache) {return;}\n\n const state: RunState = {\n runId: run.runId,\n task: run.task,\n status: run.status,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n\n await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);\n }\n\n /**\n * Broadcast turn deltas to all session-level listeners. Callers MUST await\n * persistence (sessionManager.addEvent) before calling this, so listeners\n * never observe a delta whose underlying turn state isn't on disk yet —\n * that ordering is what makes gap-recovery / reconnect resume correct.\n */\n broadcastSessionDeltas(sessionId: string, deltas: TurnDelta[]): void {\n if (deltas.length === 0) { return; }\n this.notifySessionListeners(sessionId, { kind: 'deltas', deltas });\n }\n\n /**\n * Broadcast a run's terminal outcome to session-level listeners. Called\n * directly from the run's own completion handler (after `agent.execute()`\n * resolves) rather than derived reactively from an `agent:end` event —\n * the completion handler already has definitive success/summary/duration,\n * and this guarantees the message fires exactly once, deterministically.\n */\n broadcastRunCompleted(sessionId: string, payload: Omit<Extract<SessionBroadcastPayload, { kind: 'run:completed' }>, 'kind'>): void {\n this.notifySessionListeners(sessionId, { kind: 'run:completed', ...payload });\n }\n\n private notifySessionListeners(sessionId: string, payload: SessionBroadcastPayload): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (!listeners) { return; }\n for (const listener of listeners) {\n try {\n listener(payload);\n } catch {\n // Ignore listener errors — one bad WS connection shouldn't affect others\n }\n }\n }\n\n /**\n * Add a session-level listener — receives updates from ALL runs in this session.\n */\n addSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n if (!this.sessionListeners.has(sessionId)) {\n this.sessionListeners.set(sessionId, new Set());\n }\n this.sessionListeners.get(sessionId)!.add(callback);\n }\n\n /**\n * Remove a session-level listener.\n */\n removeSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.sessionListeners.delete(sessionId);\n }\n }\n }\n\n /**\n * List all active runs\n */\n listActive(): Array<{ runId: string; task: string; status: RunStatus; startedAt: string }> {\n return Array.from(this.activeRuns.values()).map(r => ({\n runId: r.runId,\n task: r.task,\n status: r.status,\n startedAt: r.startedAt,\n }));\n }\n\n /**\n * Request graceful stop of a running agent (and its child agents via propagated AbortSignal).\n * Agent finishes its current tool call then exits at the next iteration boundary.\n */\n requestStop(runId: string): boolean {\n const run = this.activeRuns.get(runId);\n if (!run || run.status !== 'running' || !run.agent) {\n return false;\n }\n run.agent.requestStop();\n return true;\n }\n\n /**\n * Clean up completed runs from memory (cache handles its own TTL)\n */\n cleanup(): void {\n for (const [runId, run] of this.activeRuns) {\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n // Remove from memory but keep in cache\n this.activeRuns.delete(runId);\n }\n }\n }\n}\n\n/**\n * Singleton instance — stored on globalThis so all bundled modules share one instance.\n * When tsup compiles multiple entry points, each gets its own module scope,\n * so a plain `export const RunManager = new RunManagerImpl()` creates separate instances.\n * Using globalThis ensures run-handler.js and session-stream-handler.js share one RunManager.\n */\nconst GLOBAL_KEY = '__kb_agent_run_manager__';\nif (!(globalThis as Record<string, unknown>)[GLOBAL_KEY]) {\n (globalThis as Record<string, unknown>)[GLOBAL_KEY] = new RunManagerImpl();\n}\nexport const RunManager = (globalThis as Record<string, unknown>)[GLOBAL_KEY] as RunManagerImpl;\n","/**\n * GET /run/:runId handler\n *\n * Returns current status of a run\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport type { RunStatusResponse } from '@kb-labs/agent-contracts';\nimport { RunManager } from '../run-manager.js';\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<void>\n ): Promise<RunStatusResponse> {\n try {\n const { runId } = input.params as { runId: string };\n\n // First try to get active run from memory\n const run = RunManager.get(runId);\n\n if (!run) {\n // If not in memory, check cache for completed runs\n const state = await RunManager.getState(runId);\n\n if (!state) {\n // Return 404-like response\n return {\n runId,\n status: 'failed',\n task: '',\n startedAt: '',\n error: `Run ${runId} not found`,\n };\n }\n\n // Return cached state (no active orchestrator)\n return {\n runId: state.runId,\n status: state.status,\n task: state.task,\n startedAt: state.startedAt,\n completedAt: state.completedAt,\n durationMs: state.durationMs,\n summary: state.summary,\n error: state.error,\n };\n }\n\n return {\n runId: run.runId,\n status: run.status,\n task: run.task,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/rest/run-manager.ts","../../../src/rest/handlers/stop-handler.ts"],"names":[],"mappings":"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","file":"stop-handler.js","sourcesContent":["/**\n * Run Manager - tracks active agent runs for REST/WS API\n *\n * Uses platform cache for persistence and in-memory Map for active agents.\n * Cache stores serializable run state, Map stores live agent references.\n */\n\nimport type { IAgentRunner } from '@kb-labs/agent-sdk';\nimport type { SessionManager } from '@kb-labs/agent-core';\nimport type { Turn, TurnDelta } from '@kb-labs/agent-contracts';\nimport { useCache } from '@kb-labs/sdk';\n\nconst CACHE_PREFIX = 'agent:run:';\nconst CACHE_TTL = 3600000; // 1 hour\n\n/**\n * Run status\n */\nexport type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';\n\n/**\n * Serializable run state (stored in cache)\n */\nexport interface RunState {\n runId: string;\n task: string;\n status: RunStatus;\n startedAt: string;\n completedAt?: string;\n durationMs?: number;\n summary?: string;\n error?: string;\n}\n\n/**\n * Active run with live agent (in-memory only)\n */\nexport interface ActiveRun extends RunState {\n agent?: IAgentRunner;\n sessionManager: SessionManager;\n}\n\n/**\n * Payload delivered to session-level listeners — the sole live-update\n * channel for a session's WS connection(s). `deltas` carries incremental\n * turn changes (see TurnDelta); `run:completed` is a terminal signal\n * carrying the finished run's outcome and, when available, the final\n * state of the assistant turn it produced.\n */\nexport type SessionBroadcastPayload =\n | { kind: 'deltas'; deltas: TurnDelta[] }\n | {\n kind: 'run:completed';\n runId: string;\n success: boolean;\n summary: string;\n durationMs: number;\n seq: number;\n turn?: Turn;\n };\n\ntype SessionListenerCallback = (payload: SessionBroadcastPayload) => void;\n\n/**\n * Run Manager implementation\n */\nclass RunManagerImpl {\n /** Live agents (not cacheable) */\n private activeRuns: Map<string, ActiveRun> = new Map();\n\n /** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */\n private sessionListeners: Map<string, Set<SessionListenerCallback>> = new Map();\n\n /**\n * Generate unique run ID\n */\n generateRunId(): string {\n return `run-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n }\n\n /**\n * Register a new run\n */\n async register(\n runId: string,\n task: string,\n agent: IAgentRunner | undefined,\n sessionManager: SessionManager,\n ): Promise<ActiveRun> {\n const now = new Date().toISOString();\n\n const run: ActiveRun = {\n runId,\n task,\n status: 'pending',\n agent,\n sessionManager,\n startedAt: now,\n };\n\n // Store in memory (for live agent)\n this.activeRuns.set(runId, run);\n\n // Store serializable state in cache\n await this.saveToCache(run);\n\n return run;\n }\n\n /**\n * Get run by ID (from memory first, then cache for state)\n */\n get(runId: string): ActiveRun | undefined {\n return this.activeRuns.get(runId);\n }\n\n /**\n * Check if run exists (in memory or cache)\n */\n async exists(runId: string): Promise<boolean> {\n // Check memory first\n if (this.activeRuns.has(runId)) {\n return true;\n }\n // Fallback to cache\n const state = await this.getState(runId);\n return state !== null;\n }\n\n /**\n * Get run state from cache (for completed runs or cross-process access)\n */\n async getState(runId: string): Promise<RunState | null> {\n const cache = useCache();\n if (!cache) {return null;}\n\n return cache.get<RunState>(`${CACHE_PREFIX}${runId}`);\n }\n\n /**\n * Update run status\n */\n async updateStatus(runId: string, status: RunStatus, extra?: Partial<RunState>): Promise<void> {\n const run = this.activeRuns.get(runId);\n if (run) {\n run.status = status;\n if (extra) {\n Object.assign(run, extra);\n }\n await this.saveToCache(run);\n }\n }\n\n /**\n * Save run state to cache\n */\n private async saveToCache(run: ActiveRun): Promise<void> {\n const cache = useCache();\n if (!cache) {return;}\n\n const state: RunState = {\n runId: run.runId,\n task: run.task,\n status: run.status,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n\n await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);\n }\n\n /**\n * Broadcast turn deltas to all session-level listeners. Callers MUST await\n * persistence (sessionManager.addEvent) before calling this, so listeners\n * never observe a delta whose underlying turn state isn't on disk yet —\n * that ordering is what makes gap-recovery / reconnect resume correct.\n */\n broadcastSessionDeltas(sessionId: string, deltas: TurnDelta[]): void {\n if (deltas.length === 0) { return; }\n this.notifySessionListeners(sessionId, { kind: 'deltas', deltas });\n }\n\n /**\n * Broadcast a run's terminal outcome to session-level listeners. Called\n * directly from the run's own completion handler (after `agent.execute()`\n * resolves) rather than derived reactively from an `agent:end` event —\n * the completion handler already has definitive success/summary/duration,\n * and this guarantees the message fires exactly once, deterministically.\n */\n broadcastRunCompleted(sessionId: string, payload: Omit<Extract<SessionBroadcastPayload, { kind: 'run:completed' }>, 'kind'>): void {\n this.notifySessionListeners(sessionId, { kind: 'run:completed', ...payload });\n }\n\n private notifySessionListeners(sessionId: string, payload: SessionBroadcastPayload): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (!listeners) { return; }\n for (const listener of listeners) {\n try {\n listener(payload);\n } catch {\n // Ignore listener errors — one bad WS connection shouldn't affect others\n }\n }\n }\n\n /**\n * Add a session-level listener — receives updates from ALL runs in this session.\n */\n addSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n if (!this.sessionListeners.has(sessionId)) {\n this.sessionListeners.set(sessionId, new Set());\n }\n this.sessionListeners.get(sessionId)!.add(callback);\n }\n\n /**\n * Remove a session-level listener.\n */\n removeSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.sessionListeners.delete(sessionId);\n }\n }\n }\n\n /**\n * List all active runs\n */\n listActive(): Array<{ runId: string; task: string; status: RunStatus; startedAt: string }> {\n return Array.from(this.activeRuns.values()).map(r => ({\n runId: r.runId,\n task: r.task,\n status: r.status,\n startedAt: r.startedAt,\n }));\n }\n\n /**\n * Request graceful stop of a running agent (and its child agents via propagated AbortSignal).\n * Agent finishes its current tool call then exits at the next iteration boundary.\n */\n requestStop(runId: string): boolean {\n const run = this.activeRuns.get(runId);\n if (!run || run.status !== 'running' || !run.agent) {\n return false;\n }\n run.agent.requestStop();\n return true;\n }\n\n /**\n * Clean up completed runs from memory (cache handles its own TTL)\n */\n cleanup(): void {\n for (const [runId, run] of this.activeRuns) {\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n // Remove from memory but keep in cache\n this.activeRuns.delete(runId);\n }\n }\n }\n}\n\n/**\n * Singleton instance — stored on globalThis so all bundled modules share one instance.\n * When tsup compiles multiple entry points, each gets its own module scope,\n * so a plain `export const RunManager = new RunManagerImpl()` creates separate instances.\n * Using globalThis ensures run-handler.js and session-stream-handler.js share one RunManager.\n */\nconst GLOBAL_KEY = '__kb_agent_run_manager__';\nif (!(globalThis as Record<string, unknown>)[GLOBAL_KEY]) {\n (globalThis as Record<string, unknown>)[GLOBAL_KEY] = new RunManagerImpl();\n}\nexport const RunManager = (globalThis as Record<string, unknown>)[GLOBAL_KEY] as RunManagerImpl;\n","/**\n * POST /run/:runId/stop handler\n *\n * Stops a running agent execution\n */\n\nimport { defineHandler, rethrowForRest, useAnalytics, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport type { StopRequest, StopResponse } from '@kb-labs/agent-contracts';\nimport { AGENT_ANALYTICS_EVENTS } from '@kb-labs/agent-contracts';\nimport { RunManager } from '../run-manager.js';\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<StopRequest>\n ): Promise<StopResponse> {\n try {\n const { runId } = input.params as { runId: string };\n const body = input.body as StopRequest | undefined;\n const reason = body?.reason;\n\n ctx.platform.logger.info(`[stop-handler] Stop requested for run ${runId}${reason ? `: ${reason}` : ''}`);\n\n const run = RunManager.get(runId);\n\n if (!run) {\n return {\n stopped: false,\n runId,\n finalStatus: 'not_found',\n };\n }\n\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n return {\n stopped: false,\n runId,\n finalStatus: 'already_completed',\n };\n }\n\n // Signal the agent to stop after its current tool call finishes\n RunManager.requestStop(runId);\n\n // Update status optimistically — agent:end event will also update it async\n await RunManager.updateStatus(runId, 'stopped', {\n completedAt: new Date().toISOString(),\n durationMs: Date.now() - new Date(run.startedAt).getTime(),\n summary: reason ? `Stopped by user: ${reason}` : 'Stopped by user',\n });\n\n // Track stop\n const analytics = useAnalytics();\n await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_STOPPED, {\n runId,\n durationMs: Date.now() - new Date(run.startedAt).getTime(),\n reason: reason?.slice(0, 200),\n });\n\n ctx.platform.logger.info(`[stop-handler] Run ${runId} stopped`);\n\n return {\n stopped: true,\n runId,\n finalStatus: 'stopped',\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/run-manager.ts","../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/stop-handler.ts"],"names":[],"mappings":"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","file":"stop-handler.js","sourcesContent":["/**\n * Run Manager - tracks active agent runs for REST/WS API\n *\n * Uses platform cache for persistence and in-memory Map for active agents.\n * Cache stores serializable run state, Map stores live agent references.\n */\n\nimport type { IAgentRunner } from '@kb-labs/agent-sdk';\nimport type { SessionManager } from '@kb-labs/agent-core';\nimport type { Turn, TurnDelta } from '@kb-labs/agent-contracts';\nimport { useCache } from '@kb-labs/sdk';\n\nconst CACHE_PREFIX = 'agent:run:';\nconst CACHE_TTL = 3600000; // 1 hour\n\n/**\n * Run status\n */\nexport type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';\n\n/**\n * Serializable run state (stored in cache)\n */\nexport interface RunState {\n runId: string;\n task: string;\n status: RunStatus;\n startedAt: string;\n completedAt?: string;\n durationMs?: number;\n summary?: string;\n error?: string;\n}\n\n/**\n * Active run with live agent (in-memory only)\n */\nexport interface ActiveRun extends RunState {\n agent?: IAgentRunner;\n sessionManager: SessionManager;\n}\n\n/**\n * Payload delivered to session-level listeners — the sole live-update\n * channel for a session's WS connection(s). `deltas` carries incremental\n * turn changes (see TurnDelta); `run:completed` is a terminal signal\n * carrying the finished run's outcome and, when available, the final\n * state of the assistant turn it produced.\n */\nexport type SessionBroadcastPayload =\n | { kind: 'deltas'; deltas: TurnDelta[] }\n | {\n kind: 'run:completed';\n runId: string;\n success: boolean;\n summary: string;\n durationMs: number;\n seq: number;\n turn?: Turn;\n };\n\ntype SessionListenerCallback = (payload: SessionBroadcastPayload) => void;\n\n/**\n * Run Manager implementation\n */\nclass RunManagerImpl {\n /** Live agents (not cacheable) */\n private activeRuns: Map<string, ActiveRun> = new Map();\n\n /** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */\n private sessionListeners: Map<string, Set<SessionListenerCallback>> = new Map();\n\n /**\n * Generate unique run ID\n */\n generateRunId(): string {\n return `run-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n }\n\n /**\n * Register a new run\n */\n async register(\n runId: string,\n task: string,\n agent: IAgentRunner | undefined,\n sessionManager: SessionManager,\n ): Promise<ActiveRun> {\n const now = new Date().toISOString();\n\n const run: ActiveRun = {\n runId,\n task,\n status: 'pending',\n agent,\n sessionManager,\n startedAt: now,\n };\n\n // Store in memory (for live agent)\n this.activeRuns.set(runId, run);\n\n // Store serializable state in cache\n await this.saveToCache(run);\n\n return run;\n }\n\n /**\n * Get run by ID (from memory first, then cache for state)\n */\n get(runId: string): ActiveRun | undefined {\n return this.activeRuns.get(runId);\n }\n\n /**\n * Check if run exists (in memory or cache)\n */\n async exists(runId: string): Promise<boolean> {\n // Check memory first\n if (this.activeRuns.has(runId)) {\n return true;\n }\n // Fallback to cache\n const state = await this.getState(runId);\n return state !== null;\n }\n\n /**\n * Get run state from cache (for completed runs or cross-process access)\n */\n async getState(runId: string): Promise<RunState | null> {\n const cache = useCache();\n if (!cache) {return null;}\n\n return cache.get<RunState>(`${CACHE_PREFIX}${runId}`);\n }\n\n /**\n * Update run status\n */\n async updateStatus(runId: string, status: RunStatus, extra?: Partial<RunState>): Promise<void> {\n const run = this.activeRuns.get(runId);\n if (run) {\n run.status = status;\n if (extra) {\n Object.assign(run, extra);\n }\n await this.saveToCache(run);\n }\n }\n\n /**\n * Save run state to cache\n */\n private async saveToCache(run: ActiveRun): Promise<void> {\n const cache = useCache();\n if (!cache) {return;}\n\n const state: RunState = {\n runId: run.runId,\n task: run.task,\n status: run.status,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n\n await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);\n }\n\n /**\n * Broadcast turn deltas to all session-level listeners. Callers MUST await\n * persistence (sessionManager.addEvent) before calling this, so listeners\n * never observe a delta whose underlying turn state isn't on disk yet —\n * that ordering is what makes gap-recovery / reconnect resume correct.\n */\n broadcastSessionDeltas(sessionId: string, deltas: TurnDelta[]): void {\n if (deltas.length === 0) { return; }\n this.notifySessionListeners(sessionId, { kind: 'deltas', deltas });\n }\n\n /**\n * Broadcast a run's terminal outcome to session-level listeners. Called\n * directly from the run's own completion handler (after `agent.execute()`\n * resolves) rather than derived reactively from an `agent:end` event —\n * the completion handler already has definitive success/summary/duration,\n * and this guarantees the message fires exactly once, deterministically.\n */\n broadcastRunCompleted(sessionId: string, payload: Omit<Extract<SessionBroadcastPayload, { kind: 'run:completed' }>, 'kind'>): void {\n this.notifySessionListeners(sessionId, { kind: 'run:completed', ...payload });\n }\n\n private notifySessionListeners(sessionId: string, payload: SessionBroadcastPayload): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (!listeners) { return; }\n for (const listener of listeners) {\n try {\n listener(payload);\n } catch {\n // Ignore listener errors — one bad WS connection shouldn't affect others\n }\n }\n }\n\n /**\n * Add a session-level listener — receives updates from ALL runs in this session.\n */\n addSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n if (!this.sessionListeners.has(sessionId)) {\n this.sessionListeners.set(sessionId, new Set());\n }\n this.sessionListeners.get(sessionId)!.add(callback);\n }\n\n /**\n * Remove a session-level listener.\n */\n removeSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.sessionListeners.delete(sessionId);\n }\n }\n }\n\n /**\n * List all active runs\n */\n listActive(): Array<{ runId: string; task: string; status: RunStatus; startedAt: string }> {\n return Array.from(this.activeRuns.values()).map(r => ({\n runId: r.runId,\n task: r.task,\n status: r.status,\n startedAt: r.startedAt,\n }));\n }\n\n /**\n * Request graceful stop of a running agent (and its child agents via propagated AbortSignal).\n * Agent finishes its current tool call then exits at the next iteration boundary.\n */\n requestStop(runId: string): boolean {\n const run = this.activeRuns.get(runId);\n if (!run || run.status !== 'running' || !run.agent) {\n return false;\n }\n run.agent.requestStop();\n return true;\n }\n\n /**\n * Clean up completed runs from memory (cache handles its own TTL)\n */\n cleanup(): void {\n for (const [runId, run] of this.activeRuns) {\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n // Remove from memory but keep in cache\n this.activeRuns.delete(runId);\n }\n }\n }\n}\n\n/**\n * Singleton instance — stored on globalThis so all bundled modules share one instance.\n * When tsup compiles multiple entry points, each gets its own module scope,\n * so a plain `export const RunManager = new RunManagerImpl()` creates separate instances.\n * Using globalThis ensures run-handler.js and session-stream-handler.js share one RunManager.\n */\nconst GLOBAL_KEY = '__kb_agent_run_manager__';\nif (!(globalThis as Record<string, unknown>)[GLOBAL_KEY]) {\n (globalThis as Record<string, unknown>)[GLOBAL_KEY] = new RunManagerImpl();\n}\nexport const RunManager = (globalThis as Record<string, unknown>)[GLOBAL_KEY] as RunManagerImpl;\n","/**\n * POST /run/:runId/stop handler\n *\n * Stops a running agent execution\n */\n\nimport { defineHandler, rethrowForRest, useAnalytics, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport type { StopRequest, StopResponse } from '@kb-labs/agent-contracts';\nimport { AGENT_ANALYTICS_EVENTS } from '@kb-labs/agent-contracts';\nimport { RunManager } from '../run-manager.js';\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<StopRequest>\n ): Promise<StopResponse> {\n try {\n const { runId } = input.params as { runId: string };\n const body = input.body as StopRequest | undefined;\n const reason = body?.reason;\n\n ctx.platform.logger.info(`[stop-handler] Stop requested for run ${runId}${reason ? `: ${reason}` : ''}`);\n\n const run = RunManager.get(runId);\n\n if (!run) {\n return {\n stopped: false,\n runId,\n finalStatus: 'not_found',\n };\n }\n\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n return {\n stopped: false,\n runId,\n finalStatus: 'already_completed',\n };\n }\n\n // Signal the agent to stop after its current tool call finishes\n RunManager.requestStop(runId);\n\n // Update status optimistically — agent:end event will also update it async\n await RunManager.updateStatus(runId, 'stopped', {\n completedAt: new Date().toISOString(),\n durationMs: Date.now() - new Date(run.startedAt).getTime(),\n summary: reason ? `Stopped by user: ${reason}` : 'Stopped by user',\n });\n\n // Track stop\n const analytics = useAnalytics();\n await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_STOPPED, {\n runId,\n durationMs: Date.now() - new Date(run.startedAt).getTime(),\n reason: reason?.slice(0, 200),\n });\n\n ctx.platform.logger.info(`[stop-handler] Run ${runId} stopped`);\n\n return {\n stopped: true,\n runId,\n finalStatus: 'stopped',\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/rest/run-manager.ts","../../src/ws/session-stream-handler.ts"],"names":[],"mappings":";;;;AAYA,IAAM,YAAA,GAAe,YAAA;AACrB,IAAM,SAAA,GAAY,IAAA;AAqDlB,IAAM,iBAAN,MAAqB;AAAA;AAAA,EAEX,UAAA,uBAAyC,GAAA,EAAI;AAAA;AAAA,EAG7C,gBAAA,uBAAkE,GAAA,EAAI;AAAA;AAAA;AAAA;AAAA,EAK9E,aAAA,GAAwB;AACtB,IAAA,OAAO,CAAA,IAAA,EAAO,IAAA,CAAK,GAAA,EAAK,IAAI,IAAA,CAAK,MAAA,EAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAA,CACJ,KAAA,EACA,IAAA,EACA,OACA,cAAA,EACoB;AACpB,IAAA,MAAM,GAAA,GAAA,iBAAM,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAEnC,IAAA,MAAM,GAAA,GAAiB;AAAA,MACrB,KAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,KAAA;AAAA,MACA,cAAA;AAAA,MACA,SAAA,EAAW;AAAA,KACb;AAGA,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AAG9B,IAAA,MAAM,IAAA,CAAK,YAAY,GAAG,CAAA;AAE1B,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAA,EAAsC;AACxC,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,KAAA,EAAiC;AAE5C,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA,EAAG;AAC9B,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA;AACvC,IAAA,OAAO,KAAA,KAAU,IAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,KAAA,EAAyC;AACtD,IAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,IAAA,IAAI,CAAC,KAAA,EAAO;AAAC,MAAA,OAAO,IAAA;AAAA,IAAK;AAEzB,IAAA,OAAO,MAAM,GAAA,CAAc,CAAA,EAAG,YAAY,CAAA,EAAG,KAAK,CAAA,CAAE,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAA,CAAa,KAAA,EAAe,MAAA,EAAmB,KAAA,EAA0C;AAC7F,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AACrC,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,GAAA,CAAI,MAAA,GAAS,MAAA;AACb,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,MAAA,CAAO,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,MAC1B;AACA,MAAA,MAAM,IAAA,CAAK,YAAY,GAAG,CAAA;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YAAY,GAAA,EAA+B;AACvD,IAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,IAAA,IAAI,CAAC,KAAA,EAAO;AAAC,MAAA;AAAA,IAAO;AAEpB,IAAA,MAAM,KAAA,GAAkB;AAAA,MACtB,OAAO,GAAA,CAAI,KAAA;AAAA,MACX,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,QAAQ,GAAA,CAAI,MAAA;AAAA,MACZ,WAAW,GAAA,CAAI,SAAA;AAAA,MACf,aAAa,GAAA,CAAI,WAAA;AAAA,MACjB,YAAY,GAAA,CAAI,UAAA;AAAA,MAChB,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,OAAO,GAAA,CAAI;AAAA,KACb;AAEA,IAAA,MAAM,KAAA,CAAM,IAAI,CAAA,EAAG,YAAY,GAAG,GAAA,CAAI,KAAK,CAAA,CAAA,EAAI,KAAA,EAAO,SAAS,CAAA;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,sBAAA,CAAuB,WAAmB,MAAA,EAA2B;AACnE,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AAAE,MAAA;AAAA,IAAQ;AACnC,IAAA,IAAA,CAAK,uBAAuB,SAAA,EAAW,EAAE,IAAA,EAAM,QAAA,EAAU,QAAQ,CAAA;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,qBAAA,CAAsB,WAAmB,OAAA,EAA0F;AACjI,IAAA,IAAA,CAAK,uBAAuB,SAAA,EAAW,EAAE,MAAM,eAAA,EAAiB,GAAG,SAAS,CAAA;AAAA,EAC9E;AAAA,EAEQ,sBAAA,CAAuB,WAAmB,OAAA,EAAwC;AACxF,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,SAAS,CAAA;AACrD,IAAA,IAAI,CAAC,SAAA,EAAW;AAAE,MAAA;AAAA,IAAQ;AAC1B,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,OAAO,CAAA;AAAA,MAClB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAA,CAAmB,WAAmB,QAAA,EAAyC;AAC7E,IAAA,IAAI,CAAC,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,SAAS,CAAA,EAAG;AACzC,MAAA,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,SAAA,kBAAW,IAAI,KAAK,CAAA;AAAA,IAChD;AACA,IAAA,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,SAAS,CAAA,CAAG,IAAI,QAAQ,CAAA;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAA,CAAsB,WAAmB,QAAA,EAAyC;AAChF,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,SAAS,CAAA;AACrD,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AACzB,MAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACxB,QAAA,IAAA,CAAK,gBAAA,CAAiB,OAAO,SAAS,CAAA;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAA2F;AACzF,IAAA,OAAO,KAAA,CAAM,KAAK,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,CAAE,IAAI,CAAA,CAAA,MAAM;AAAA,MACpD,OAAO,CAAA,CAAE,KAAA;AAAA,MACT,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,QAAQ,CAAA,CAAE,MAAA;AAAA,MACV,WAAW,CAAA,CAAE;AAAA,KACf,CAAE,CAAA;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,KAAA,EAAwB;AAClC,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AACrC,IAAA,IAAI,CAAC,GAAA,IAAO,GAAA,CAAI,WAAW,SAAA,IAAa,CAAC,IAAI,KAAA,EAAO;AAClD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,GAAA,CAAI,MAAM,WAAA,EAAY;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAAgB;AACd,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,GAAG,CAAA,IAAK,KAAK,UAAA,EAAY;AAC1C,MAAA,IAAI,GAAA,CAAI,WAAW,WAAA,IAAe,GAAA,CAAI,WAAW,QAAA,IAAY,GAAA,CAAI,WAAW,SAAA,EAAW;AAErF,QAAA,IAAA,CAAK,UAAA,CAAW,OAAO,KAAK,CAAA;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AACF,CAAA;AAQA,IAAM,UAAA,GAAa,0BAAA;AACnB,IAAI,CAAE,UAAA,CAAuC,UAAU,CAAA,EAAG;AACxD,EAAC,UAAA,CAAuC,UAAU,CAAA,GAAI,IAAI,cAAA,EAAe;AAC3E;AACO,IAAM,UAAA,GAAc,WAAuC,UAAU,CAAA;AChP5E,IAAM,eAAA,uBAAsB,OAAA,EAAwC;AAEpE,IAAO,iCAAQ,eAAA,CAAuD;AAAA,EACpE,IAAA,EAAM,qBAAA;AAAA,EACN,WAAA,EAAa,4CAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,SAAA,CAAU,GAAA,EAAsB,MAAA,EAAoC;AACxE,MAAA,MAAM,cAAc,GAAA,CAAI,WAAA;AACxB,MAAA,MAAM,SAAA,GAAY,YAAY,MAAA,EAAQ,SAAA;AAMtC,MAAA,MAAM,QAAA,GAAW,YAAY,KAAA,EAAO,QAAA,GAAW,OAAO,WAAA,CAAY,KAAA,CAAM,QAAQ,CAAA,GAAI,MAAA;AAEpF,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,MAAM,OAAO,IAAA,CAAK;AAAA,UAChB,IAAA,EAAM,OAAA;AAAA,UACN,OAAA,EAAS,EAAE,IAAA,EAAM,oBAAA,EAAsB,SAAS,wBAAA,EAAyB;AAAA,UACzE,SAAA,EAAW,KAAK,GAAA;AAAI,SACE,CAAA;AACxB,QAAA,MAAA,CAAO,KAAA,CAAM,KAAM,oBAAoB,CAAA;AACvC,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA;AAAA,QAClB,QAAA,IAAY,OACR,CAAA,yCAAA,EAA4C,SAAS,sBAAsB,QAAQ,CAAA,CAAA,CAAA,GACnF,4CAA4C,SAAS,CAAA;AAAA,OAC3D;AAEA,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAGjD,MAAA,IAAI;AACF,QAAA,MAAM,OAAO,IAAA,CAAK;AAAA,UAChB,IAAA,EAAM,kBAAA;AAAA,UACN,OAAA,EAAS,EAAE,KAAA,EAAO,SAAA,EAAW,8BAAa,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY,EAAE;AAAA,UACnE,SAAA,EAAW,KAAK,GAAA;AAAI,SACY,CAAA;AAAA,MACpC,SAAS,GAAA,EAAK;AACZ,QAAA,GAAA,CAAI,SAAS,MAAA,CAAO,KAAA,CAAM,iDAAiD,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AACxF,QAAA,MAAM,GAAA;AAAA,MACR;AAIA,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,KAAA,EAAO,GAAA,KAAQ,MAAM,cAAA,CAAe,cAAc,SAAS,CAAA;AACnE,QAAA,MAAM,iBAAiB,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,WAAW,CAAA;AACnE,QAAA,MAAM,cAAc,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,WAAW,CAAA;AAChE,QAAA,MAAM,OAAO,IAAA,CAAK;AAAA,UAChB,IAAA,EAAM,uBAAA;AAAA,UACN,OAAA,EAAS;AAAA,YACP,SAAA;AAAA,YACA,cAAA;AAAA,YACA,WAAA;AAAA,YACA,YAAY,KAAA,CAAM,MAAA;AAAA,YAClB,GAAA;AAAA,YACA,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,WACpC;AAAA,UACA,SAAA,EAAW,KAAK,GAAA;AAAI,SACiB,CAAA;AACvC,QAAA,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA;AAAA,UAClB,+BAA+B,cAAA,CAAe,MAAM,gBAAgB,WAAA,CAAY,MAAM,wBAAwB,GAAG,CAAA;AAAA,SACnH;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,GAAA,CAAI,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,CAAA,sCAAA,EAAyC,GAAG,CAAA,CAAE,CAAA;AAAA,MAC1E;AAKA,MAAA,MAAM,QAAA,GAAW,CAAC,OAAA,KAAqC;AACrD,QAAA,IAAI,OAAA,CAAQ,SAAS,QAAA,EAAU;AAC7B,UAAA,KAAA,MAAW,KAAA,IAAS,QAAQ,MAAA,EAAQ;AAClC,YAAA,KAAK,OAAO,IAAA,CAAK;AAAA,cACf,IAAA,EAAM,YAAA;AAAA,cACN,OAAA,EAAS,EAAE,SAAA,EAAW,KAAA,EAAM;AAAA,cAC5B,SAAA,EAAW,KAAK,GAAA;AAAI,aACM,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AAC3C,cAAA,GAAA,CAAI,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,CAAA,wCAAA,EAA2C,GAAG,CAAA,CAAE,CAAA;AAAA,YAC5E,CAAC,CAAA;AAAA,UACH;AACA,UAAA;AAAA,QACF;AAEA,QAAA,KAAK,OAAO,IAAA,CAAK;AAAA,UACf,IAAA,EAAM,eAAA;AAAA,UACN,OAAA,EAAS;AAAA,YACP,OAAO,OAAA,CAAQ,KAAA;AAAA,YACf,SAAS,OAAA,CAAQ,OAAA;AAAA,YACjB,SAAS,OAAA,CAAQ,OAAA;AAAA,YACjB,YAAY,OAAA,CAAQ,UAAA;AAAA,YACpB,KAAK,OAAA,CAAQ,GAAA;AAAA,YACb,MAAM,OAAA,CAAQ;AAAA,WAChB;AAAA,UACA,SAAA,EAAW,KAAK,GAAA;AAAI,SACS,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AAC9C,UAAA,GAAA,CAAI,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,CAAA,2CAAA,EAA8C,GAAG,CAAA,CAAE,CAAA;AAAA,QAC/E,CAAC,CAAA;AAAA,MACH,CAAA;AAGA,MAAA,eAAA,CAAgB,GAAA,CAAI,GAAA,EAAe,EAAE,SAAA,EAAW,UAAU,CAAA;AAE1D,MAAA,IAAI;AACF,QAAA,UAAA,CAAW,kBAAA,CAAmB,WAAW,QAAQ,CAAA;AAAA,MACnD,SAAS,GAAA,EAAK;AACZ,QAAA,GAAA,CAAI,SAAS,MAAA,CAAO,KAAA,CAAM,qDAAqD,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC5F,QAAA,MAAM,GAAA;AAAA,MACR;AACA,MAAA,GAAA,CAAI,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,CAAA,qDAAA,EAAwD,SAAS,CAAA,CAAE,CAAA;AAAA,IAC9F,CAAA;AAAA,IAEA,MAAM,SAAA,CAAU,GAAA,EAAsB,OAAA,EAAwB,MAAA,EAAoC;AAEhG,MAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAQ;AAC3B,QAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,GAAA,CAAI,GAAa,GAAG,SAAA,IAAa,EAAA;AACnE,QAAA,MAAM,OAAO,IAAA,CAAK;AAAA,UAChB,IAAA,EAAM,kBAAA;AAAA,UACN,OAAA,EAAS,EAAE,KAAA,EAAO,SAAA,IAAa,EAAA,EAAI,8BAAa,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY,EAAE;AAAA,UACzE,SAAA,EAAW,KAAK,GAAA;AAAI,SACrB,CAAA;AAAA,MACH;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,aAAa,GAAA,EAAsB;AACvC,MAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,GAAA,CAAI,GAAa,CAAA;AAC/C,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,UAAA,CAAW,qBAAA,CAAsB,KAAA,CAAM,SAAA,EAAW,KAAA,CAAM,QAAQ,CAAA;AAChE,QAAA,eAAA,CAAgB,OAAO,GAAa,CAAA;AAAA,MACtC;AAEA,MAAA,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,CAAA,8CAAA,EAAiD,KAAA,EAAO,SAAS,CAAA,CAAE,CAAA;AAAA,IAC9F,CAAA;AAAA,IAEA,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAc,MAAA,EAAoC;AACpF,MAAA,GAAA,CAAI,SAAS,MAAA,CAAO,KAAA,CAAM,CAAA,8BAAA,EAAiC,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAC1E,MAAA,MAAM,OAAO,IAAA,CAAK;AAAA,QAChB,IAAA,EAAM,OAAA;AAAA,QACN,SAAS,EAAE,IAAA,EAAM,gBAAA,EAAkB,OAAA,EAAS,MAAM,OAAA,EAAQ;AAAA,QAC1D,SAAA,EAAW,KAAK,GAAA;AAAI,OACE,CAAA;AAAA,IAC1B;AAAA;AAEJ,CAAC","file":"session-stream-handler.js","sourcesContent":["/**\n * Run Manager - tracks active agent runs for REST/WS API\n *\n * Uses platform cache for persistence and in-memory Map for active agents.\n * Cache stores serializable run state, Map stores live agent references.\n */\n\nimport type { IAgentRunner } from '@kb-labs/agent-sdk';\nimport type { SessionManager } from '@kb-labs/agent-core';\nimport type { Turn, TurnDelta } from '@kb-labs/agent-contracts';\nimport { useCache } from '@kb-labs/sdk';\n\nconst CACHE_PREFIX = 'agent:run:';\nconst CACHE_TTL = 3600000; // 1 hour\n\n/**\n * Run status\n */\nexport type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';\n\n/**\n * Serializable run state (stored in cache)\n */\nexport interface RunState {\n runId: string;\n task: string;\n status: RunStatus;\n startedAt: string;\n completedAt?: string;\n durationMs?: number;\n summary?: string;\n error?: string;\n}\n\n/**\n * Active run with live agent (in-memory only)\n */\nexport interface ActiveRun extends RunState {\n agent?: IAgentRunner;\n sessionManager: SessionManager;\n}\n\n/**\n * Payload delivered to session-level listeners — the sole live-update\n * channel for a session's WS connection(s). `deltas` carries incremental\n * turn changes (see TurnDelta); `run:completed` is a terminal signal\n * carrying the finished run's outcome and, when available, the final\n * state of the assistant turn it produced.\n */\nexport type SessionBroadcastPayload =\n | { kind: 'deltas'; deltas: TurnDelta[] }\n | {\n kind: 'run:completed';\n runId: string;\n success: boolean;\n summary: string;\n durationMs: number;\n seq: number;\n turn?: Turn;\n };\n\ntype SessionListenerCallback = (payload: SessionBroadcastPayload) => void;\n\n/**\n * Run Manager implementation\n */\nclass RunManagerImpl {\n /** Live agents (not cacheable) */\n private activeRuns: Map<string, ActiveRun> = new Map();\n\n /** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */\n private sessionListeners: Map<string, Set<SessionListenerCallback>> = new Map();\n\n /**\n * Generate unique run ID\n */\n generateRunId(): string {\n return `run-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n }\n\n /**\n * Register a new run\n */\n async register(\n runId: string,\n task: string,\n agent: IAgentRunner | undefined,\n sessionManager: SessionManager,\n ): Promise<ActiveRun> {\n const now = new Date().toISOString();\n\n const run: ActiveRun = {\n runId,\n task,\n status: 'pending',\n agent,\n sessionManager,\n startedAt: now,\n };\n\n // Store in memory (for live agent)\n this.activeRuns.set(runId, run);\n\n // Store serializable state in cache\n await this.saveToCache(run);\n\n return run;\n }\n\n /**\n * Get run by ID (from memory first, then cache for state)\n */\n get(runId: string): ActiveRun | undefined {\n return this.activeRuns.get(runId);\n }\n\n /**\n * Check if run exists (in memory or cache)\n */\n async exists(runId: string): Promise<boolean> {\n // Check memory first\n if (this.activeRuns.has(runId)) {\n return true;\n }\n // Fallback to cache\n const state = await this.getState(runId);\n return state !== null;\n }\n\n /**\n * Get run state from cache (for completed runs or cross-process access)\n */\n async getState(runId: string): Promise<RunState | null> {\n const cache = useCache();\n if (!cache) {return null;}\n\n return cache.get<RunState>(`${CACHE_PREFIX}${runId}`);\n }\n\n /**\n * Update run status\n */\n async updateStatus(runId: string, status: RunStatus, extra?: Partial<RunState>): Promise<void> {\n const run = this.activeRuns.get(runId);\n if (run) {\n run.status = status;\n if (extra) {\n Object.assign(run, extra);\n }\n await this.saveToCache(run);\n }\n }\n\n /**\n * Save run state to cache\n */\n private async saveToCache(run: ActiveRun): Promise<void> {\n const cache = useCache();\n if (!cache) {return;}\n\n const state: RunState = {\n runId: run.runId,\n task: run.task,\n status: run.status,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n\n await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);\n }\n\n /**\n * Broadcast turn deltas to all session-level listeners. Callers MUST await\n * persistence (sessionManager.addEvent) before calling this, so listeners\n * never observe a delta whose underlying turn state isn't on disk yet —\n * that ordering is what makes gap-recovery / reconnect resume correct.\n */\n broadcastSessionDeltas(sessionId: string, deltas: TurnDelta[]): void {\n if (deltas.length === 0) { return; }\n this.notifySessionListeners(sessionId, { kind: 'deltas', deltas });\n }\n\n /**\n * Broadcast a run's terminal outcome to session-level listeners. Called\n * directly from the run's own completion handler (after `agent.execute()`\n * resolves) rather than derived reactively from an `agent:end` event —\n * the completion handler already has definitive success/summary/duration,\n * and this guarantees the message fires exactly once, deterministically.\n */\n broadcastRunCompleted(sessionId: string, payload: Omit<Extract<SessionBroadcastPayload, { kind: 'run:completed' }>, 'kind'>): void {\n this.notifySessionListeners(sessionId, { kind: 'run:completed', ...payload });\n }\n\n private notifySessionListeners(sessionId: string, payload: SessionBroadcastPayload): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (!listeners) { return; }\n for (const listener of listeners) {\n try {\n listener(payload);\n } catch {\n // Ignore listener errors — one bad WS connection shouldn't affect others\n }\n }\n }\n\n /**\n * Add a session-level listener — receives updates from ALL runs in this session.\n */\n addSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n if (!this.sessionListeners.has(sessionId)) {\n this.sessionListeners.set(sessionId, new Set());\n }\n this.sessionListeners.get(sessionId)!.add(callback);\n }\n\n /**\n * Remove a session-level listener.\n */\n removeSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.sessionListeners.delete(sessionId);\n }\n }\n }\n\n /**\n * List all active runs\n */\n listActive(): Array<{ runId: string; task: string; status: RunStatus; startedAt: string }> {\n return Array.from(this.activeRuns.values()).map(r => ({\n runId: r.runId,\n task: r.task,\n status: r.status,\n startedAt: r.startedAt,\n }));\n }\n\n /**\n * Request graceful stop of a running agent (and its child agents via propagated AbortSignal).\n * Agent finishes its current tool call then exits at the next iteration boundary.\n */\n requestStop(runId: string): boolean {\n const run = this.activeRuns.get(runId);\n if (!run || run.status !== 'running' || !run.agent) {\n return false;\n }\n run.agent.requestStop();\n return true;\n }\n\n /**\n * Clean up completed runs from memory (cache handles its own TTL)\n */\n cleanup(): void {\n for (const [runId, run] of this.activeRuns) {\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n // Remove from memory but keep in cache\n this.activeRuns.delete(runId);\n }\n }\n }\n}\n\n/**\n * Singleton instance — stored on globalThis so all bundled modules share one instance.\n * When tsup compiles multiple entry points, each gets its own module scope,\n * so a plain `export const RunManager = new RunManagerImpl()` creates separate instances.\n * Using globalThis ensures run-handler.js and session-stream-handler.js share one RunManager.\n */\nconst GLOBAL_KEY = '__kb_agent_run_manager__';\nif (!(globalThis as Record<string, unknown>)[GLOBAL_KEY]) {\n (globalThis as Record<string, unknown>)[GLOBAL_KEY] = new RunManagerImpl();\n}\nexport const RunManager = (globalThis as Record<string, unknown>)[GLOBAL_KEY] as RunManagerImpl;\n","/**\n * WebSocket handler for session-level event streaming\n *\n * Path: /session/:sessionId\n * Single persistent connection per session — streams turn deltas for ALL runs in the session.\n * Unlike /events/:runId which closes when a run ends, this stays open for the entire session.\n *\n * Delta-based, not read-derived: the session listener registered here receives\n * the exact TurnDelta[] that SessionManager.processEventAndUpdateTurn computed\n * at persist time (via RunManager.broadcastSessionDeltas), not re-derived by\n * re-reading turns.json off disk on every event. That re-read (the previous\n * resolveTurnForEvent) was the actual root cause of the WS stream lagging one\n * event behind persisted state — see run-handler.ts's onEvent for the other\n * half of that fix (persist now happens before broadcast, not after).\n */\n\nimport {\n defineWebSocket,\n type PluginContextV3,\n type TypedSender,\n} from '@kb-labs/sdk';\nimport type {\n ServerMessage,\n ClientMessage,\n ConnectionReadyMessage,\n RunCompletedMessage,\n ErrorMessage,\n TurnDeltaMessage,\n ConversationSnapshotMessage,\n} from '@kb-labs/agent-contracts';\nimport { RunManager, type SessionBroadcastPayload } from '../rest/run-manager.js';\nimport { SessionManager } from '@kb-labs/agent-core';\n\ninterface SessionConnectionState {\n sessionId: string;\n callback: (payload: SessionBroadcastPayload) => void;\n}\n\n/** Per-connection state keyed by the opaque ctx object — avoids mutating ctx */\nconst connectionState = new WeakMap<object, SessionConnectionState>();\n\nexport default defineWebSocket<unknown, ClientMessage, ServerMessage>({\n path: '/session/:sessionId',\n description: 'Persistent session event stream (all runs)',\n\n handler: {\n async onConnect(ctx: PluginContextV3, sender: TypedSender<ServerMessage>) {\n const hostContext = ctx.hostContext as { params?: { sessionId?: string }; query?: Record<string, string> };\n const sessionId = hostContext.params?.sessionId;\n // Present on resume/gap-recovery reconnects (see AgentsPage.tsx's turn-reducer\n // 'gap' handling). Not used to filter the response — see getProjection's doc\n // comment for why resume always re-sends the full projection rather than a\n // replayed delta range — but accepted and logged so a resume is distinguishable\n // from a cold connect in server logs.\n const afterSeq = hostContext.query?.afterSeq ? Number(hostContext.query.afterSeq) : undefined;\n\n if (!sessionId) {\n await sender.send({\n type: 'error',\n payload: { code: 'MISSING_SESSION_ID', message: 'Session ID is required' },\n timestamp: Date.now(),\n } satisfies ErrorMessage);\n sender.close(4000, 'Missing session ID');\n return;\n }\n\n ctx.platform.logger.info(\n afterSeq != null\n ? `[session-ws] Client connected to session ${sessionId} (resume after seq ${afterSeq})`\n : `[session-ws] Client connected to session ${sessionId}`\n );\n\n const sessionManager = new SessionManager(ctx.cwd);\n\n // Send connection:ready immediately\n try {\n await sender.send({\n type: 'connection:ready',\n payload: { runId: sessionId, connectedAt: new Date().toISOString() },\n timestamp: Date.now(),\n } satisfies ConnectionReadyMessage);\n } catch (err) {\n ctx.platform.logger.error(`[session-ws] Failed to send connection:ready: ${String(err)}`);\n throw err;\n }\n\n // Send conversation:snapshot (full current projection) as the baseline —\n // both for a cold connect AND a resume/gap-recovery reconnect alike.\n try {\n const { turns, seq } = await sessionManager.getProjection(sessionId);\n const completedTurns = turns.filter((t) => t.status !== 'streaming');\n const activeTurns = turns.filter((t) => t.status === 'streaming');\n await sender.send({\n type: 'conversation:snapshot',\n payload: {\n sessionId,\n completedTurns,\n activeTurns,\n totalTurns: turns.length,\n seq,\n timestamp: new Date().toISOString(),\n },\n timestamp: Date.now(),\n } satisfies ConversationSnapshotMessage);\n ctx.platform.logger.info(\n `[session-ws] Sent snapshot: ${completedTurns.length} completed + ${activeTurns.length} active turns at seq ${seq}`\n );\n } catch (err) {\n ctx.platform.logger.error(`[session-ws] Failed to send snapshot: ${err}`);\n }\n\n // Session-level listener — receives turn deltas and run:completed\n // notifications from ALL runs in this session, already computed at\n // persist time (see module doc comment above).\n const callback = (payload: SessionBroadcastPayload) => {\n if (payload.kind === 'deltas') {\n for (const delta of payload.deltas) {\n void sender.send({\n type: 'turn:delta',\n payload: { sessionId, delta },\n timestamp: Date.now(),\n } satisfies TurnDeltaMessage).catch((err) => {\n ctx.platform.logger.error(`[session-ws] Failed to send turn:delta: ${err}`);\n });\n }\n return;\n }\n\n void sender.send({\n type: 'run:completed',\n payload: {\n runId: payload.runId,\n success: payload.success,\n summary: payload.summary,\n durationMs: payload.durationMs,\n seq: payload.seq,\n turn: payload.turn,\n },\n timestamp: Date.now(),\n } satisfies RunCompletedMessage).catch((err) => {\n ctx.platform.logger.error(`[session-ws] Failed to send run:completed: ${err}`);\n });\n };\n\n // Store callback for cleanup in a WeakMap keyed by ctx — no ctx mutation\n connectionState.set(ctx as object, { sessionId, callback });\n\n try {\n RunManager.addSessionListener(sessionId, callback);\n } catch (err) {\n ctx.platform.logger.error(`[session-ws] Failed to register session listener: ${String(err)}`);\n throw err;\n }\n ctx.platform.logger.info(`[session-ws] Session listener registered for session ${sessionId}`);\n },\n\n async onMessage(ctx: PluginContextV3, message: ClientMessage, sender: TypedSender<ServerMessage>) {\n // Handle ping or corrections here if needed\n if (message.type === 'ping') {\n const sessionId = connectionState.get(ctx as object)?.sessionId ?? '';\n await sender.send({\n type: 'connection:ready',\n payload: { runId: sessionId ?? '', connectedAt: new Date().toISOString() },\n timestamp: Date.now(),\n });\n }\n },\n\n async onDisconnect(ctx: PluginContextV3) {\n const state = connectionState.get(ctx as object);\n if (state) {\n RunManager.removeSessionListener(state.sessionId, state.callback);\n connectionState.delete(ctx as object);\n }\n\n ctx.platform.logger.info(`[session-ws] Client disconnected from session ${state?.sessionId}`);\n },\n\n async onError(ctx: PluginContextV3, error: Error, sender: TypedSender<ServerMessage>) {\n ctx.platform.logger.error(`[session-ws] WebSocket error: ${error.message}`);\n await sender.send({\n type: 'error',\n payload: { code: 'INTERNAL_ERROR', message: error.message },\n timestamp: Date.now(),\n } satisfies ErrorMessage);\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/run-manager.ts","../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/ws/session-stream-handler.ts"],"names":[],"mappings":"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","file":"session-stream-handler.js","sourcesContent":["/**\n * Run Manager - tracks active agent runs for REST/WS API\n *\n * Uses platform cache for persistence and in-memory Map for active agents.\n * Cache stores serializable run state, Map stores live agent references.\n */\n\nimport type { IAgentRunner } from '@kb-labs/agent-sdk';\nimport type { SessionManager } from '@kb-labs/agent-core';\nimport type { Turn, TurnDelta } from '@kb-labs/agent-contracts';\nimport { useCache } from '@kb-labs/sdk';\n\nconst CACHE_PREFIX = 'agent:run:';\nconst CACHE_TTL = 3600000; // 1 hour\n\n/**\n * Run status\n */\nexport type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';\n\n/**\n * Serializable run state (stored in cache)\n */\nexport interface RunState {\n runId: string;\n task: string;\n status: RunStatus;\n startedAt: string;\n completedAt?: string;\n durationMs?: number;\n summary?: string;\n error?: string;\n}\n\n/**\n * Active run with live agent (in-memory only)\n */\nexport interface ActiveRun extends RunState {\n agent?: IAgentRunner;\n sessionManager: SessionManager;\n}\n\n/**\n * Payload delivered to session-level listeners — the sole live-update\n * channel for a session's WS connection(s). `deltas` carries incremental\n * turn changes (see TurnDelta); `run:completed` is a terminal signal\n * carrying the finished run's outcome and, when available, the final\n * state of the assistant turn it produced.\n */\nexport type SessionBroadcastPayload =\n | { kind: 'deltas'; deltas: TurnDelta[] }\n | {\n kind: 'run:completed';\n runId: string;\n success: boolean;\n summary: string;\n durationMs: number;\n seq: number;\n turn?: Turn;\n };\n\ntype SessionListenerCallback = (payload: SessionBroadcastPayload) => void;\n\n/**\n * Run Manager implementation\n */\nclass RunManagerImpl {\n /** Live agents (not cacheable) */\n private activeRuns: Map<string, ActiveRun> = new Map();\n\n /** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */\n private sessionListeners: Map<string, Set<SessionListenerCallback>> = new Map();\n\n /**\n * Generate unique run ID\n */\n generateRunId(): string {\n return `run-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n }\n\n /**\n * Register a new run\n */\n async register(\n runId: string,\n task: string,\n agent: IAgentRunner | undefined,\n sessionManager: SessionManager,\n ): Promise<ActiveRun> {\n const now = new Date().toISOString();\n\n const run: ActiveRun = {\n runId,\n task,\n status: 'pending',\n agent,\n sessionManager,\n startedAt: now,\n };\n\n // Store in memory (for live agent)\n this.activeRuns.set(runId, run);\n\n // Store serializable state in cache\n await this.saveToCache(run);\n\n return run;\n }\n\n /**\n * Get run by ID (from memory first, then cache for state)\n */\n get(runId: string): ActiveRun | undefined {\n return this.activeRuns.get(runId);\n }\n\n /**\n * Check if run exists (in memory or cache)\n */\n async exists(runId: string): Promise<boolean> {\n // Check memory first\n if (this.activeRuns.has(runId)) {\n return true;\n }\n // Fallback to cache\n const state = await this.getState(runId);\n return state !== null;\n }\n\n /**\n * Get run state from cache (for completed runs or cross-process access)\n */\n async getState(runId: string): Promise<RunState | null> {\n const cache = useCache();\n if (!cache) {return null;}\n\n return cache.get<RunState>(`${CACHE_PREFIX}${runId}`);\n }\n\n /**\n * Update run status\n */\n async updateStatus(runId: string, status: RunStatus, extra?: Partial<RunState>): Promise<void> {\n const run = this.activeRuns.get(runId);\n if (run) {\n run.status = status;\n if (extra) {\n Object.assign(run, extra);\n }\n await this.saveToCache(run);\n }\n }\n\n /**\n * Save run state to cache\n */\n private async saveToCache(run: ActiveRun): Promise<void> {\n const cache = useCache();\n if (!cache) {return;}\n\n const state: RunState = {\n runId: run.runId,\n task: run.task,\n status: run.status,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n\n await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);\n }\n\n /**\n * Broadcast turn deltas to all session-level listeners. Callers MUST await\n * persistence (sessionManager.addEvent) before calling this, so listeners\n * never observe a delta whose underlying turn state isn't on disk yet —\n * that ordering is what makes gap-recovery / reconnect resume correct.\n */\n broadcastSessionDeltas(sessionId: string, deltas: TurnDelta[]): void {\n if (deltas.length === 0) { return; }\n this.notifySessionListeners(sessionId, { kind: 'deltas', deltas });\n }\n\n /**\n * Broadcast a run's terminal outcome to session-level listeners. Called\n * directly from the run's own completion handler (after `agent.execute()`\n * resolves) rather than derived reactively from an `agent:end` event —\n * the completion handler already has definitive success/summary/duration,\n * and this guarantees the message fires exactly once, deterministically.\n */\n broadcastRunCompleted(sessionId: string, payload: Omit<Extract<SessionBroadcastPayload, { kind: 'run:completed' }>, 'kind'>): void {\n this.notifySessionListeners(sessionId, { kind: 'run:completed', ...payload });\n }\n\n private notifySessionListeners(sessionId: string, payload: SessionBroadcastPayload): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (!listeners) { return; }\n for (const listener of listeners) {\n try {\n listener(payload);\n } catch {\n // Ignore listener errors — one bad WS connection shouldn't affect others\n }\n }\n }\n\n /**\n * Add a session-level listener — receives updates from ALL runs in this session.\n */\n addSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n if (!this.sessionListeners.has(sessionId)) {\n this.sessionListeners.set(sessionId, new Set());\n }\n this.sessionListeners.get(sessionId)!.add(callback);\n }\n\n /**\n * Remove a session-level listener.\n */\n removeSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.sessionListeners.delete(sessionId);\n }\n }\n }\n\n /**\n * List all active runs\n */\n listActive(): Array<{ runId: string; task: string; status: RunStatus; startedAt: string }> {\n return Array.from(this.activeRuns.values()).map(r => ({\n runId: r.runId,\n task: r.task,\n status: r.status,\n startedAt: r.startedAt,\n }));\n }\n\n /**\n * Request graceful stop of a running agent (and its child agents via propagated AbortSignal).\n * Agent finishes its current tool call then exits at the next iteration boundary.\n */\n requestStop(runId: string): boolean {\n const run = this.activeRuns.get(runId);\n if (!run || run.status !== 'running' || !run.agent) {\n return false;\n }\n run.agent.requestStop();\n return true;\n }\n\n /**\n * Clean up completed runs from memory (cache handles its own TTL)\n */\n cleanup(): void {\n for (const [runId, run] of this.activeRuns) {\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n // Remove from memory but keep in cache\n this.activeRuns.delete(runId);\n }\n }\n }\n}\n\n/**\n * Singleton instance — stored on globalThis so all bundled modules share one instance.\n * When tsup compiles multiple entry points, each gets its own module scope,\n * so a plain `export const RunManager = new RunManagerImpl()` creates separate instances.\n * Using globalThis ensures run-handler.js and session-stream-handler.js share one RunManager.\n */\nconst GLOBAL_KEY = '__kb_agent_run_manager__';\nif (!(globalThis as Record<string, unknown>)[GLOBAL_KEY]) {\n (globalThis as Record<string, unknown>)[GLOBAL_KEY] = new RunManagerImpl();\n}\nexport const RunManager = (globalThis as Record<string, unknown>)[GLOBAL_KEY] as RunManagerImpl;\n","/**\n * WebSocket handler for session-level event streaming\n *\n * Path: /session/:sessionId\n * Single persistent connection per session — streams turn deltas for ALL runs in the session.\n * Unlike /events/:runId which closes when a run ends, this stays open for the entire session.\n *\n * Delta-based, not read-derived: the session listener registered here receives\n * the exact TurnDelta[] that SessionManager.processEventAndUpdateTurn computed\n * at persist time (via RunManager.broadcastSessionDeltas), not re-derived by\n * re-reading turns.json off disk on every event. That re-read (the previous\n * resolveTurnForEvent) was the actual root cause of the WS stream lagging one\n * event behind persisted state — see run-handler.ts's onEvent for the other\n * half of that fix (persist now happens before broadcast, not after).\n */\n\nimport {\n defineWebSocket,\n type PluginContextV3,\n type TypedSender,\n} from '@kb-labs/sdk';\nimport type {\n ServerMessage,\n ClientMessage,\n ConnectionReadyMessage,\n RunCompletedMessage,\n ErrorMessage,\n TurnDeltaMessage,\n ConversationSnapshotMessage,\n} from '@kb-labs/agent-contracts';\nimport { RunManager, type SessionBroadcastPayload } from '../rest/run-manager.js';\nimport { SessionManager } from '@kb-labs/agent-core';\n\ninterface SessionConnectionState {\n sessionId: string;\n callback: (payload: SessionBroadcastPayload) => void;\n}\n\n/** Per-connection state keyed by the opaque ctx object — avoids mutating ctx */\nconst connectionState = new WeakMap<object, SessionConnectionState>();\n\nexport default defineWebSocket<unknown, ClientMessage, ServerMessage>({\n path: '/session/:sessionId',\n description: 'Persistent session event stream (all runs)',\n\n handler: {\n async onConnect(ctx: PluginContextV3, sender: TypedSender<ServerMessage>) {\n const hostContext = ctx.hostContext as { params?: { sessionId?: string }; query?: Record<string, string> };\n const sessionId = hostContext.params?.sessionId;\n // Present on resume/gap-recovery reconnects (see AgentsPage.tsx's turn-reducer\n // 'gap' handling). Not used to filter the response — see getProjection's doc\n // comment for why resume always re-sends the full projection rather than a\n // replayed delta range — but accepted and logged so a resume is distinguishable\n // from a cold connect in server logs.\n const afterSeq = hostContext.query?.afterSeq ? Number(hostContext.query.afterSeq) : undefined;\n\n if (!sessionId) {\n await sender.send({\n type: 'error',\n payload: { code: 'MISSING_SESSION_ID', message: 'Session ID is required' },\n timestamp: Date.now(),\n } satisfies ErrorMessage);\n sender.close(4000, 'Missing session ID');\n return;\n }\n\n ctx.platform.logger.info(\n afterSeq != null\n ? `[session-ws] Client connected to session ${sessionId} (resume after seq ${afterSeq})`\n : `[session-ws] Client connected to session ${sessionId}`\n );\n\n const sessionManager = new SessionManager(ctx.cwd);\n\n // Send connection:ready immediately\n try {\n await sender.send({\n type: 'connection:ready',\n payload: { runId: sessionId, connectedAt: new Date().toISOString() },\n timestamp: Date.now(),\n } satisfies ConnectionReadyMessage);\n } catch (err) {\n ctx.platform.logger.error(`[session-ws] Failed to send connection:ready: ${String(err)}`);\n throw err;\n }\n\n // Send conversation:snapshot (full current projection) as the baseline —\n // both for a cold connect AND a resume/gap-recovery reconnect alike.\n try {\n const { turns, seq } = await sessionManager.getProjection(sessionId);\n const completedTurns = turns.filter((t) => t.status !== 'streaming');\n const activeTurns = turns.filter((t) => t.status === 'streaming');\n await sender.send({\n type: 'conversation:snapshot',\n payload: {\n sessionId,\n completedTurns,\n activeTurns,\n totalTurns: turns.length,\n seq,\n timestamp: new Date().toISOString(),\n },\n timestamp: Date.now(),\n } satisfies ConversationSnapshotMessage);\n ctx.platform.logger.info(\n `[session-ws] Sent snapshot: ${completedTurns.length} completed + ${activeTurns.length} active turns at seq ${seq}`\n );\n } catch (err) {\n ctx.platform.logger.error(`[session-ws] Failed to send snapshot: ${err}`);\n }\n\n // Session-level listener — receives turn deltas and run:completed\n // notifications from ALL runs in this session, already computed at\n // persist time (see module doc comment above).\n const callback = (payload: SessionBroadcastPayload) => {\n if (payload.kind === 'deltas') {\n for (const delta of payload.deltas) {\n void sender.send({\n type: 'turn:delta',\n payload: { sessionId, delta },\n timestamp: Date.now(),\n } satisfies TurnDeltaMessage).catch((err) => {\n ctx.platform.logger.error(`[session-ws] Failed to send turn:delta: ${err}`);\n });\n }\n return;\n }\n\n void sender.send({\n type: 'run:completed',\n payload: {\n runId: payload.runId,\n success: payload.success,\n summary: payload.summary,\n durationMs: payload.durationMs,\n seq: payload.seq,\n turn: payload.turn,\n },\n timestamp: Date.now(),\n } satisfies RunCompletedMessage).catch((err) => {\n ctx.platform.logger.error(`[session-ws] Failed to send run:completed: ${err}`);\n });\n };\n\n // Store callback for cleanup in a WeakMap keyed by ctx — no ctx mutation\n connectionState.set(ctx as object, { sessionId, callback });\n\n try {\n RunManager.addSessionListener(sessionId, callback);\n } catch (err) {\n ctx.platform.logger.error(`[session-ws] Failed to register session listener: ${String(err)}`);\n throw err;\n }\n ctx.platform.logger.info(`[session-ws] Session listener registered for session ${sessionId}`);\n },\n\n async onMessage(ctx: PluginContextV3, message: ClientMessage, sender: TypedSender<ServerMessage>) {\n // Handle ping or corrections here if needed\n if (message.type === 'ping') {\n const sessionId = connectionState.get(ctx as object)?.sessionId ?? '';\n await sender.send({\n type: 'connection:ready',\n payload: { runId: sessionId ?? '', connectedAt: new Date().toISOString() },\n timestamp: Date.now(),\n });\n }\n },\n\n async onDisconnect(ctx: PluginContextV3) {\n const state = connectionState.get(ctx as object);\n if (state) {\n RunManager.removeSessionListener(state.sessionId, state.callback);\n connectionState.delete(ctx as object);\n }\n\n ctx.platform.logger.info(`[session-ws] Client disconnected from session ${state?.sessionId}`);\n },\n\n async onError(ctx: PluginContextV3, error: Error, sender: TypedSender<ServerMessage>) {\n ctx.platform.logger.error(`[session-ws] WebSocket error: ${error.message}`);\n await sender.send({\n type: 'error',\n payload: { code: 'INTERNAL_ERROR', message: error.message },\n timestamp: Date.now(),\n } satisfies ErrorMessage);\n },\n },\n});\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kb-labs/agent-entry",
3
3
  "description": "CLI commands for KB Labs Agents V2. Provides agent:run-v2 command.",
4
- "version": "2.119.0-canary.e120bc0ee",
4
+ "version": "2.119.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -23,15 +23,15 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "zod": "^3.25.76",
26
- "@kb-labs/agent-contracts": "2.119.0-canary.e120bc0ee",
27
- "@kb-labs/agent-core": "2.119.0-canary.e120bc0ee",
28
- "@kb-labs/agent-history": "2.119.0-canary.e120bc0ee",
29
- "@kb-labs/agent-runtime": "2.119.0-canary.e120bc0ee",
30
- "@kb-labs/agent-sdk": "2.119.0-canary.e120bc0ee",
31
- "@kb-labs/agent-kernel": "2.119.0-canary.e120bc0ee",
32
- "@kb-labs/agent-store": "2.119.0-canary.e120bc0ee",
33
- "@kb-labs/agent-tools": "2.119.0-canary.e120bc0ee",
34
- "@kb-labs/agent-tracing": "2.119.0-canary.e120bc0ee",
26
+ "@kb-labs/agent-contracts": "2.119.0",
27
+ "@kb-labs/agent-core": "2.119.0",
28
+ "@kb-labs/agent-kernel": "2.119.0",
29
+ "@kb-labs/agent-history": "2.119.0",
30
+ "@kb-labs/agent-runtime": "2.119.0",
31
+ "@kb-labs/agent-sdk": "2.119.0",
32
+ "@kb-labs/agent-store": "2.119.0",
33
+ "@kb-labs/agent-tools": "2.119.0",
34
+ "@kb-labs/agent-tracing": "2.119.0",
35
35
  "@kb-labs/sdk": "2.115.4"
36
36
  },
37
37
  "devDependencies": {
@@ -46,12 +46,12 @@
46
46
  "tsup": "^8.5.0",
47
47
  "typescript": "^5.6.3",
48
48
  "vitest": "^3.2.6",
49
- "@kb-labs/devkit": "2.119.0-canary.e120bc0ee",
50
- "@kb-labs/studio-plugin-tools": "2.119.0-canary.e120bc0ee",
51
- "@kb-labs/plugin-runtime": "2.119.0-canary.e120bc0ee"
49
+ "@kb-labs/plugin-runtime": "2.119.0",
50
+ "@kb-labs/devkit": "2.119.0",
51
+ "@kb-labs/studio-plugin-tools": "2.119.0"
52
52
  },
53
53
  "engines": {
54
- "node": ">=22.0.0",
54
+ "node": ">=24.0.0",
55
55
  "pnpm": ">=9.0.0"
56
56
  },
57
57
  "kb": {