@geminixiang/mikan 1.0.0-beta.26 → 1.0.0-beta.28

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 (124) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +1 -1
  3. package/dist/adapters/discord/bot.d.ts.map +1 -1
  4. package/dist/adapters/discord/bot.js +17 -3
  5. package/dist/adapters/discord/bot.js.map +1 -1
  6. package/dist/adapters/slack/blocks.d.ts.map +1 -1
  7. package/dist/adapters/slack/blocks.js +49 -5
  8. package/dist/adapters/slack/blocks.js.map +1 -1
  9. package/dist/adapters/slack/bot.d.ts.map +1 -1
  10. package/dist/adapters/slack/bot.js +13 -1
  11. package/dist/adapters/slack/bot.js.map +1 -1
  12. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  13. package/dist/adapters/slack/response-lifecycle.js +14 -4
  14. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  15. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  16. package/dist/adapters/telegram/bot.js +24 -1
  17. package/dist/adapters/telegram/bot.js.map +1 -1
  18. package/dist/agent.d.ts.map +1 -1
  19. package/dist/agent.js +73 -0
  20. package/dist/agent.js.map +1 -1
  21. package/dist/cli/boot.d.ts +1 -1
  22. package/dist/cli/boot.d.ts.map +1 -1
  23. package/dist/cli/boot.js +7 -14
  24. package/dist/cli/boot.js.map +1 -1
  25. package/dist/commands/new.d.ts.map +1 -1
  26. package/dist/commands/new.js +8 -1
  27. package/dist/commands/new.js.map +1 -1
  28. package/dist/commands/types.d.ts +2 -1
  29. package/dist/commands/types.d.ts.map +1 -1
  30. package/dist/commands/types.js.map +1 -1
  31. package/dist/config.d.ts.map +1 -1
  32. package/dist/config.js +13 -40
  33. package/dist/config.js.map +1 -1
  34. package/dist/harness/extensions/registry.d.ts +19 -7
  35. package/dist/harness/extensions/registry.d.ts.map +1 -1
  36. package/dist/harness/extensions/registry.js +65 -6
  37. package/dist/harness/extensions/registry.js.map +1 -1
  38. package/dist/harness/extensions/types.d.ts +27 -6
  39. package/dist/harness/extensions/types.d.ts.map +1 -1
  40. package/dist/harness/extensions/types.js.map +1 -1
  41. package/dist/harness/index.d.ts +1 -1
  42. package/dist/harness/index.d.ts.map +1 -1
  43. package/dist/harness/index.js.map +1 -1
  44. package/dist/harness/runner.d.ts +8 -1
  45. package/dist/harness/runner.d.ts.map +1 -1
  46. package/dist/harness/runner.js +62 -11
  47. package/dist/harness/runner.js.map +1 -1
  48. package/dist/harness/session-store.d.ts +5 -4
  49. package/dist/harness/session-store.d.ts.map +1 -1
  50. package/dist/harness/session-store.js +120 -28
  51. package/dist/harness/session-store.js.map +1 -1
  52. package/dist/main.js +1 -51
  53. package/dist/main.js.map +1 -1
  54. package/dist/runtime/conversation-runtime.js +86 -4
  55. package/dist/runtime/conversation-runtime.js.map +1 -1
  56. package/dist/runtime/types.d.ts +2 -0
  57. package/dist/runtime/types.d.ts.map +1 -1
  58. package/dist/runtime/types.js.map +1 -1
  59. package/dist/sandbox/gondolin-bootstrap.d.ts +3 -17
  60. package/dist/sandbox/gondolin-bootstrap.d.ts.map +1 -1
  61. package/dist/sandbox/gondolin-bootstrap.js +2 -20
  62. package/dist/sandbox/gondolin-bootstrap.js.map +1 -1
  63. package/dist/sandbox/gondolin-contract.d.ts +3 -70
  64. package/dist/sandbox/gondolin-contract.d.ts.map +1 -1
  65. package/dist/sandbox/gondolin-contract.js +5 -89
  66. package/dist/sandbox/gondolin-contract.js.map +1 -1
  67. package/dist/sandbox/gondolin-recovery.d.ts +5 -18
  68. package/dist/sandbox/gondolin-recovery.d.ts.map +1 -1
  69. package/dist/sandbox/gondolin-recovery.js +5 -20
  70. package/dist/sandbox/gondolin-recovery.js.map +1 -1
  71. package/dist/sandbox/gondolin-worker-client.d.ts +8 -33
  72. package/dist/sandbox/gondolin-worker-client.d.ts.map +1 -1
  73. package/dist/sandbox/gondolin-worker-client.js +6 -7
  74. package/dist/sandbox/gondolin-worker-client.js.map +1 -1
  75. package/dist/sandbox/gondolin.d.ts +0 -5
  76. package/dist/sandbox/gondolin.d.ts.map +1 -1
  77. package/dist/sandbox/gondolin.js +14 -56
  78. package/dist/sandbox/gondolin.js.map +1 -1
  79. package/dist/sandbox/types.d.ts +1 -1
  80. package/dist/sandbox/types.d.ts.map +1 -1
  81. package/dist/sandbox/types.js.map +1 -1
  82. package/dist/sessions/chat-history-sync.d.ts.map +1 -1
  83. package/dist/sessions/chat-history-sync.js +14 -3
  84. package/dist/sessions/chat-history-sync.js.map +1 -1
  85. package/dist/tools/bash.d.ts.map +1 -1
  86. package/dist/tools/bash.js +1 -0
  87. package/dist/tools/bash.js.map +1 -1
  88. package/dist/tools/edit.d.ts.map +1 -1
  89. package/dist/tools/edit.js +1 -0
  90. package/dist/tools/edit.js.map +1 -1
  91. package/dist/tools/sandbox.d.ts.map +1 -1
  92. package/dist/tools/sandbox.js +1 -0
  93. package/dist/tools/sandbox.js.map +1 -1
  94. package/dist/tools/write.d.ts.map +1 -1
  95. package/dist/tools/write.js +1 -0
  96. package/dist/tools/write.js.map +1 -1
  97. package/dist/types.d.ts +6 -65
  98. package/dist/types.d.ts.map +1 -1
  99. package/dist/types.js.map +1 -1
  100. package/package.json +1 -1
  101. package/dist/sandbox/gondolin-fleet.d.ts +0 -104
  102. package/dist/sandbox/gondolin-fleet.d.ts.map +0 -1
  103. package/dist/sandbox/gondolin-fleet.js +0 -330
  104. package/dist/sandbox/gondolin-fleet.js.map +0 -1
  105. package/dist/sandbox/gondolin-gateway.d.ts +0 -86
  106. package/dist/sandbox/gondolin-gateway.d.ts.map +0 -1
  107. package/dist/sandbox/gondolin-gateway.js +0 -407
  108. package/dist/sandbox/gondolin-gateway.js.map +0 -1
  109. package/dist/sandbox/gondolin-join.d.ts +0 -62
  110. package/dist/sandbox/gondolin-join.d.ts.map +0 -1
  111. package/dist/sandbox/gondolin-join.js +0 -261
  112. package/dist/sandbox/gondolin-join.js.map +0 -1
  113. package/dist/sandbox/gondolin-nfs-advisory.d.ts +0 -15
  114. package/dist/sandbox/gondolin-nfs-advisory.d.ts.map +0 -1
  115. package/dist/sandbox/gondolin-nfs-advisory.js +0 -60
  116. package/dist/sandbox/gondolin-nfs-advisory.js.map +0 -1
  117. package/dist/sandbox/gondolin-placement.d.ts +0 -30
  118. package/dist/sandbox/gondolin-placement.d.ts.map +0 -1
  119. package/dist/sandbox/gondolin-placement.js +0 -77
  120. package/dist/sandbox/gondolin-placement.js.map +0 -1
  121. package/dist/sandbox/gondolin-remote.d.ts +0 -70
  122. package/dist/sandbox/gondolin-remote.d.ts.map +0 -1
  123. package/dist/sandbox/gondolin-remote.js +0 -325
  124. package/dist/sandbox/gondolin-remote.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/harness/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,KAAK,EACL,sBAAsB,EACtB,OAAO,EACP,YAAY,EACZ,qBAAqB,EACrB,UAAU,EACV,iBAAiB,EACjB,aAAa,GAMd,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iBAAiB,GAKlB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AAIjC,OAAO,EAAE,sBAAsB,EAA6C,MAAM,eAAe,CAAC;AAGlG,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAqD3F,6EAA6E;AAC7E,kDAAkD;AAClD,MAAM,uBAAuB,GAC3B,wcAAwc,CAAC;AAE3c,SAAS,KAAK,CAAC,EAAU,EAAE,MAAmB;IAC5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/B,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC;AAaD,MAAM,OAAO,iBAAiB;IAqB5B,YAAY,OAAiC;QAfrC,cAAS,GAAG,IAAI,GAAG,EAAwB,CAAC;QAC5C,iBAAY,GAAG,CAAC,CAAC;QACjB,8BAAyB,GAAG,KAAK,CAAC;QAGlC,cAAS,GAAG,KAAK,CAAC;QAClB,UAAK,GAAa;YACxB,KAAK,EAAE,wBAAwB,EAAE;YACjC,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,CAAC;SACb,CAAC;QACM,cAAS,GAAmB,EAAE,CAAC;QAKrC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,QAAQ,GAAG,sBAAsB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QAErC,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvF,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC;YACrB,YAAY,EAAE;gBACZ,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,KAAK;aACN;YACD,YAAY;YACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,CAC1C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC;YAChE,cAAc,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;gBAC3C,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,WAAW,CAAC;oBAAE,OAAO,SAAS,CAAC;gBACjE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE;oBACrD,UAAU,EAAE,QAAQ,CAAC,EAAE;oBACvB,QAAQ,EAAE,QAAQ,CAAC,IAAI;oBACvB,IAAI;oBACJ,MAAM,EAAE,IAAI,CAAC,SAAS;iBACvB,CAAC,CAAC;gBACH,OAAO,MAAM,IAAI,SAAS,CAAC;YAC7B,CAAC;YACD,aAAa,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;gBAC3D,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,aAAa,CAAC;oBAAE,OAAO,SAAS,CAAC;gBACnE,8DAA8D;gBAC9D,kEAAkE;gBAClE,6BAA6B;gBAC7B,OAAO,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC;oBACpC,UAAU,EAAE,QAAQ,CAAC,EAAE;oBACvB,QAAQ,EAAE,QAAQ,CAAC,IAAI;oBACvB,IAAI;oBACJ,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,OAAO;oBACP,MAAM,EAAE,IAAI,CAAC,SAAS;iBACvB,CAAC,CAAC;YACL,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACnC,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,2DAA2D;IAC3D,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;IACnC,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;IAChC,CAAC;IAED,+EAA+E;IAC/E,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,6EAA6E;IAC7E,eAAe;QAQb,OAAO;YACL,KAAK,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;YAC1C,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW;YACpC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;YACpC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ;YAC7B,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC5E,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1F,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,iBAAiB,CAAC,KAAoB;QAC1C,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC1C,IAAI,IAAI,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QACzD,MAAM,MAAM,GAAG,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAC/C,IAAI,MAAM;YAAE,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,SAAS,CAAC,QAA8B;QACtC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,oEAAoE;IACpE,iBAAiB;QACf,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE,CAAC;QACxD,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC/C,CAAC;QACD,OAAO,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IACjC,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,MAAM,CACV,IAAY,EACZ,OAAkF;QAElF,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,SAAS,CACrB,IAAY,EACZ,OAAkF;QAElF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;QACrC,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAEvC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,yBAAyB,GAAG,KAAK,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC;QACjE,IAAI,CAAC,oBAAoB,GAAG,SAAS,CAAC;QACtC,IAAI,CAAC,KAAK,GAAG;YACX,KAAK,EAAE,wBAAwB,EAAE;YACjC,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QACF,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,MAAM,CAAC;QAEjC,0EAA0E;QAC1E,oDAAoD;QACpD,MAAM,aAAa,GAAG,IAAI,CAAC,wBAAwB,EAAE,CAAC;QACtD,IAAI,aAAa,IAAI,aAAa,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;YAC1D,MAAM,IAAI,CAAC,wBAAwB,CAAC,aAAa,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,UAAU,GAAG,IAAI,CAAC;QACtB,IAAI,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC;QACjD,IAAI,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC;gBACxD,MAAM,EAAE,UAAU;gBAClB,MAAM,EAAE,OAAO,EAAE,MAAM;gBACvB,YAAY;gBACZ,MAAM,EAAE,IAAI,CAAC,SAAS;aACvB,CAAC,CAAC;YACH,IAAI,MAAM,EAAE,KAAK,EAAE,CAAC;gBAClB,mEAAmE;gBACnE,oEAAoE;gBACpE,GAAG,CAAC,OAAO,CAAC,yBAAyB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAClF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;YAClD,CAAC;YACD,IAAI,MAAM,EAAE,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACjE,GAAG,CAAC,OAAO,CACT,kCAAkC,UAAU,CAAC,MAAM,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,QAAQ,CACtF,CAAC;gBACF,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;YAC7B,CAAC;YACD,IAAI,MAAM,EAAE,YAAY,IAAI,MAAM,CAAC,YAAY,KAAK,YAAY,EAAE,CAAC;gBACjE,oEAAoE;gBACpE,sEAAsE;gBACtE,yDAAyD;gBACzD,GAAG,CAAC,OAAO,CACT,oCAAoC,YAAY,CAAC,MAAM,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,QAAQ,CAChG,CAAC;gBACF,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;gBACnC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,GAAG,YAAY,CAAC;YAC/C,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAAiB;YAChC,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;YACzE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QAEF,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;QACvC,OAAO,MAAM,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;YAClC,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC9B,CAAC;QAED,qEAAqE;QACrE,+DAA+D;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAChD,IAAI,OAAO,EAAE,UAAU,KAAK,OAAO,IAAI,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,aAAa,CAAC,EAAE,CAAC;YACnF,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,EAAE;gBACxC,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,eAAe;gBACrD,MAAM,EAAE,IAAI,CAAC,SAAS;aACvB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE;gBACrC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ;gBACnC,MAAM,EAAE,IAAI,CAAC,SAAS;aACvB,CAAC,CAAC;QACL,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,6EAA6E;IAC7E,KAAK;QACH,IAAI,CAAC,oBAAoB,EAAE,KAAK,EAAE,CAAC;QACnC,IAAI,CAAC,yBAAyB,EAAE,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAAC,KAAiB;QAClD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,gCAAgC,KAAK,CAAC,QAAQ,0EAA0E,CACzH,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,KAAmB;QACpC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,UAAU,CACZ,+BAA+B,EAC/B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,KAAiB;QAC9C,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEvB,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa;YAAE,OAAO;QACzC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAE9B,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC7F,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,OAAwB,CAAC;YACxC,IAAI,CAAC,YAAY,CAAC,wBAAwB,CACxC,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,OAAO,CACf,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,aAAa,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QACjF,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACjC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC1B,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAClC,IAAI,OAAO,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBACnC,IAAI,CAAC,yBAAyB,GAAG,KAAK,CAAC;gBACvC,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;oBAC1B,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;oBACvF,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,sEAAsE;IAC9D,WAAW,CAAC,OAAyB;QAC3C,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC;QACzB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC5B,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,sFAAsF;IAC9E,KAAK,CAAC,aAAa,CAAC,OAAyB;QACnD,IAAI,IAAI,CAAC,oBAAoB;YAAE,OAAO;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,kFAAkF;IAC1E,KAAK,CAAC,YAAY,CAAC,MAAc;QACvC,IAAI,CAAC,oBAAoB,GAAG,MAAM,CAAC;QACnC,MAAM,IAAI,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,iBAAiB;YACvB,MAAM;YACN,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW;YACpC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;YACpC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ;YAC7B,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS;SAC9C,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,EAAE;gBAC5C,MAAM;gBACN,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW;gBACpC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;gBACpC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAC7B,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS;gBAC7C,MAAM,EAAE,IAAI,CAAC,SAAS;aACvB,CAAC,CAAC;QACL,CAAC;QACD,GAAG,CAAC,UAAU,CAAC,gCAAgC,EAAE,MAAM,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAEO,gBAAgB,CAAC,OAAyB;QAChD,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;QACvC,MAAM,gBAAgB,GACpB,OAAO,CAAC,UAAU,KAAK,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QAC7F,IAAI,gBAAgB,IAAI,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,WAAW,EAAE,CAAC;YACxF,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,iBAAiB,WAAW,QAAQ,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC,wBAAwB,EAAE,CAAC;IACzC,CAAC;IAED,+EAA+E;IACvE,wBAAwB;QAC9B,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;QAChE,IAAI,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,IAAI,SAAS,EAAE,CAAC;YACzE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,cAAc,SAAS,QAAQ,CAAC;QACxE,CAAC;QACD,IAAI,UAAU,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC;YAC1E,OAAO,QAAQ,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,UAAU,YAAY,CAAC;QACzF,CAAC;QACD,IAAI,aAAa,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,aAAa,EAAE,CAAC;YACtF,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,SAAS,aAAa,UAAU,CAAC;QAC9E,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,wBAAwB;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC3C,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;gBAAE,OAAO,OAAO,CAAC;QACnD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,0FAA0F;IAClF,KAAK,CAAC,aAAa;QACzB,4EAA4E;QAC5E,qEAAqE;QACrE,IAAI,IAAI,CAAC,oBAAoB;YAAE,OAAO,KAAK,CAAC;QAE5C,MAAM,aAAa,GAAG,IAAI,CAAC,wBAAwB,EAAE,CAAC;QACtD,IAAI,CAAC,aAAa;YAAE,OAAO,KAAK,CAAC;QAEjC,IAAI,aAAa,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;YACzC,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;YAChE,IAAI,iBAAiB,CAAC,aAAa,EAAE,aAAa,CAAC,EAAE,CAAC;gBACpD,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;YAC/B,CAAC;YACD,IAAI,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,CAAC;gBACzC,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;YAC1C,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC,wBAAwB,CAAC,aAAa,CAAC,CAAC;IACtD,CAAC;IAEO,KAAK,CAAC,cAAc;QAC1B,IAAI,IAAI,CAAC,yBAAyB,EAAE,CAAC;YACnC,MAAM,IAAI,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,gBAAgB;gBACtB,MAAM,EAAE,UAAU;gBAClB,OAAO,EAAE,KAAK;gBACd,YAAY,EACV,2GAA2G;aAC9G,CAAC,CAAC;YACH,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC;QACtC,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAC9C,CAAC;IAEO,KAAK,CAAC,wBAAwB,CAAC,aAA+B;QACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC1C,IAAI,CAAC,QAAQ,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QACpC,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;QAChE,IAAI,aAAa,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QAErC,IAAI,aAAa,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,sBAAsB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1F,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAClE,IAAI,QAAQ,CAAC,cAAc,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACnD,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC;QAClC,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,aAAa,EAAE,QAAQ,CAAC;YAAE,OAAO,KAAK,CAAC;QACzE,OAAO,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,MAAwB,EAAE,SAAkB;QACtE,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC;YAClD,MAAM,WAAW,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;YACzF,IAAI,CAAC,WAAW;gBAAE,OAAO,KAAK,CAAC;YAE/B,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC,CAAC;YACtD,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,CAAC,yBAAyB,GAAG,IAAI,eAAe,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC;YAErD,MAAM,MAAM,GAAG,UAAU,CACvB,MAAM,OAAO,CACX,WAAW,EACX,IAAI,CAAC,MAAM,CAAC,MAAM,EAClB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EACtB,SAAS,EACT,MAAM,EACN,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAC/B,CACF,CAAC;YACF,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBACnE,OAAO,KAAK,CAAC;YACf,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAChD,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,gBAAgB,EACvB,MAAM,CAAC,YAAY,EACnB,MAAM,CAAC,OAAO,CACf,CAAC;YACF,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE,CAAC;YACxD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;YAE7C,IAAI,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACpD,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAClD,IAAI,KAAK,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;oBACjC,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,EAAE;wBAC5C,KAAK,EAAE,KAAwB;wBAC/B,MAAM;qBACP,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,MAAM,IAAI,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,gBAAgB;gBACtB,MAAM;gBACN,MAAM,EAAE;oBACN,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;oBACzC,YAAY,EAAE,MAAM,CAAC,YAAY;iBAClC;gBACD,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;YAEH,IAAI,SAAS,EAAE,CAAC;gBACd,IAAI,CAAC,wBAAwB,EAAE,CAAC;gBAChC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;YAClF,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,IAAI,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,gBAAgB;oBACtB,MAAM;oBACN,OAAO,EAAE,KAAK;oBACd,YAAY,EACV,MAAM,KAAK,UAAU;wBACnB,CAAC,CAAC,qCAAqC,YAAY,EAAE;wBACrD,CAAC,CAAC,2BAA2B,YAAY,EAAE;iBAChD,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,UAAU,CAAC,+BAA+B,EAAE,YAAY,CAAC,CAAC;YAChE,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,yBAAyB,GAAG,SAAS,CAAC;QAC7C,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,OAAyB;QAChD,IAAI,OAAO,CAAC,UAAU,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY;YAAE,OAAO,KAAK,CAAC;QAC1E,OAAO,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5D,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,OAAyB;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QACrC,IAAI,CAAC,QAAQ,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAEpC,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC;YAC5C,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,MAAM,IAAI,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,IAAI,CAAC,YAAY;gBAC1B,UAAU,EAAE,OAAO,CAAC,YAAY;aACjC,CAAC,CAAC;YACH,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;QACpE,MAAM,IAAI,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,IAAI,CAAC,YAAY;YAC1B,WAAW,EAAE,QAAQ,CAAC,UAAU;YAChC,OAAO;YACP,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,eAAe;SACtD,CAAC,CAAC;QAEH,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAEhC,IAAI,CAAC,oBAAoB,GAAG,IAAI,eAAe,EAAE,CAAC;QAClD,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC;YAClC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;YACtB,MAAM,IAAI,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAE,KAAK;gBACd,OAAO;gBACP,UAAU,EAAE,iBAAiB;aAC9B,CAAC,CAAC;YACH,OAAO,KAAK,CAAC;QACf,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,oBAAoB,GAAG,SAAS,CAAC;QACxC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,wBAAwB;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC3C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC9E,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * MikanAgentSession — mikan's agent run loop.\n *\n * Owns a pi-agent-core `Agent` and layers on the behaviors mikan needs for\n * long-lived chat conversations:\n *\n * - message persistence into the conversation's {@link SessionStore}\n * - automatic context compaction (threshold and overflow recovery), using\n * pi-agent-core's compaction pipeline over the session tree\n * - automatic retry with exponential backoff on transient provider errors\n * - extension hook dispatch ({@link ExtensionRegistry})\n *\n * Events mirror the agent's lifecycle events plus `compaction_start/_end`\n * and `auto_retry_start/_end`, preserving the event surface mikan's\n * platform adapters already render.\n */\nimport {\n Agent,\n calculateContextTokens,\n compact,\n convertToLlm,\n estimateContextTokens,\n getOrThrow,\n prepareCompaction,\n shouldCompact,\n type AgentEvent,\n type AgentMessage,\n type AgentTool,\n type CustomMessage,\n type ThinkingLevel,\n} from \"@earendil-works/pi-agent-core\";\nimport {\n isContextOverflow,\n type Api,\n type AssistantMessage,\n type ImageContent,\n type Model,\n} from \"@earendil-works/pi-ai\";\nimport * as log from \"../log.js\";\nimport type { ExtensionRegistry } from \"./extensions/registry.js\";\nimport type { RunOrigin } from \"./extensions/types.js\";\nimport type { MikanModels } from \"./models.js\";\nimport { resolveHarnessSettings, type BudgetSettings, type HarnessSettings } from \"./settings.js\";\nimport type { SessionStore } from \"./session-store.js\";\nimport type { CompactionEntry, SubagentUsage } from \"./types.js\";\nimport { addSubagentUsage, copySubagentUsage, createEmptySubagentUsage } from \"./usage.js\";\n\nexport type CompactionReason = \"threshold\" | \"overflow\" | \"manual\";\n\n/** Running resource tally for the current `prompt()` call, matched against the budget. */\ninterface RunTally {\n usage: SubagentUsage;\n llmCalls: number;\n startedAt: number;\n}\n\ninterface CompactionResultSummary {\n summary: string;\n firstKeptEntryId: string;\n tokensBefore: number;\n}\n\nexport type HarnessEvent =\n | AgentEvent\n | { type: \"compaction_start\"; reason: CompactionReason }\n | {\n type: \"compaction_end\";\n reason: CompactionReason;\n result?: CompactionResultSummary;\n aborted: boolean;\n errorMessage?: string;\n }\n | {\n type: \"auto_retry_start\";\n attempt: number;\n maxAttempts: number;\n delayMs: number;\n errorMessage: string;\n }\n | { type: \"auto_retry_end\"; success: boolean; attempt: number; finalError?: string }\n | {\n type: \"budget_exceeded\";\n /** Which cap was hit, e.g. \"cost 2.01 USD > 2 USD limit\". */\n reason: string;\n tokens: number;\n costUsd: number;\n llmCalls: number;\n durationMs: number;\n };\n\nexport type HarnessEventListener = (event: HarnessEvent) => void | Promise<void>;\n\n/** Outcome of a `prompt()` call that an extension blocked before the model ran. */\nexport interface PromptBlockedOutcome {\n blocked: true;\n reason?: string;\n}\n\n// Transient provider failures worth retrying: overload/rate-limit responses,\n// 5xx statuses, and network/stream interruptions.\nconst RETRYABLE_ERROR_PATTERN =\n /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|http2 request did not get a response|timed? out|timeout|terminated|retry delay/i;\n\nfunction sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal.aborted) {\n reject(new Error(\"aborted\"));\n return;\n }\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(new Error(\"aborted\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nexport interface MikanAgentSessionOptions {\n systemPrompt: string;\n model: Model<Api>;\n thinkingLevel: ThinkingLevel;\n tools: AgentTool[];\n models: MikanModels;\n sessionStore: SessionStore;\n settings?: Parameters<typeof resolveHarnessSettings>[0];\n extensions?: ExtensionRegistry;\n}\n\nexport class MikanAgentSession {\n readonly agent: Agent;\n readonly sessionStore: SessionStore;\n private readonly models: MikanModels;\n private readonly settings: HarnessSettings;\n private readonly extensions: ExtensionRegistry | undefined;\n private listeners = new Set<HarnessEventListener>();\n private retryAttempt = 0;\n private overflowRecoveryAttempted = false;\n private retryAbortController: AbortController | undefined;\n private compactionAbortController: AbortController | undefined;\n private runActive = false;\n private tally: RunTally = {\n usage: createEmptySubagentUsage(),\n llmCalls: 0,\n startedAt: 0,\n };\n private runBudget: BudgetSettings = {};\n private budgetExceededReason: string | undefined;\n private runOrigin: RunOrigin | undefined;\n\n constructor(options: MikanAgentSessionOptions) {\n this.models = options.models;\n this.sessionStore = options.sessionStore;\n this.settings = resolveHarnessSettings(options.settings);\n this.extensions = options.extensions;\n\n const tools = [...options.tools, ...(options.extensions?.getContributedTools() ?? [])];\n this.agent = new Agent({\n initialState: {\n systemPrompt: options.systemPrompt,\n model: options.model,\n thinkingLevel: options.thinkingLevel,\n tools,\n },\n convertToLlm,\n streamFn: (model, context, streamOptions) =>\n this.models.models.streamSimple(model, context, streamOptions),\n beforeToolCall: async ({ toolCall, args }) => {\n if (!this.extensions?.hasHandlers(\"tool_call\")) return undefined;\n const result = await this.extensions.emit(\"tool_call\", {\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n args,\n origin: this.runOrigin,\n });\n return result ?? undefined;\n },\n afterToolCall: async ({ toolCall, args, result, isError }) => {\n if (!this.extensions?.hasHandlers(\"tool_result\")) return undefined;\n // Chained extension rewrites (redaction, truncation) become a\n // pi-agent-core AfterToolCallResult override; undefined keeps the\n // executed result untouched.\n return this.extensions.emitToolResult({\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n args,\n content: result.content,\n isError,\n origin: this.runOrigin,\n });\n },\n });\n\n this.agent.subscribe(async (event) => {\n await this.handleAgentEvent(event);\n });\n }\n\n /** Conversation transcript currently held by the agent. */\n get messages(): AgentMessage[] {\n return this.agent.state.messages;\n }\n\n get model(): Model<Api> {\n return this.agent.state.model;\n }\n\n /** Whether this session currently owns a prompt, including pre-model hooks. */\n get isActiveRun(): boolean {\n return this.runActive;\n }\n\n /** Resource totals and terminal budget state from the most recent prompt. */\n getLastRunStats(): Readonly<{\n usage: SubagentUsage;\n tokens: number;\n costUsd: number;\n llmCalls: number;\n durationMs: number;\n budgetExceededReason?: string;\n }> {\n return {\n usage: copySubagentUsage(this.tally.usage),\n tokens: this.tally.usage.totalTokens,\n costUsd: this.tally.usage.cost.total,\n llmCalls: this.tally.llmCalls,\n durationMs: this.tally.startedAt > 0 ? Date.now() - this.tally.startedAt : 0,\n ...(this.budgetExceededReason ? { budgetExceededReason: this.budgetExceededReason } : {}),\n };\n }\n\n /**\n * Fold spend incurred outside this session's own LLM calls — e.g. subagent\n * runs launched by a tool during the current prompt — into the run tally\n * and enforce the run budget at the fold itself: a fold that lands over a\n * resource ceiling aborts the run now instead of waiting for a next\n * assistant message that may never come (and would be paid for). Complete\n * usage is folded; external runs are not this session's turns.\n */\n async foldExternalUsage(usage: SubagentUsage): Promise<void> {\n addSubagentUsage(this.tally.usage, usage);\n if (this.budgetExceededReason || !this.runActive) return;\n const reason = this.resourceOverBudgetReason();\n if (reason) await this.exceedBudget(reason);\n }\n\n subscribe(listener: HarnessEventListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /** Replace the agent transcript from the persisted session tree. */\n reloadFromSession(): number {\n const context = this.sessionStore.buildSessionContext();\n if (context.messages.length > 0) {\n this.agent.state.messages = context.messages;\n }\n return context.messages.length;\n }\n\n /**\n * Send a user prompt and run the agent loop to completion, including\n * automatic retries and compaction. Resolves when the turn (and any\n * recovery continuations) settles. Returns a blocked outcome when a\n * `before_agent_start` extension blocked the turn — the model was never\n * called and nothing was persisted.\n *\n * @param options.budget Per-run resource ceilings that override the session\n * defaults. Autonomous (event / trigger) runs should pass a budget so a\n * runaway loop is stopped even with no human watching.\n * @param options.origin Platform provenance forwarded to extension hooks.\n */\n async prompt(\n text: string,\n options?: { images?: ImageContent[]; budget?: BudgetSettings; origin?: RunOrigin },\n ): Promise<PromptBlockedOutcome | undefined> {\n if (this.runActive) {\n throw new Error(\"Agent is already processing a prompt\");\n }\n this.runActive = true;\n try {\n return await this.runPrompt(text, options);\n } finally {\n this.runActive = false;\n }\n }\n\n private async runPrompt(\n text: string,\n options?: { images?: ImageContent[]; budget?: BudgetSettings; origin?: RunOrigin },\n ): Promise<PromptBlockedOutcome | undefined> {\n const model = this.agent.state.model;\n await this.ensureAuthConfigured(model);\n\n this.retryAttempt = 0;\n this.overflowRecoveryAttempted = false;\n this.runBudget = { ...this.settings.budget, ...options?.budget };\n this.budgetExceededReason = undefined;\n this.tally = {\n usage: createEmptySubagentUsage(),\n llmCalls: 0,\n startedAt: Date.now(),\n };\n this.runOrigin = options?.origin;\n\n // A previous turn may have ended over the threshold (for example after an\n // abort); compact before adding new context on top.\n const lastAssistant = this.findLastAssistantMessage();\n if (lastAssistant && lastAssistant.stopReason !== \"error\") {\n await this.checkThresholdCompaction(lastAssistant);\n }\n\n let promptText = text;\n let systemPrompt = this.agent.state.systemPrompt;\n if (this.extensions?.hasHandlers(\"before_agent_start\")) {\n const result = await this.extensions.emitBeforeAgentStart({\n prompt: promptText,\n images: options?.images,\n systemPrompt,\n origin: this.runOrigin,\n });\n if (result?.block) {\n // Blocked before agent.prompt(): the user message never enters the\n // transcript or session store, so the blocked turn leaves no trace.\n log.logInfo(`Extension blocked turn${result.reason ? `: ${result.reason}` : \"\"}`);\n return { blocked: true, reason: result.reason };\n }\n if (result?.prompt !== undefined && result.prompt !== promptText) {\n log.logInfo(\n `Extension rewrote user prompt: ${promptText.length} → ${result.prompt.length} chars`,\n );\n promptText = result.prompt;\n }\n if (result?.systemPrompt && result.systemPrompt !== systemPrompt) {\n // An extension rewrote the system prompt for this turn. Log the new\n // size so the diagnostic in agent.ts (which logs the pre-hook prompt)\n // isn't mistaken for the final prompt sent to the model.\n log.logInfo(\n `Extension rewrote system prompt: ${systemPrompt.length} → ${result.systemPrompt.length} chars`,\n );\n systemPrompt = result.systemPrompt;\n this.agent.state.systemPrompt = systemPrompt;\n }\n }\n\n const userMessage: AgentMessage = {\n role: \"user\",\n content: [{ type: \"text\", text: promptText }, ...(options?.images ?? [])],\n timestamp: Date.now(),\n };\n\n await this.agent.prompt([userMessage]);\n while (await this.handlePostRun()) {\n await this.agent.continue();\n }\n\n // The turn settled on an error (retries exhausted or not retryable):\n // give monitoring extensions the final failure, once per turn.\n const settled = this.findLastAssistantMessage();\n if (settled?.stopReason === \"error\" && this.extensions?.hasHandlers(\"agent_error\")) {\n await this.extensions.emit(\"agent_error\", {\n errorMessage: settled.errorMessage || \"Unknown error\",\n origin: this.runOrigin,\n });\n }\n\n if (this.extensions?.hasHandlers(\"turn_end\")) {\n await this.extensions.emit(\"turn_end\", {\n messages: this.agent.state.messages,\n origin: this.runOrigin,\n });\n }\n return undefined;\n }\n\n /** Abort the active run, pending retry backoff, and in-flight compaction. */\n abort(): void {\n this.retryAbortController?.abort();\n this.compactionAbortController?.abort();\n this.agent.abort();\n }\n\n private async ensureAuthConfigured(model: Model<Api>): Promise<void> {\n const auth = await this.models.getAuth(model);\n if (!auth) {\n throw new Error(\n `No credentials for provider \"${model.provider}\". Set the provider API key environment variable or add it to auth.json.`,\n );\n }\n }\n\n private async emit(event: HarnessEvent): Promise<void> {\n for (const listener of this.listeners) {\n try {\n await listener(event);\n } catch (err) {\n log.logWarning(\n \"Harness event listener failed\",\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n }\n\n private async handleAgentEvent(event: AgentEvent): Promise<void> {\n await this.emit(event);\n\n if (event.type !== \"message_end\") return;\n const message = event.message;\n\n if (message.role === \"user\" || message.role === \"assistant\" || message.role === \"toolResult\") {\n this.sessionStore.appendMessage(message);\n } else if (message.role === \"custom\") {\n const custom = message as CustomMessage;\n this.sessionStore.appendCustomMessageEntry(\n custom.customType,\n custom.content,\n custom.display,\n custom.details,\n );\n }\n\n if (this.extensions?.hasHandlers(\"message_end\")) {\n await this.extensions.emit(\"message_end\", { message, origin: this.runOrigin });\n }\n\n if (message.role === \"assistant\") {\n this.recordUsage(message);\n await this.enforceBudget(message);\n if (message.stopReason !== \"error\") {\n this.overflowRecoveryAttempted = false;\n if (this.retryAttempt > 0) {\n await this.emit({ type: \"auto_retry_end\", success: true, attempt: this.retryAttempt });\n this.retryAttempt = 0;\n }\n }\n }\n }\n\n /** Fold one assistant turn's usage into the running per-run tally. */\n private recordUsage(message: AssistantMessage): void {\n this.tally.llmCalls += 1;\n const usage = message.usage;\n if (!usage) return;\n addSubagentUsage(this.tally.usage, usage);\n }\n\n /** Compare the tally against the run budget; abort the run when a cap is exceeded. */\n private async enforceBudget(message: AssistantMessage): Promise<void> {\n if (this.budgetExceededReason) return;\n const reason = this.overBudgetReason(message);\n if (!reason) return;\n await this.exceedBudget(reason);\n }\n\n /** Mark the run over budget, notify listeners and extensions, abort the agent. */\n private async exceedBudget(reason: string): Promise<void> {\n this.budgetExceededReason = reason;\n await this.emit({\n type: \"budget_exceeded\",\n reason,\n tokens: this.tally.usage.totalTokens,\n costUsd: this.tally.usage.cost.total,\n llmCalls: this.tally.llmCalls,\n durationMs: Date.now() - this.tally.startedAt,\n });\n if (this.extensions?.hasHandlers(\"budget_exceeded\")) {\n await this.extensions.emit(\"budget_exceeded\", {\n reason,\n tokens: this.tally.usage.totalTokens,\n costUsd: this.tally.usage.cost.total,\n llmCalls: this.tally.llmCalls,\n durationMs: Date.now() - this.tally.startedAt,\n origin: this.runOrigin,\n });\n }\n log.logWarning(\"Run budget exceeded — aborting\", reason);\n this.agent.abort();\n }\n\n private overBudgetReason(message: AssistantMessage): string | undefined {\n const { maxLlmCalls } = this.runBudget;\n const needsAnotherCall =\n message.stopReason === \"error\" || message.content.some((part) => part.type === \"toolCall\");\n if (needsAnotherCall && maxLlmCalls !== undefined && this.tally.llmCalls >= maxLlmCalls) {\n return `${this.tally.llmCalls} LLM calls >= ${maxLlmCalls} limit`;\n }\n return this.resourceOverBudgetReason();\n }\n\n /** The message-independent budget checks, shared with external-spend folds. */\n private resourceOverBudgetReason(): string | undefined {\n const { maxTokens, maxCostUsd, maxDurationMs } = this.runBudget;\n if (maxTokens !== undefined && this.tally.usage.totalTokens >= maxTokens) {\n return `${this.tally.usage.totalTokens} tokens >= ${maxTokens} limit`;\n }\n if (maxCostUsd !== undefined && this.tally.usage.cost.total >= maxCostUsd) {\n return `cost ${this.tally.usage.cost.total.toFixed(2)} USD >= ${maxCostUsd} USD limit`;\n }\n if (maxDurationMs !== undefined && Date.now() - this.tally.startedAt >= maxDurationMs) {\n return `${Date.now() - this.tally.startedAt}ms >= ${maxDurationMs}ms limit`;\n }\n return undefined;\n }\n\n private findLastAssistantMessage(): AssistantMessage | undefined {\n const messages = this.agent.state.messages;\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i];\n if (message.role === \"assistant\") return message;\n }\n return undefined;\n }\n\n /** Decide what to do after a run settles. Returns true when the agent should continue. */\n private async handlePostRun(): Promise<boolean> {\n // A run stopped for going over budget must not be retried or compacted back\n // into another continuation — that would defeat the circuit breaker.\n if (this.budgetExceededReason) return false;\n\n const lastAssistant = this.findLastAssistantMessage();\n if (!lastAssistant) return false;\n\n if (lastAssistant.stopReason === \"error\") {\n const contextWindow = this.agent.state.model.contextWindow || 0;\n if (isContextOverflow(lastAssistant, contextWindow)) {\n return this.handleOverflow();\n }\n if (this.isRetryableError(lastAssistant)) {\n return this.prepareRetry(lastAssistant);\n }\n return false;\n }\n\n return this.checkThresholdCompaction(lastAssistant);\n }\n\n private async handleOverflow(): Promise<boolean> {\n if (this.overflowRecoveryAttempted) {\n await this.emit({\n type: \"compaction_end\",\n reason: \"overflow\",\n aborted: false,\n errorMessage:\n \"Context overflow recovery failed after one compact-and-retry attempt. Try /new or a larger-context model.\",\n });\n return false;\n }\n this.overflowRecoveryAttempted = true;\n this.dropTrailingErrorMessage();\n return this.runCompaction(\"overflow\", true);\n }\n\n private async checkThresholdCompaction(lastAssistant: AssistantMessage): Promise<boolean> {\n const settings = this.settings.compaction;\n if (!settings.enabled) return false;\n const contextWindow = this.agent.state.model.contextWindow || 0;\n if (contextWindow <= 0) return false;\n\n let contextTokens = lastAssistant.usage ? calculateContextTokens(lastAssistant.usage) : 0;\n if (contextTokens === 0) {\n const estimate = estimateContextTokens(this.agent.state.messages);\n if (estimate.lastUsageIndex === null) return false;\n contextTokens = estimate.tokens;\n }\n\n if (!shouldCompact(contextTokens, contextWindow, settings)) return false;\n return this.runCompaction(\"threshold\", false);\n }\n\n private async runCompaction(reason: CompactionReason, willRetry: boolean): Promise<boolean> {\n let started = false;\n try {\n const pathEntries = this.sessionStore.getBranch();\n const preparation = getOrThrow(prepareCompaction(pathEntries, this.settings.compaction));\n if (!preparation) return false;\n\n await this.emit({ type: \"compaction_start\", reason });\n started = true;\n this.compactionAbortController = new AbortController();\n const signal = this.compactionAbortController.signal;\n\n const result = getOrThrow(\n await compact(\n preparation,\n this.models.models,\n this.agent.state.model,\n undefined,\n signal,\n this.agent.state.thinkingLevel,\n ),\n );\n if (signal.aborted) {\n await this.emit({ type: \"compaction_end\", reason, aborted: true });\n return false;\n }\n\n const entryId = this.sessionStore.appendCompaction(\n result.summary,\n result.firstKeptEntryId,\n result.tokensBefore,\n result.details,\n );\n const context = this.sessionStore.buildSessionContext();\n this.agent.state.messages = context.messages;\n\n if (this.extensions?.hasHandlers(\"session_compact\")) {\n const entry = this.sessionStore.getEntry(entryId);\n if (entry?.type === \"compaction\") {\n await this.extensions.emit(\"session_compact\", {\n entry: entry as CompactionEntry,\n reason,\n });\n }\n }\n\n await this.emit({\n type: \"compaction_end\",\n reason,\n result: {\n summary: result.summary,\n firstKeptEntryId: result.firstKeptEntryId,\n tokensBefore: result.tokensBefore,\n },\n aborted: false,\n });\n\n if (willRetry) {\n this.dropTrailingErrorMessage();\n return true;\n }\n return this.agent.hasQueuedMessages();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"compaction failed\";\n if (started) {\n await this.emit({\n type: \"compaction_end\",\n reason,\n aborted: false,\n errorMessage:\n reason === \"overflow\"\n ? `Context overflow recovery failed: ${errorMessage}`\n : `Auto-compaction failed: ${errorMessage}`,\n });\n } else {\n log.logWarning(\"Compaction preparation failed\", errorMessage);\n }\n return false;\n } finally {\n this.compactionAbortController = undefined;\n }\n }\n\n private isRetryableError(message: AssistantMessage): boolean {\n if (message.stopReason !== \"error\" || !message.errorMessage) return false;\n return RETRYABLE_ERROR_PATTERN.test(message.errorMessage);\n }\n\n private async prepareRetry(message: AssistantMessage): Promise<boolean> {\n const settings = this.settings.retry;\n if (!settings.enabled) return false;\n\n this.retryAttempt++;\n if (this.retryAttempt > settings.maxRetries) {\n this.retryAttempt--;\n await this.emit({\n type: \"auto_retry_end\",\n success: false,\n attempt: this.retryAttempt,\n finalError: message.errorMessage,\n });\n this.retryAttempt = 0;\n return false;\n }\n\n const delayMs = settings.baseDelayMs * 2 ** (this.retryAttempt - 1);\n await this.emit({\n type: \"auto_retry_start\",\n attempt: this.retryAttempt,\n maxAttempts: settings.maxRetries,\n delayMs,\n errorMessage: message.errorMessage || \"Unknown error\",\n });\n\n this.dropTrailingErrorMessage();\n\n this.retryAbortController = new AbortController();\n try {\n await sleep(delayMs, this.retryAbortController.signal);\n } catch {\n const attempt = this.retryAttempt;\n this.retryAttempt = 0;\n await this.emit({\n type: \"auto_retry_end\",\n success: false,\n attempt,\n finalError: \"Retry cancelled\",\n });\n return false;\n } finally {\n this.retryAbortController = undefined;\n }\n return true;\n }\n\n private dropTrailingErrorMessage(): void {\n const messages = this.agent.state.messages;\n if (messages.length > 0 && messages[messages.length - 1].role === \"assistant\") {\n this.agent.state.messages = messages.slice(0, -1);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/harness/runner.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MikanAgentSession — mikan's agent run loop.\n *\n * Owns a pi-agent-core `Agent` and layers on the behaviors mikan needs for\n * long-lived chat conversations:\n *\n * - message persistence into the conversation's {@link SessionStore}\n * - automatic context compaction (threshold and overflow recovery), using\n * pi-agent-core's compaction pipeline over the session tree\n * - automatic retry with exponential backoff on transient provider errors\n * - extension hook dispatch ({@link ExtensionRegistry})\n *\n * Events mirror the agent's lifecycle events plus `compaction_start/_end`\n * and `auto_retry_start/_end`, preserving the event surface mikan's\n * platform adapters already render.\n */\nimport {\n Agent,\n calculateContextTokens,\n compact,\n convertToLlm,\n estimateContextTokens,\n getOrThrow,\n prepareCompaction,\n shouldCompact,\n type AgentEvent,\n type AgentMessage,\n type AgentTool,\n type CustomMessage,\n type ThinkingLevel,\n} from \"@earendil-works/pi-agent-core\";\nimport {\n isContextOverflow,\n type Api,\n type AssistantMessage,\n type ImageContent,\n type Model,\n type Models,\n type Usage,\n} from \"@earendil-works/pi-ai\";\nimport * as log from \"../log.js\";\nimport type { ExtensionRegistry } from \"./extensions/registry.js\";\nimport type { RunOrigin } from \"./extensions/types.js\";\nimport type { MikanModels } from \"./models.js\";\nimport { resolveHarnessSettings, type BudgetSettings, type HarnessSettings } from \"./settings.js\";\nimport type { SessionStore } from \"./session-store.js\";\nimport type { CompactionEntry, SubagentUsage } from \"./types.js\";\nimport { addSubagentUsage, copySubagentUsage, createEmptySubagentUsage } from \"./usage.js\";\n\nexport type CompactionReason = \"threshold\" | \"overflow\" | \"manual\";\n\n/** Running resource tally for the current `prompt()` call, matched against the budget. */\ninterface RunTally {\n usage: SubagentUsage;\n llmCalls: number;\n startedAt: number;\n}\n\ninterface CompactionResultSummary {\n summary: string;\n firstKeptEntryId: string;\n tokensBefore: number;\n}\n\nexport type HarnessEvent =\n | AgentEvent\n | { type: \"compaction_start\"; reason: CompactionReason }\n | {\n type: \"compaction_end\";\n reason: CompactionReason;\n result?: CompactionResultSummary;\n aborted: boolean;\n errorMessage?: string;\n }\n | {\n type: \"auto_retry_start\";\n attempt: number;\n maxAttempts: number;\n delayMs: number;\n errorMessage: string;\n }\n | { type: \"auto_retry_end\"; success: boolean; attempt: number; finalError?: string }\n | {\n type: \"budget_exceeded\";\n /** Which cap was hit, e.g. \"cost 2.01 USD > 2 USD limit\". */\n reason: string;\n tokens: number;\n costUsd: number;\n llmCalls: number;\n durationMs: number;\n };\n\nexport type HarnessEventListener = (event: HarnessEvent) => void | Promise<void>;\n\n/** Outcome of a `prompt()` call that an extension blocked before the model ran. */\nexport interface PromptBlockedOutcome {\n blocked: true;\n reason?: string;\n}\n\n// Transient provider failures worth retrying: overload/rate-limit responses,\n// 5xx statuses, and network/stream interruptions.\nconst RETRYABLE_ERROR_PATTERN =\n /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|http2 request did not get a response|timed? out|timeout|terminated|retry delay/i;\n\nfunction sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal.aborted) {\n reject(new Error(\"aborted\"));\n return;\n }\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(new Error(\"aborted\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nexport interface MikanAgentSessionOptions {\n systemPrompt: string;\n model: Model<Api>;\n thinkingLevel: ThinkingLevel;\n tools: AgentTool[];\n models: MikanModels;\n sessionStore: SessionStore;\n settings?: Parameters<typeof resolveHarnessSettings>[0];\n extensions?: ExtensionRegistry;\n}\n\nexport class MikanAgentSession {\n readonly agent: Agent;\n readonly sessionStore: SessionStore;\n private readonly models: MikanModels;\n private readonly settings: HarnessSettings;\n private readonly extensions: ExtensionRegistry | undefined;\n private listeners = new Set<HarnessEventListener>();\n private retryAttempt = 0;\n private overflowRecoveryAttempted = false;\n private retryAbortController: AbortController | undefined;\n private compactionAbortController: AbortController | undefined;\n private runActive = false;\n private tally: RunTally = {\n usage: createEmptySubagentUsage(),\n llmCalls: 0,\n startedAt: 0,\n };\n private runBudget: BudgetSettings = {};\n private budgetExceededReason: string | undefined;\n private runOrigin: RunOrigin | undefined;\n\n constructor(options: MikanAgentSessionOptions) {\n this.models = options.models;\n this.sessionStore = options.sessionStore;\n this.settings = resolveHarnessSettings(options.settings);\n this.extensions = options.extensions;\n\n const tools = [...options.tools, ...(options.extensions?.getContributedTools() ?? [])];\n this.agent = new Agent({\n initialState: {\n systemPrompt: options.systemPrompt,\n model: options.model,\n thinkingLevel: options.thinkingLevel,\n tools,\n },\n convertToLlm,\n transformContext: async (messages) => {\n if (!this.extensions?.hasHandlers(\"context\")) return messages;\n return this.extensions.emitContext({ messages, origin: this.runOrigin });\n },\n streamFn: (model, context, streamOptions) =>\n this.models.models.streamSimple(model, context, streamOptions),\n beforeToolCall: async ({ toolCall, args }) => {\n if (!this.extensions?.hasHandlers(\"tool_call\")) return undefined;\n const result = await this.extensions.emit(\"tool_call\", {\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n args,\n origin: this.runOrigin,\n });\n return result ?? undefined;\n },\n afterToolCall: async ({ toolCall, args, result, isError }) => {\n if (!this.extensions?.hasHandlers(\"tool_result\")) return undefined;\n // Chained extension rewrites (redaction, truncation) become a\n // pi-agent-core AfterToolCallResult override; undefined keeps the\n // executed result untouched.\n return this.extensions.emitToolResult({\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n args,\n content: result.content,\n details: result.details,\n isError,\n usage: (result as typeof result & { usage?: Usage }).usage,\n origin: this.runOrigin,\n });\n },\n });\n\n this.agent.subscribe(async (event) => {\n await this.handleAgentEvent(event);\n });\n }\n\n /** Conversation transcript currently held by the agent. */\n get messages(): AgentMessage[] {\n return this.agent.state.messages;\n }\n\n get model(): Model<Api> {\n return this.agent.state.model;\n }\n\n /** Whether this session currently owns a prompt, including pre-model hooks. */\n get isActiveRun(): boolean {\n return this.runActive;\n }\n\n /** Resource totals and terminal budget state from the most recent prompt. */\n getLastRunStats(): Readonly<{\n usage: SubagentUsage;\n tokens: number;\n costUsd: number;\n llmCalls: number;\n durationMs: number;\n budgetExceededReason?: string;\n }> {\n return {\n usage: copySubagentUsage(this.tally.usage),\n tokens: this.tally.usage.totalTokens,\n costUsd: this.tally.usage.cost.total,\n llmCalls: this.tally.llmCalls,\n durationMs: this.tally.startedAt > 0 ? Date.now() - this.tally.startedAt : 0,\n ...(this.budgetExceededReason ? { budgetExceededReason: this.budgetExceededReason } : {}),\n };\n }\n\n /**\n * Fold spend incurred outside this session's own LLM calls — e.g. subagent\n * runs launched by a tool during the current prompt — into the run tally\n * and enforce the run budget at the fold itself: a fold that lands over a\n * resource ceiling aborts the run now instead of waiting for a next\n * assistant message that may never come (and would be paid for). Complete\n * usage is folded; external runs are not this session's turns.\n */\n async foldExternalUsage(usage: SubagentUsage): Promise<void> {\n addSubagentUsage(this.tally.usage, usage);\n if (this.budgetExceededReason || !this.runActive) return;\n const reason = this.resourceOverBudgetReason();\n if (reason) await this.exceedBudget(reason);\n }\n\n subscribe(listener: HarnessEventListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /** Replace the agent transcript from the persisted session tree. */\n reloadFromSession(): number {\n const context = this.sessionStore.buildSessionContext();\n if (context.messages.length > 0) {\n this.agent.state.messages = context.messages;\n }\n return context.messages.length;\n }\n\n /**\n * Send a user prompt and run the agent loop to completion, including\n * automatic retries and compaction. Resolves when the turn (and any\n * recovery continuations) settles. Returns a blocked outcome when a\n * `before_agent_start` extension blocked the turn — the model was never\n * called and nothing was persisted.\n *\n * @param options.budget Per-run resource ceilings that override the session\n * defaults. Autonomous (event / trigger) runs should pass a budget so a\n * runaway loop is stopped even with no human watching.\n * @param options.origin Platform provenance forwarded to extension hooks.\n */\n async prompt(\n text: string,\n options?: { images?: ImageContent[]; budget?: BudgetSettings; origin?: RunOrigin },\n ): Promise<PromptBlockedOutcome | undefined> {\n if (this.runActive) {\n throw new Error(\"Agent is already processing a prompt\");\n }\n this.runActive = true;\n const runSystemPrompt = this.agent.state.systemPrompt;\n try {\n return await this.runPrompt(text, runSystemPrompt, options);\n } finally {\n this.agent.state.systemPrompt = runSystemPrompt;\n this.runActive = false;\n }\n }\n\n private async runPrompt(\n text: string,\n runSystemPrompt: string,\n options?: { images?: ImageContent[]; budget?: BudgetSettings; origin?: RunOrigin },\n ): Promise<PromptBlockedOutcome | undefined> {\n const model = this.agent.state.model;\n await this.ensureAuthConfigured(model);\n\n this.retryAttempt = 0;\n this.overflowRecoveryAttempted = false;\n this.runBudget = { ...this.settings.budget, ...options?.budget };\n this.budgetExceededReason = undefined;\n this.tally = {\n usage: createEmptySubagentUsage(),\n llmCalls: 0,\n startedAt: Date.now(),\n };\n this.runOrigin = options?.origin;\n\n // A previous turn may have ended over the threshold (for example after an\n // abort); compact before adding new context on top.\n const lastAssistant = this.findLastAssistantMessage();\n if (lastAssistant && lastAssistant.stopReason !== \"error\") {\n await this.checkThresholdCompaction(lastAssistant);\n }\n\n let promptText = text;\n let systemPrompt = runSystemPrompt;\n if (this.extensions?.hasHandlers(\"before_agent_start\")) {\n const result = await this.extensions.emitBeforeAgentStart({\n prompt: promptText,\n images: options?.images,\n systemPrompt,\n origin: this.runOrigin,\n });\n if (result?.block) {\n // Blocked before agent.prompt(): the user message never enters the\n // transcript or session store, so the blocked turn leaves no trace.\n log.logInfo(`Extension blocked turn${result.reason ? `: ${result.reason}` : \"\"}`);\n return { blocked: true, reason: result.reason };\n }\n if (result?.prompt !== undefined && result.prompt !== promptText) {\n log.logInfo(\n `Extension rewrote user prompt: ${promptText.length} → ${result.prompt.length} chars`,\n );\n promptText = result.prompt;\n }\n if (result?.systemPrompt && result.systemPrompt !== systemPrompt) {\n // An extension rewrote the system prompt for this turn. Log the new\n // size so the diagnostic in agent.ts (which logs the pre-hook prompt)\n // isn't mistaken for the final prompt sent to the model.\n log.logInfo(\n `Extension rewrote system prompt: ${systemPrompt.length} → ${result.systemPrompt.length} chars`,\n );\n systemPrompt = result.systemPrompt;\n this.agent.state.systemPrompt = systemPrompt;\n }\n }\n\n const userMessage: AgentMessage = {\n role: \"user\",\n content: [{ type: \"text\", text: promptText }, ...(options?.images ?? [])],\n timestamp: Date.now(),\n };\n\n await this.agent.prompt([userMessage]);\n while (await this.handlePostRun()) {\n await this.agent.continue();\n }\n\n // The turn settled on an error (retries exhausted or not retryable):\n // give monitoring extensions the final failure, once per turn.\n const settled = this.findLastAssistantMessage();\n if (settled?.stopReason === \"error\" && this.extensions?.hasHandlers(\"agent_error\")) {\n await this.extensions.emit(\"agent_error\", {\n errorMessage: settled.errorMessage || \"Unknown error\",\n origin: this.runOrigin,\n });\n }\n\n if (this.extensions?.hasHandlers(\"turn_end\")) {\n await this.extensions.emit(\"turn_end\", {\n messages: this.agent.state.messages,\n origin: this.runOrigin,\n });\n }\n return undefined;\n }\n\n /** Abort the active run, pending retry backoff, and in-flight compaction. */\n abort(): void {\n this.retryAbortController?.abort();\n this.compactionAbortController?.abort();\n this.agent.abort();\n }\n\n private async ensureAuthConfigured(model: Model<Api>): Promise<void> {\n const auth = await this.models.getAuth(model);\n if (!auth) {\n throw new Error(\n `No credentials for provider \"${model.provider}\". Set the provider API key environment variable or add it to auth.json.`,\n );\n }\n }\n\n private async emit(event: HarnessEvent): Promise<void> {\n for (const listener of this.listeners) {\n try {\n await listener(event);\n } catch (err) {\n log.logWarning(\n \"Harness event listener failed\",\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n }\n\n private async handleAgentEvent(event: AgentEvent): Promise<void> {\n if (event.type !== \"message_end\") {\n await this.emit(event);\n return;\n }\n\n let message = event.message;\n if (this.extensions?.hasHandlers(\"message_end\")) {\n const result = await this.extensions.emitMessageEnd({ message, origin: this.runOrigin });\n if (result?.message) {\n for (const key of Object.keys(message)) {\n delete (message as unknown as Record<string, unknown>)[key];\n }\n Object.assign(message, result.message);\n }\n }\n\n if (message.role === \"user\" || message.role === \"assistant\" || message.role === \"toolResult\") {\n this.sessionStore.appendMessage(message);\n } else if (message.role === \"custom\") {\n const custom = message as CustomMessage;\n this.sessionStore.appendCustomMessageEntry(\n custom.customType,\n custom.content,\n custom.display,\n custom.details,\n );\n }\n\n await this.emit({ ...event, message });\n\n if (message.role === \"assistant\") {\n this.recordUsage(message);\n await this.enforceBudget(message);\n if (message.stopReason !== \"error\") {\n this.overflowRecoveryAttempted = false;\n if (this.retryAttempt > 0) {\n await this.emit({ type: \"auto_retry_end\", success: true, attempt: this.retryAttempt });\n this.retryAttempt = 0;\n }\n }\n }\n }\n\n /** Fold one assistant completion's usage into the running per-run tally. */\n private recordUsage(message: AssistantMessage): void {\n this.tally.llmCalls += 1;\n const usage = message.usage;\n if (!usage) return;\n addSubagentUsage(this.tally.usage, usage);\n }\n\n /** Compare the tally against the run budget; abort the run when a cap is exceeded. */\n private async enforceBudget(message: AssistantMessage): Promise<void> {\n if (this.budgetExceededReason) return;\n const reason = this.overBudgetReason(message);\n if (!reason) return;\n await this.exceedBudget(reason);\n }\n\n /** Mark the run over budget, notify listeners and extensions, abort the agent. */\n private async exceedBudget(reason: string): Promise<void> {\n if (this.budgetExceededReason) return;\n this.budgetExceededReason = reason;\n await this.emit({\n type: \"budget_exceeded\",\n reason,\n tokens: this.tally.usage.totalTokens,\n costUsd: this.tally.usage.cost.total,\n llmCalls: this.tally.llmCalls,\n durationMs: Date.now() - this.tally.startedAt,\n });\n if (this.extensions?.hasHandlers(\"budget_exceeded\")) {\n await this.extensions.emit(\"budget_exceeded\", {\n reason,\n tokens: this.tally.usage.totalTokens,\n costUsd: this.tally.usage.cost.total,\n llmCalls: this.tally.llmCalls,\n durationMs: Date.now() - this.tally.startedAt,\n origin: this.runOrigin,\n });\n }\n log.logWarning(\"Run budget exceeded — aborting\", reason);\n this.agent.abort();\n }\n\n private overBudgetReason(message: AssistantMessage): string | undefined {\n const { maxLlmCalls } = this.runBudget;\n const needsAnotherCall =\n message.stopReason === \"error\" || message.content.some((part) => part.type === \"toolCall\");\n if (needsAnotherCall && maxLlmCalls !== undefined && this.tally.llmCalls >= maxLlmCalls) {\n return `${this.tally.llmCalls} LLM calls >= ${maxLlmCalls} limit`;\n }\n return this.resourceOverBudgetReason();\n }\n\n /** The message-independent budget checks, shared with external-spend folds. */\n private resourceOverBudgetReason(): string | undefined {\n const { maxTokens, maxCostUsd, maxDurationMs } = this.runBudget;\n if (maxTokens !== undefined && this.tally.usage.totalTokens >= maxTokens) {\n return `${this.tally.usage.totalTokens} tokens >= ${maxTokens} limit`;\n }\n if (maxCostUsd !== undefined && this.tally.usage.cost.total >= maxCostUsd) {\n return `cost ${this.tally.usage.cost.total.toFixed(2)} USD >= ${maxCostUsd} USD limit`;\n }\n if (maxDurationMs !== undefined && Date.now() - this.tally.startedAt >= maxDurationMs) {\n return `${Date.now() - this.tally.startedAt}ms >= ${maxDurationMs}ms limit`;\n }\n return undefined;\n }\n\n private findLastAssistantMessage(): AssistantMessage | undefined {\n const messages = this.agent.state.messages;\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i];\n if (message.role === \"assistant\") return message;\n }\n return undefined;\n }\n\n /** Decide what to do after a run settles. Returns true when the agent should continue. */\n private async handlePostRun(): Promise<boolean> {\n // A run stopped for going over budget must not be retried or compacted back\n // into another continuation — that would defeat the circuit breaker.\n if (this.budgetExceededReason) return false;\n\n const lastAssistant = this.findLastAssistantMessage();\n if (!lastAssistant) return false;\n\n if (lastAssistant.stopReason === \"error\") {\n const contextWindow = this.agent.state.model.contextWindow || 0;\n if (isContextOverflow(lastAssistant, contextWindow)) {\n return this.handleOverflow();\n }\n if (this.isRetryableError(lastAssistant)) {\n return this.prepareRetry(lastAssistant);\n }\n return false;\n }\n\n return this.checkThresholdCompaction(lastAssistant);\n }\n\n private async handleOverflow(): Promise<boolean> {\n if (this.overflowRecoveryAttempted) {\n await this.emit({\n type: \"compaction_end\",\n reason: \"overflow\",\n aborted: false,\n errorMessage:\n \"Context overflow recovery failed after one compact-and-retry attempt. Try /new or a larger-context model.\",\n });\n return false;\n }\n this.overflowRecoveryAttempted = true;\n this.dropTrailingErrorMessage();\n return this.runCompaction(\"overflow\", true);\n }\n\n private async checkThresholdCompaction(lastAssistant: AssistantMessage): Promise<boolean> {\n const settings = this.settings.compaction;\n if (!settings.enabled) return false;\n const contextWindow = this.agent.state.model.contextWindow || 0;\n if (contextWindow <= 0) return false;\n\n let contextTokens = lastAssistant.usage ? calculateContextTokens(lastAssistant.usage) : 0;\n if (contextTokens === 0) {\n const estimate = estimateContextTokens(this.agent.state.messages);\n if (estimate.lastUsageIndex === null) return false;\n contextTokens = estimate.tokens;\n }\n\n if (!shouldCompact(contextTokens, contextWindow, settings)) return false;\n return this.runCompaction(\"threshold\", false);\n }\n\n private async runCompaction(reason: CompactionReason, willRetry: boolean): Promise<boolean> {\n let started = false;\n try {\n const pathEntries = this.sessionStore.getBranch();\n const preparation = getOrThrow(prepareCompaction(pathEntries, this.settings.compaction));\n if (!preparation) return false;\n\n await this.emit({ type: \"compaction_start\", reason });\n started = true;\n this.compactionAbortController = new AbortController();\n const signal = this.compactionAbortController.signal;\n\n const result = getOrThrow(\n await compact(\n preparation,\n this.createCompactionModels(),\n this.agent.state.model,\n undefined,\n signal,\n this.agent.state.thinkingLevel,\n ),\n );\n if (signal.aborted) {\n await this.emit({ type: \"compaction_end\", reason, aborted: true });\n return false;\n }\n\n const entryId = this.sessionStore.appendCompaction(\n result.summary,\n result.firstKeptEntryId,\n result.tokensBefore,\n result.details,\n );\n const context = this.sessionStore.buildSessionContext();\n this.agent.state.messages = context.messages;\n\n if (this.extensions?.hasHandlers(\"session_compact\")) {\n const entry = this.sessionStore.getEntry(entryId);\n if (entry?.type === \"compaction\") {\n await this.extensions.emit(\"session_compact\", {\n entry: entry as CompactionEntry,\n reason,\n });\n }\n }\n\n await this.emit({\n type: \"compaction_end\",\n reason,\n result: {\n summary: result.summary,\n firstKeptEntryId: result.firstKeptEntryId,\n tokensBefore: result.tokensBefore,\n },\n aborted: false,\n });\n\n if (this.budgetExceededReason) return false;\n if (willRetry) {\n this.dropTrailingErrorMessage();\n return true;\n }\n return this.agent.hasQueuedMessages();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"compaction failed\";\n if (started) {\n await this.emit({\n type: \"compaction_end\",\n reason,\n aborted: false,\n errorMessage:\n reason === \"overflow\"\n ? `Context overflow recovery failed: ${errorMessage}`\n : `Auto-compaction failed: ${errorMessage}`,\n });\n } else {\n log.logWarning(\"Compaction preparation failed\", errorMessage);\n }\n return false;\n } finally {\n this.compactionAbortController = undefined;\n }\n }\n\n /**\n * Compaction can make one completion, or two when its cut splits a turn.\n * Intercept only those opaque upstream calls so each returned assistant\n * message is tallied exactly once. A call at maxLlmCalls is not started;\n * the cap is otherwise enforced before any post-compaction continuation.\n */\n private createCompactionModels(): Models {\n const models = this.models.models;\n return new Proxy(models, {\n get: (target, property) => {\n if (property === \"completeSimple\") {\n return async (...args: Parameters<Models[\"completeSimple\"]>) => {\n const maxLlmCalls = this.runBudget.maxLlmCalls;\n if (maxLlmCalls !== undefined && this.tally.llmCalls >= maxLlmCalls) {\n await this.exceedBudget(`${this.tally.llmCalls} LLM calls >= ${maxLlmCalls} limit`);\n throw new Error(\"Compaction LLM-call budget exhausted\");\n }\n\n const message = await target.completeSimple(...args);\n this.recordUsage(message);\n const reason = this.resourceOverBudgetReason();\n if (reason) await this.exceedBudget(reason);\n return message;\n };\n }\n const value: unknown = Reflect.get(target, property, target);\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n });\n }\n\n private isRetryableError(message: AssistantMessage): boolean {\n if (message.stopReason !== \"error\" || !message.errorMessage) return false;\n return RETRYABLE_ERROR_PATTERN.test(message.errorMessage);\n }\n\n private async prepareRetry(message: AssistantMessage): Promise<boolean> {\n const settings = this.settings.retry;\n if (!settings.enabled) return false;\n\n this.retryAttempt++;\n if (this.retryAttempt > settings.maxRetries) {\n this.retryAttempt--;\n await this.emit({\n type: \"auto_retry_end\",\n success: false,\n attempt: this.retryAttempt,\n finalError: message.errorMessage,\n });\n this.retryAttempt = 0;\n return false;\n }\n\n const delayMs = settings.baseDelayMs * 2 ** (this.retryAttempt - 1);\n await this.emit({\n type: \"auto_retry_start\",\n attempt: this.retryAttempt,\n maxAttempts: settings.maxRetries,\n delayMs,\n errorMessage: message.errorMessage || \"Unknown error\",\n });\n\n this.dropTrailingErrorMessage();\n\n this.retryAbortController = new AbortController();\n try {\n await sleep(delayMs, this.retryAbortController.signal);\n } catch {\n const attempt = this.retryAttempt;\n this.retryAttempt = 0;\n await this.emit({\n type: \"auto_retry_end\",\n success: false,\n attempt,\n finalError: \"Retry cancelled\",\n });\n return false;\n } finally {\n this.retryAbortController = undefined;\n }\n return true;\n }\n\n private dropTrailingErrorMessage(): void {\n const messages = this.agent.state.messages;\n if (messages.length > 0 && messages[messages.length - 1].role === \"assistant\") {\n this.agent.state.messages = messages.slice(0, -1);\n }\n }\n}\n"]}
@@ -1,12 +1,12 @@
1
1
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
2
2
  import type { ImageContent, TextContent } from "@earendil-works/pi-ai";
3
3
  import { type SessionContext, type SessionEntry, type SessionFileEntry, type SessionHeader } from "./types.js";
4
- /** Parse JSONL content tolerantly: malformed lines are skipped. */
4
+ /** Parse JSONL content tolerantly for compatibility with existing read-only callers. */
5
5
  export declare function parseSessionFileEntries(content: string): SessionFileEntry[];
6
6
  /**
7
- * Load a session file. Returns no entries when the file is missing or its
8
- * first parseable line is not a valid session header (mirrors the tolerant
9
- * read behavior mikan has relied on). Throws only on I/O errors.
7
+ * Load and validate a session file. Missing and whitespace-only files return
8
+ * no entries. A malformed final non-empty line is ignored as a crash tail;
9
+ * all other malformed JSON and invalid tree relationships throw.
10
10
  */
11
11
  export declare function loadSessionFileEntries(filePath: string): SessionFileEntry[];
12
12
  /**
@@ -22,6 +22,7 @@ export declare class SessionStore {
22
22
  private readonly sessionId;
23
23
  private header;
24
24
  private headerOnDisk;
25
+ private rewriteBeforeAppend;
25
26
  private entries;
26
27
  private byId;
27
28
  private leafId;
@@ -1 +1 @@
1
- {"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/harness/session-store.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAkBpB,mEAAmE;AACnE,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAmB3E;AAMD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAM3E;AAQD;;;;;;GAMG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgB;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,MAAM,CAAuB;IAErC,OAAO,eAiBN;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,CAW5D;IAED,kFAAkF;IAClF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,YAAY,CAUhF;IAED,oEAAoE;IACpE,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAgB,GAAG,YAAY,CAEjD;IAED,cAAc,IAAI,MAAM,GAAG,SAAS,CAEnC;IAED,WAAW,IAAI,OAAO,CAErB;IAED,MAAM,IAAI,MAAM,CAEf;IAED,wEAAwE;IACxE,SAAS,IAAI,aAAa,GAAG,IAAI,CAEhC;IAED,8EAA8E;IAC9E,YAAY,IAAI,MAAM,CAErB;IAED,SAAS,IAAI,MAAM,GAAG,IAAI,CAEzB;IAED,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAE7C;IAED,qEAAqE;IACrE,UAAU,IAAI,YAAY,EAAE,CAE3B;IAED,iDAAiD;IACjD,cAAc,IAAI,MAAM,GAAG,SAAS,CAMnC;IAED;;;OAGG;IACH,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CAUzC;IAED;;;OAGG;IACH,mBAAmB,IAAI,cAAc,CAEpC;IAED,kFAAkF;IAClF,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAE3C;IAED,0EAA0E;IAC1E,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAE5D;IAED,sEAAsE;IACtE,wBAAwB,CACtB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,EAChD,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB,MAAM,CAER;IAED,0CAA0C;IAC1C,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtC;IAED,8DAA8D;IAC9D,gBAAgB,CACd,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,OAAO,EACjB,QAAQ,CAAC,EAAE,OAAO,GACjB,MAAM,CASR;IAED,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,OAAO;CAkBhB"}
1
+ {"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/harness/session-store.ts"],"names":[],"mappings":"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"}
@@ -26,7 +26,7 @@ function generateEntryId(byId) {
26
26
  }
27
27
  return randomUUID();
28
28
  }
29
- /** Parse JSONL content tolerantly: malformed lines are skipped. */
29
+ /** Parse JSONL content tolerantly for compatibility with existing read-only callers. */
30
30
  export function parseSessionFileEntries(content) {
31
31
  const entries = [];
32
32
  for (const line of content.split("\n")) {
@@ -42,7 +42,7 @@ export function parseSessionFileEntries(content) {
42
42
  }
43
43
  }
44
44
  catch {
45
- // Skip malformed lines
45
+ // This compatibility parser is intentionally tolerant. SessionStore.open is not.
46
46
  }
47
47
  }
48
48
  return entries;
@@ -50,26 +50,120 @@ export function parseSessionFileEntries(content) {
50
50
  function isSessionHeader(entry) {
51
51
  return entry.type === "session" && typeof entry.id === "string";
52
52
  }
53
- /**
54
- * Load a session file. Returns no entries when the file is missing or its
55
- * first parseable line is not a valid session header (mirrors the tolerant
56
- * read behavior mikan has relied on). Throws only on I/O errors.
57
- */
58
- export function loadSessionFileEntries(filePath) {
53
+ function corrupted(filePath, detail) {
54
+ return new Error(`Session file is corrupted (${detail}): ${filePath}. Refusing to open for writing.`);
55
+ }
56
+ function parseSessionLine(line, filePath, lineNumber) {
57
+ let parsed;
58
+ try {
59
+ parsed = JSON.parse(line);
60
+ }
61
+ catch {
62
+ throw corrupted(filePath, `line ${lineNumber} is not valid JSON`);
63
+ }
64
+ if (!parsed ||
65
+ typeof parsed !== "object" ||
66
+ typeof parsed.type !== "string") {
67
+ throw corrupted(filePath, `line ${lineNumber} is not a session object`);
68
+ }
69
+ return parsed;
70
+ }
71
+ function validateSessionTree(filePath, fileEntries) {
72
+ const records = fileEntries.slice(1);
73
+ const allIds = new Set();
74
+ const treeEntries = new Map();
75
+ for (const [index, record] of records.entries()) {
76
+ const lineNumber = index + 2;
77
+ if (isSessionHeader(record))
78
+ throw corrupted(filePath, `line ${lineNumber} repeats the header`);
79
+ const entry = record;
80
+ if (typeof entry.id !== "string" || !entry.id) {
81
+ throw corrupted(filePath, `line ${lineNumber} has no entry id`);
82
+ }
83
+ if (allIds.has(entry.id))
84
+ throw corrupted(filePath, `duplicate entry id ${entry.id}`);
85
+ allIds.add(entry.id);
86
+ if (entry.type !== "leaf")
87
+ treeEntries.set(entry.id, entry);
88
+ }
89
+ for (const [index, record] of records.entries()) {
90
+ const lineNumber = index + 2;
91
+ const entry = record;
92
+ if (entry.parentId !== null && typeof entry.parentId !== "string") {
93
+ throw corrupted(filePath, `line ${lineNumber} has an invalid parentId`);
94
+ }
95
+ if (entry.parentId === entry.id)
96
+ throw corrupted(filePath, `entry ${entry.id} is its own parent`);
97
+ if (entry.parentId !== null && !treeEntries.has(entry.parentId)) {
98
+ throw corrupted(filePath, `entry ${entry.id} references missing parent ${entry.parentId}`);
99
+ }
100
+ if (entry.type === "leaf") {
101
+ if (entry.targetId !== null && typeof entry.targetId !== "string") {
102
+ throw corrupted(filePath, `leaf ${entry.id} has an invalid target`);
103
+ }
104
+ if (entry.targetId !== null && !treeEntries.has(entry.targetId)) {
105
+ throw corrupted(filePath, `leaf ${entry.id} references missing target ${entry.targetId}`);
106
+ }
107
+ }
108
+ }
109
+ for (const entry of treeEntries.values()) {
110
+ const seen = new Set();
111
+ let current = entry;
112
+ while (current) {
113
+ if (seen.has(current.id))
114
+ throw corrupted(filePath, `parent cycle includes entry ${current.id}`);
115
+ seen.add(current.id);
116
+ current = current.parentId === null ? undefined : treeEntries.get(current.parentId);
117
+ }
118
+ }
119
+ for (const entry of treeEntries.values()) {
120
+ if (entry.type !== "compaction")
121
+ continue;
122
+ if (typeof entry.firstKeptEntryId !== "string" || !treeEntries.has(entry.firstKeptEntryId)) {
123
+ throw corrupted(filePath, `compaction ${entry.id} references missing first kept entry`);
124
+ }
125
+ let ancestorId = entry.parentId;
126
+ while (ancestorId !== null && ancestorId !== entry.firstKeptEntryId) {
127
+ ancestorId = treeEntries.get(ancestorId)?.parentId ?? null;
128
+ }
129
+ if (ancestorId === null) {
130
+ throw corrupted(filePath, `compaction ${entry.id} first kept entry ${entry.firstKeptEntryId} is not on its branch`);
131
+ }
132
+ }
133
+ }
134
+ function loadValidatedSessionFile(filePath) {
59
135
  if (!existsSync(filePath))
60
- return [];
61
- const entries = parseSessionFileEntries(readFileSync(filePath, "utf-8"));
62
- if (entries.length === 0)
63
- return entries;
136
+ return { entries: [], discardedCrashTail: false };
137
+ const nonEmptyLines = readFileSync(filePath, "utf-8")
138
+ .split("\n")
139
+ .map((line, index) => ({ text: line.trim(), number: index + 1 }))
140
+ .filter(({ text }) => text.length > 0);
141
+ if (nonEmptyLines.length === 0)
142
+ return { entries: [], discardedCrashTail: false };
143
+ const entries = [];
144
+ let discardedCrashTail = false;
145
+ for (const [index, line] of nonEmptyLines.entries()) {
146
+ try {
147
+ entries.push(parseSessionLine(line.text, filePath, line.number));
148
+ }
149
+ catch (error) {
150
+ if (index !== nonEmptyLines.length - 1 || index === 0)
151
+ throw error;
152
+ discardedCrashTail = true;
153
+ }
154
+ }
64
155
  if (!isSessionHeader(entries[0]))
65
- return [];
66
- return entries;
156
+ throw corrupted(filePath, "first non-empty line is not a valid header");
157
+ validateSessionTree(filePath, entries);
158
+ return { entries, discardedCrashTail };
67
159
  }
68
- /** True when the file exists and holds any non-whitespace content on disk. */
69
- function hasSessionFileContent(filePath) {
70
- if (!existsSync(filePath))
71
- return false;
72
- return readFileSync(filePath, "utf-8").trim().length > 0;
160
+ /**
161
+ * Load and validate a session file. Missing and whitespace-only files return
162
+ * no entries. A malformed final non-empty line is ignored as a crash tail;
163
+ * all other malformed JSON and invalid tree relationships throw.
164
+ */
165
+ export function loadSessionFileEntries(filePath) {
166
+ return loadValidatedSessionFile(filePath).entries;
73
167
  }
74
168
  /**
75
169
  * Append-oriented session store over one v3 JSONL file.
@@ -79,13 +173,14 @@ function hasSessionFileContent(filePath) {
79
173
  * without a valid header gets its header materialized on the first append.
80
174
  */
81
175
  export class SessionStore {
82
- constructor(sessionFile, cwd, fileEntries) {
176
+ constructor(sessionFile, cwd, fileEntries, rewriteBeforeAppend = false) {
83
177
  this.entries = [];
84
178
  this.byId = new Map();
85
179
  this.leafId = null;
86
180
  this.sessionFile = sessionFile === null ? null : resolve(sessionFile);
87
181
  this.header = fileEntries.length > 0 && isSessionHeader(fileEntries[0]) ? fileEntries[0] : null;
88
182
  this.headerOnDisk = this.header !== null;
183
+ this.rewriteBeforeAppend = rewriteBeforeAppend;
89
184
  this.sessionId = this.header?.id ?? randomUUID();
90
185
  this.cwd = cwd;
91
186
  for (const entry of fileEntries) {
@@ -110,14 +205,10 @@ export class SessionStore {
110
205
  * @param cwdOverride Working directory override; defaults to the header cwd.
111
206
  */
112
207
  static open(path, cwdOverride) {
113
- const fileEntries = loadSessionFileEntries(path);
114
- if (fileEntries.length === 0 && hasSessionFileContent(path)) {
115
- throw new Error(`Session file is corrupted (no valid session header): ${path}. ` +
116
- `Refusing to open to avoid overwriting existing content.`);
117
- }
118
- const header = fileEntries.find(isSessionHeader);
208
+ const loaded = loadValidatedSessionFile(path);
209
+ const header = loaded.entries.find(isSessionHeader);
119
210
  const cwd = cwdOverride ?? header?.cwd ?? process.cwd();
120
- return new SessionStore(path, cwd, fileEntries);
211
+ return new SessionStore(path, cwd, loaded.entries, loaded.discardedCrashTail);
121
212
  }
122
213
  /** Create a new session file with a fresh header, replacing any existing file. */
123
214
  static create(path, cwd, options) {
@@ -237,7 +328,7 @@ export class SessionStore {
237
328
  persist(entry) {
238
329
  if (this.sessionFile === null)
239
330
  return;
240
- if (!this.headerOnDisk) {
331
+ if (!this.headerOnDisk || this.rewriteBeforeAppend) {
241
332
  this.header ??= {
242
333
  type: "session",
243
334
  version: CURRENT_SESSION_VERSION,
@@ -249,6 +340,7 @@ export class SessionStore {
249
340
  mkdirSync(dirname(this.sessionFile), { recursive: true });
250
341
  atomicWritePrivateFile(this.sessionFile, `${lines.join("\n")}\n`);
251
342
  this.headerOnDisk = true;
343
+ this.rewriteBeforeAppend = false;
252
344
  return;
253
345
  }
254
346
  appendFileSync(this.sessionFile, `${JSON.stringify(entry)}\n`);
@@ -1 +1 @@
1
- {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/harness/session-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * mikan-owned session storage.\n *\n * Sessions are append-only trees stored as JSONL files: a `session` header\n * line followed by entries that carry `id`/`parentId` links. The format is\n * the v3 layout mikan has always written, and entry shapes are structurally\n * identical to pi-agent-core's `SessionTreeEntry`, so pi-agent-core's\n * context-building and compaction helpers operate on these entries directly.\n *\n * The store is synchronous by design: every mikan call site (session scope\n * resolution, chat-history sync, session view, admin portal) reads and\n * writes sessions inside synchronous flows.\n */\nimport { randomUUID } from \"crypto\";\nimport { appendFileSync, existsSync, mkdirSync, readFileSync } from \"fs\";\nimport { dirname, resolve } from \"path\";\nimport { buildSessionContext as buildContextFromEntries } from \"@earendil-works/pi-agent-core\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport { atomicWritePrivateFile } from \"../utils/fs-atomic.js\";\nimport {\n CURRENT_SESSION_VERSION,\n type SessionContext,\n type SessionEntry,\n type SessionFileEntry,\n type SessionHeader,\n} from \"./types.js\";\n\n/** Distributive omit so each entry variant keeps its own fields. */\ntype PendingSessionEntry = SessionEntry extends infer TEntry\n ? TEntry extends SessionEntry\n ? Omit<TEntry, \"id\" | \"parentId\" | \"timestamp\">\n : never\n : never;\n\n/** Generate a unique short entry id (8 hex chars, collision-checked). */\nfunction generateEntryId(byId: Map<string, SessionEntry>): string {\n for (let i = 0; i < 100; i++) {\n const id = randomUUID().slice(0, 8);\n if (!byId.has(id)) return id;\n }\n return randomUUID();\n}\n\n/** Parse JSONL content tolerantly: malformed lines are skipped. */\nexport function parseSessionFileEntries(content: string): SessionFileEntry[] {\n const entries: SessionFileEntry[] = [];\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const parsed: unknown = JSON.parse(trimmed);\n if (\n parsed &&\n typeof parsed === \"object\" &&\n typeof (parsed as { type?: unknown }).type === \"string\"\n ) {\n entries.push(parsed as SessionFileEntry);\n }\n } catch {\n // Skip malformed lines\n }\n }\n return entries;\n}\n\nfunction isSessionHeader(entry: SessionFileEntry): entry is SessionHeader {\n return entry.type === \"session\" && typeof (entry as SessionHeader).id === \"string\";\n}\n\n/**\n * Load a session file. Returns no entries when the file is missing or its\n * first parseable line is not a valid session header (mirrors the tolerant\n * read behavior mikan has relied on). Throws only on I/O errors.\n */\nexport function loadSessionFileEntries(filePath: string): SessionFileEntry[] {\n if (!existsSync(filePath)) return [];\n const entries = parseSessionFileEntries(readFileSync(filePath, \"utf-8\"));\n if (entries.length === 0) return entries;\n if (!isSessionHeader(entries[0])) return [];\n return entries;\n}\n\n/** True when the file exists and holds any non-whitespace content on disk. */\nfunction hasSessionFileContent(filePath: string): boolean {\n if (!existsSync(filePath)) return false;\n return readFileSync(filePath, \"utf-8\").trim().length > 0;\n}\n\n/**\n * Append-oriented session store over one v3 JSONL file.\n *\n * Reading is tolerant (missing files and malformed lines yield an empty\n * session); appends persist immediately. A session opened from a file\n * without a valid header gets its header materialized on the first append.\n */\nexport class SessionStore {\n private readonly sessionFile: string | null;\n private readonly cwd: string;\n private readonly sessionId: string;\n private header: SessionHeader | null;\n private headerOnDisk: boolean;\n private entries: SessionEntry[] = [];\n private byId = new Map<string, SessionEntry>();\n private leafId: string | null = null;\n\n private constructor(sessionFile: string | null, cwd: string, fileEntries: SessionFileEntry[]) {\n this.sessionFile = sessionFile === null ? null : resolve(sessionFile);\n this.header = fileEntries.length > 0 && isSessionHeader(fileEntries[0]) ? fileEntries[0] : null;\n this.headerOnDisk = this.header !== null;\n this.sessionId = this.header?.id ?? randomUUID();\n this.cwd = cwd;\n for (const entry of fileEntries) {\n if (isSessionHeader(entry)) continue;\n if (entry.type === \"leaf\") {\n // Written by pi-agent-core JSONL sessions; mikan tracks the leaf implicitly.\n this.leafId = entry.targetId;\n continue;\n }\n this.entries.push(entry);\n this.byId.set(entry.id, entry);\n this.leafId = entry.id;\n }\n }\n\n /**\n * Open a session file. A missing or empty file starts an empty session\n * whose header is written on the first append. A file that has content but\n * no leading session header is treated as corrupted and throws, rather than\n * being silently overwritten on the next append (which would erase the\n * existing history). Callers on read paths already wrap this in try/catch.\n * @param cwdOverride Working directory override; defaults to the header cwd.\n */\n static open(path: string, cwdOverride?: string): SessionStore {\n const fileEntries = loadSessionFileEntries(path);\n if (fileEntries.length === 0 && hasSessionFileContent(path)) {\n throw new Error(\n `Session file is corrupted (no valid session header): ${path}. ` +\n `Refusing to open to avoid overwriting existing content.`,\n );\n }\n const header = fileEntries.find(isSessionHeader);\n const cwd = cwdOverride ?? header?.cwd ?? process.cwd();\n return new SessionStore(path, cwd, fileEntries);\n }\n\n /** Create a new session file with a fresh header, replacing any existing file. */\n static create(path: string, cwd: string, options?: { id?: string }): SessionStore {\n const header: SessionHeader = {\n type: \"session\",\n version: CURRENT_SESSION_VERSION,\n id: options?.id ?? randomUUID(),\n timestamp: new Date().toISOString(),\n cwd,\n };\n atomicWritePrivateFile(path, `${JSON.stringify(header)}\\n`);\n return new SessionStore(path, cwd, [header]);\n }\n\n /** Create an ephemeral session that never writes a session file. */\n static inMemory(cwd = process.cwd()): SessionStore {\n return new SessionStore(null, cwd, []);\n }\n\n getSessionFile(): string | undefined {\n return this.sessionFile ?? undefined;\n }\n\n isPersisted(): boolean {\n return this.sessionFile !== null;\n }\n\n getCwd(): string {\n return this.cwd;\n }\n\n /** Session header as read from disk, or null when the file had none. */\n getHeader(): SessionHeader | null {\n return this.header;\n }\n\n /** Stable session id: the header id, or a generated id for fresh sessions. */\n getSessionId(): string {\n return this.sessionId;\n }\n\n getLeafId(): string | null {\n return this.leafId;\n }\n\n getEntry(id: string): SessionEntry | undefined {\n return this.byId.get(id);\n }\n\n /** All session entries (header excluded). Returns a shallow copy. */\n getEntries(): SessionEntry[] {\n return [...this.entries];\n }\n\n /** Latest user-assigned session name, if any. */\n getSessionName(): string | undefined {\n for (let i = this.entries.length - 1; i >= 0; i--) {\n const entry = this.entries[i];\n if (entry.type === \"session_info\") return entry.name?.trim() || undefined;\n }\n return undefined;\n }\n\n /**\n * Walk from an entry to the root, returning entries in path order\n * (root first). Defaults to the current leaf.\n */\n getBranch(fromId?: string): SessionEntry[] {\n const path: SessionEntry[] = [];\n let currentId = fromId ?? this.leafId;\n while (currentId) {\n const entry = this.byId.get(currentId);\n if (!entry) break;\n path.push(entry);\n currentId = entry.parentId;\n }\n return path.toReversed();\n }\n\n /**\n * Build the LLM context (messages, thinking level, model) from the current\n * branch, resolving compaction and branch summaries along the path.\n */\n buildSessionContext(): SessionContext {\n return buildContextFromEntries(this.getBranch());\n }\n\n /** Append a chat message as a child of the current leaf. Returns the entry id. */\n appendMessage(message: AgentMessage): string {\n return this.appendEntry({ type: \"message\", message });\n }\n\n /** Append an extension/application data entry (never sent to the LLM). */\n appendCustomEntry(customType: string, data?: unknown): string {\n return this.appendEntry({ type: \"custom\", customType, data });\n }\n\n /** Append a custom message entry that participates in LLM context. */\n appendCustomMessageEntry(\n customType: string,\n content: string | (TextContent | ImageContent)[],\n display: boolean,\n details?: unknown,\n ): string {\n return this.appendEntry({ type: \"custom_message\", customType, content, display, details });\n }\n\n /** Record a user-visible session name. */\n appendSessionInfo(name: string): string {\n return this.appendEntry({ type: \"session_info\", name });\n }\n\n /** Persist a compaction summary produced for this session. */\n appendCompaction(\n summary: string,\n firstKeptEntryId: string,\n tokensBefore: number,\n details?: unknown,\n fromHook?: boolean,\n ): string {\n return this.appendEntry({\n type: \"compaction\",\n summary,\n firstKeptEntryId,\n tokensBefore,\n ...(details !== undefined ? { details } : {}),\n ...(fromHook !== undefined ? { fromHook } : {}),\n });\n }\n\n private appendEntry(partial: PendingSessionEntry): string {\n const entry = {\n ...partial,\n id: generateEntryId(this.byId),\n parentId: this.leafId,\n timestamp: new Date().toISOString(),\n } as SessionEntry;\n this.entries.push(entry);\n this.byId.set(entry.id, entry);\n this.leafId = entry.id;\n this.persist(entry);\n return entry.id;\n }\n\n private persist(entry: SessionEntry): void {\n if (this.sessionFile === null) return;\n if (!this.headerOnDisk) {\n this.header ??= {\n type: \"session\",\n version: CURRENT_SESSION_VERSION,\n id: this.sessionId,\n timestamp: new Date().toISOString(),\n cwd: this.cwd,\n };\n const lines = [this.header, ...this.entries].map((line) => JSON.stringify(line));\n mkdirSync(dirname(this.sessionFile), { recursive: true });\n atomicWritePrivateFile(this.sessionFile, `${lines.join(\"\\n\")}\\n`);\n this.headerOnDisk = true;\n return;\n }\n appendFileSync(this.sessionFile, `${JSON.stringify(entry)}\\n`);\n }\n}\n"]}
1
+ {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/harness/session-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * mikan-owned session storage.\n *\n * Sessions are append-only trees stored as JSONL files: a `session` header\n * line followed by entries that carry `id`/`parentId` links. The format is\n * the v3 layout mikan has always written, and entry shapes are structurally\n * identical to pi-agent-core's `SessionTreeEntry`, so pi-agent-core's\n * context-building and compaction helpers operate on these entries directly.\n *\n * The store is synchronous by design: every mikan call site (session scope\n * resolution, chat-history sync, session view, admin portal) reads and\n * writes sessions inside synchronous flows.\n */\nimport { randomUUID } from \"crypto\";\nimport { appendFileSync, existsSync, mkdirSync, readFileSync } from \"fs\";\nimport { dirname, resolve } from \"path\";\nimport { buildSessionContext as buildContextFromEntries } from \"@earendil-works/pi-agent-core\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport { atomicWritePrivateFile } from \"../utils/fs-atomic.js\";\nimport {\n CURRENT_SESSION_VERSION,\n type SessionContext,\n type SessionEntry,\n type SessionFileEntry,\n type SessionHeader,\n} from \"./types.js\";\n\n/** Distributive omit so each entry variant keeps its own fields. */\ntype PendingSessionEntry = SessionEntry extends infer TEntry\n ? TEntry extends SessionEntry\n ? Omit<TEntry, \"id\" | \"parentId\" | \"timestamp\">\n : never\n : never;\n\n/** Generate a unique short entry id (8 hex chars, collision-checked). */\nfunction generateEntryId(byId: Map<string, SessionEntry>): string {\n for (let i = 0; i < 100; i++) {\n const id = randomUUID().slice(0, 8);\n if (!byId.has(id)) return id;\n }\n return randomUUID();\n}\n\n/** Parse JSONL content tolerantly for compatibility with existing read-only callers. */\nexport function parseSessionFileEntries(content: string): SessionFileEntry[] {\n const entries: SessionFileEntry[] = [];\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const parsed: unknown = JSON.parse(trimmed);\n if (\n parsed &&\n typeof parsed === \"object\" &&\n typeof (parsed as { type?: unknown }).type === \"string\"\n ) {\n entries.push(parsed as SessionFileEntry);\n }\n } catch {\n // This compatibility parser is intentionally tolerant. SessionStore.open is not.\n }\n }\n return entries;\n}\n\nfunction isSessionHeader(entry: SessionFileEntry): entry is SessionHeader {\n return entry.type === \"session\" && typeof (entry as SessionHeader).id === \"string\";\n}\n\ntype LoadedSessionFile = {\n entries: SessionFileEntry[];\n discardedCrashTail: boolean;\n};\n\nfunction corrupted(filePath: string, detail: string): Error {\n return new Error(\n `Session file is corrupted (${detail}): ${filePath}. Refusing to open for writing.`,\n );\n}\n\nfunction parseSessionLine(line: string, filePath: string, lineNumber: number): SessionFileEntry {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n throw corrupted(filePath, `line ${lineNumber} is not valid JSON`);\n }\n if (\n !parsed ||\n typeof parsed !== \"object\" ||\n typeof (parsed as { type?: unknown }).type !== \"string\"\n ) {\n throw corrupted(filePath, `line ${lineNumber} is not a session object`);\n }\n return parsed as SessionFileEntry;\n}\n\nfunction validateSessionTree(filePath: string, fileEntries: SessionFileEntry[]): void {\n const records = fileEntries.slice(1);\n const allIds = new Set<string>();\n const treeEntries = new Map<string, SessionEntry>();\n\n for (const [index, record] of records.entries()) {\n const lineNumber = index + 2;\n if (isSessionHeader(record)) throw corrupted(filePath, `line ${lineNumber} repeats the header`);\n const entry = record as SessionEntry;\n if (typeof entry.id !== \"string\" || !entry.id) {\n throw corrupted(filePath, `line ${lineNumber} has no entry id`);\n }\n if (allIds.has(entry.id)) throw corrupted(filePath, `duplicate entry id ${entry.id}`);\n allIds.add(entry.id);\n if (entry.type !== \"leaf\") treeEntries.set(entry.id, entry);\n }\n\n for (const [index, record] of records.entries()) {\n const lineNumber = index + 2;\n const entry = record as SessionEntry;\n if (entry.parentId !== null && typeof entry.parentId !== \"string\") {\n throw corrupted(filePath, `line ${lineNumber} has an invalid parentId`);\n }\n if (entry.parentId === entry.id)\n throw corrupted(filePath, `entry ${entry.id} is its own parent`);\n if (entry.parentId !== null && !treeEntries.has(entry.parentId)) {\n throw corrupted(filePath, `entry ${entry.id} references missing parent ${entry.parentId}`);\n }\n if (entry.type === \"leaf\") {\n if (entry.targetId !== null && typeof entry.targetId !== \"string\") {\n throw corrupted(filePath, `leaf ${entry.id} has an invalid target`);\n }\n if (entry.targetId !== null && !treeEntries.has(entry.targetId)) {\n throw corrupted(filePath, `leaf ${entry.id} references missing target ${entry.targetId}`);\n }\n }\n }\n\n for (const entry of treeEntries.values()) {\n const seen = new Set<string>();\n let current: SessionEntry | undefined = entry;\n while (current) {\n if (seen.has(current.id))\n throw corrupted(filePath, `parent cycle includes entry ${current.id}`);\n seen.add(current.id);\n current = current.parentId === null ? undefined : treeEntries.get(current.parentId);\n }\n }\n\n for (const entry of treeEntries.values()) {\n if (entry.type !== \"compaction\") continue;\n if (typeof entry.firstKeptEntryId !== \"string\" || !treeEntries.has(entry.firstKeptEntryId)) {\n throw corrupted(filePath, `compaction ${entry.id} references missing first kept entry`);\n }\n let ancestorId = entry.parentId;\n while (ancestorId !== null && ancestorId !== entry.firstKeptEntryId) {\n ancestorId = treeEntries.get(ancestorId)?.parentId ?? null;\n }\n if (ancestorId === null) {\n throw corrupted(\n filePath,\n `compaction ${entry.id} first kept entry ${entry.firstKeptEntryId} is not on its branch`,\n );\n }\n }\n}\n\nfunction loadValidatedSessionFile(filePath: string): LoadedSessionFile {\n if (!existsSync(filePath)) return { entries: [], discardedCrashTail: false };\n const nonEmptyLines = readFileSync(filePath, \"utf-8\")\n .split(\"\\n\")\n .map((line, index) => ({ text: line.trim(), number: index + 1 }))\n .filter(({ text }) => text.length > 0);\n if (nonEmptyLines.length === 0) return { entries: [], discardedCrashTail: false };\n\n const entries: SessionFileEntry[] = [];\n let discardedCrashTail = false;\n for (const [index, line] of nonEmptyLines.entries()) {\n try {\n entries.push(parseSessionLine(line.text, filePath, line.number));\n } catch (error) {\n if (index !== nonEmptyLines.length - 1 || index === 0) throw error;\n discardedCrashTail = true;\n }\n }\n if (!isSessionHeader(entries[0]))\n throw corrupted(filePath, \"first non-empty line is not a valid header\");\n validateSessionTree(filePath, entries);\n return { entries, discardedCrashTail };\n}\n\n/**\n * Load and validate a session file. Missing and whitespace-only files return\n * no entries. A malformed final non-empty line is ignored as a crash tail;\n * all other malformed JSON and invalid tree relationships throw.\n */\nexport function loadSessionFileEntries(filePath: string): SessionFileEntry[] {\n return loadValidatedSessionFile(filePath).entries;\n}\n\n/**\n * Append-oriented session store over one v3 JSONL file.\n *\n * Reading is tolerant (missing files and malformed lines yield an empty\n * session); appends persist immediately. A session opened from a file\n * without a valid header gets its header materialized on the first append.\n */\nexport class SessionStore {\n private readonly sessionFile: string | null;\n private readonly cwd: string;\n private readonly sessionId: string;\n private header: SessionHeader | null;\n private headerOnDisk: boolean;\n private rewriteBeforeAppend: boolean;\n private entries: SessionEntry[] = [];\n private byId = new Map<string, SessionEntry>();\n private leafId: string | null = null;\n\n private constructor(\n sessionFile: string | null,\n cwd: string,\n fileEntries: SessionFileEntry[],\n rewriteBeforeAppend = false,\n ) {\n this.sessionFile = sessionFile === null ? null : resolve(sessionFile);\n this.header = fileEntries.length > 0 && isSessionHeader(fileEntries[0]) ? fileEntries[0] : null;\n this.headerOnDisk = this.header !== null;\n this.rewriteBeforeAppend = rewriteBeforeAppend;\n this.sessionId = this.header?.id ?? randomUUID();\n this.cwd = cwd;\n for (const entry of fileEntries) {\n if (isSessionHeader(entry)) continue;\n if (entry.type === \"leaf\") {\n // Written by pi-agent-core JSONL sessions; mikan tracks the leaf implicitly.\n this.leafId = entry.targetId;\n continue;\n }\n this.entries.push(entry);\n this.byId.set(entry.id, entry);\n this.leafId = entry.id;\n }\n }\n\n /**\n * Open a session file. A missing or empty file starts an empty session\n * whose header is written on the first append. A file that has content but\n * no leading session header is treated as corrupted and throws, rather than\n * being silently overwritten on the next append (which would erase the\n * existing history). Callers on read paths already wrap this in try/catch.\n * @param cwdOverride Working directory override; defaults to the header cwd.\n */\n static open(path: string, cwdOverride?: string): SessionStore {\n const loaded = loadValidatedSessionFile(path);\n const header = loaded.entries.find(isSessionHeader);\n const cwd = cwdOverride ?? header?.cwd ?? process.cwd();\n return new SessionStore(path, cwd, loaded.entries, loaded.discardedCrashTail);\n }\n\n /** Create a new session file with a fresh header, replacing any existing file. */\n static create(path: string, cwd: string, options?: { id?: string }): SessionStore {\n const header: SessionHeader = {\n type: \"session\",\n version: CURRENT_SESSION_VERSION,\n id: options?.id ?? randomUUID(),\n timestamp: new Date().toISOString(),\n cwd,\n };\n atomicWritePrivateFile(path, `${JSON.stringify(header)}\\n`);\n return new SessionStore(path, cwd, [header]);\n }\n\n /** Create an ephemeral session that never writes a session file. */\n static inMemory(cwd = process.cwd()): SessionStore {\n return new SessionStore(null, cwd, []);\n }\n\n getSessionFile(): string | undefined {\n return this.sessionFile ?? undefined;\n }\n\n isPersisted(): boolean {\n return this.sessionFile !== null;\n }\n\n getCwd(): string {\n return this.cwd;\n }\n\n /** Session header as read from disk, or null when the file had none. */\n getHeader(): SessionHeader | null {\n return this.header;\n }\n\n /** Stable session id: the header id, or a generated id for fresh sessions. */\n getSessionId(): string {\n return this.sessionId;\n }\n\n getLeafId(): string | null {\n return this.leafId;\n }\n\n getEntry(id: string): SessionEntry | undefined {\n return this.byId.get(id);\n }\n\n /** All session entries (header excluded). Returns a shallow copy. */\n getEntries(): SessionEntry[] {\n return [...this.entries];\n }\n\n /** Latest user-assigned session name, if any. */\n getSessionName(): string | undefined {\n for (let i = this.entries.length - 1; i >= 0; i--) {\n const entry = this.entries[i];\n if (entry.type === \"session_info\") return entry.name?.trim() || undefined;\n }\n return undefined;\n }\n\n /**\n * Walk from an entry to the root, returning entries in path order\n * (root first). Defaults to the current leaf.\n */\n getBranch(fromId?: string): SessionEntry[] {\n const path: SessionEntry[] = [];\n let currentId = fromId ?? this.leafId;\n while (currentId) {\n const entry = this.byId.get(currentId);\n if (!entry) break;\n path.push(entry);\n currentId = entry.parentId;\n }\n return path.toReversed();\n }\n\n /**\n * Build the LLM context (messages, thinking level, model) from the current\n * branch, resolving compaction and branch summaries along the path.\n */\n buildSessionContext(): SessionContext {\n return buildContextFromEntries(this.getBranch());\n }\n\n /** Append a chat message as a child of the current leaf. Returns the entry id. */\n appendMessage(message: AgentMessage): string {\n return this.appendEntry({ type: \"message\", message });\n }\n\n /** Append an extension/application data entry (never sent to the LLM). */\n appendCustomEntry(customType: string, data?: unknown): string {\n return this.appendEntry({ type: \"custom\", customType, data });\n }\n\n /** Append a custom message entry that participates in LLM context. */\n appendCustomMessageEntry(\n customType: string,\n content: string | (TextContent | ImageContent)[],\n display: boolean,\n details?: unknown,\n ): string {\n return this.appendEntry({ type: \"custom_message\", customType, content, display, details });\n }\n\n /** Record a user-visible session name. */\n appendSessionInfo(name: string): string {\n return this.appendEntry({ type: \"session_info\", name });\n }\n\n /** Persist a compaction summary produced for this session. */\n appendCompaction(\n summary: string,\n firstKeptEntryId: string,\n tokensBefore: number,\n details?: unknown,\n fromHook?: boolean,\n ): string {\n return this.appendEntry({\n type: \"compaction\",\n summary,\n firstKeptEntryId,\n tokensBefore,\n ...(details !== undefined ? { details } : {}),\n ...(fromHook !== undefined ? { fromHook } : {}),\n });\n }\n\n private appendEntry(partial: PendingSessionEntry): string {\n const entry = {\n ...partial,\n id: generateEntryId(this.byId),\n parentId: this.leafId,\n timestamp: new Date().toISOString(),\n } as SessionEntry;\n this.entries.push(entry);\n this.byId.set(entry.id, entry);\n this.leafId = entry.id;\n this.persist(entry);\n return entry.id;\n }\n\n private persist(entry: SessionEntry): void {\n if (this.sessionFile === null) return;\n if (!this.headerOnDisk || this.rewriteBeforeAppend) {\n this.header ??= {\n type: \"session\",\n version: CURRENT_SESSION_VERSION,\n id: this.sessionId,\n timestamp: new Date().toISOString(),\n cwd: this.cwd,\n };\n const lines = [this.header, ...this.entries].map((line) => JSON.stringify(line));\n mkdirSync(dirname(this.sessionFile), { recursive: true });\n atomicWritePrivateFile(this.sessionFile, `${lines.join(\"\\n\")}\\n`);\n this.headerOnDisk = true;\n this.rewriteBeforeAppend = false;\n return;\n }\n appendFileSync(this.sessionFile, `${JSON.stringify(entry)}\\n`);\n }\n}\n"]}