@tianshu-ai/tianshu 0.65.0 → 0.66.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/package.json +3 -3
  2. package/packages/server/dist/chat/compact-decision.d.ts +5 -0
  3. package/packages/server/dist/chat/compact-decision.d.ts.map +1 -1
  4. package/packages/server/dist/chat/compact-decision.js +1 -1
  5. package/packages/server/dist/chat/compact-decision.js.map +1 -1
  6. package/packages/server/dist/chat/handler.d.ts.map +1 -1
  7. package/packages/server/dist/chat/handler.js +146 -33
  8. package/packages/server/dist/chat/handler.js.map +1 -1
  9. package/packages/server/dist/chat/host-tools/recall-tools.d.ts.map +1 -1
  10. package/packages/server/dist/chat/host-tools/recall-tools.js +28 -40
  11. package/packages/server/dist/chat/host-tools/recall-tools.js.map +1 -1
  12. package/packages/server/dist/chat/progressive-history.d.ts.map +1 -1
  13. package/packages/server/dist/chat/progressive-history.js +8 -50
  14. package/packages/server/dist/chat/progressive-history.js.map +1 -1
  15. package/packages/server/dist/chat/real-user-turn.d.ts +21 -0
  16. package/packages/server/dist/chat/real-user-turn.d.ts.map +1 -0
  17. package/packages/server/dist/chat/real-user-turn.js +109 -0
  18. package/packages/server/dist/chat/real-user-turn.js.map +1 -0
  19. package/packages/server/dist/chat/session-chain.d.ts +19 -0
  20. package/packages/server/dist/chat/session-chain.d.ts.map +1 -0
  21. package/packages/server/dist/chat/session-chain.js +64 -0
  22. package/packages/server/dist/chat/session-chain.js.map +1 -0
  23. package/packages/server/dist/chat/sqlite-storage.d.ts +13 -1
  24. package/packages/server/dist/chat/sqlite-storage.d.ts.map +1 -1
  25. package/packages/server/dist/chat/sqlite-storage.js +31 -3
  26. package/packages/server/dist/chat/sqlite-storage.js.map +1 -1
  27. package/packages/server/dist/chat/structured-compaction.d.ts +45 -0
  28. package/packages/server/dist/chat/structured-compaction.d.ts.map +1 -0
  29. package/packages/server/dist/chat/structured-compaction.js +216 -0
  30. package/packages/server/dist/chat/structured-compaction.js.map +1 -0
  31. package/packages/server/dist/chat/stub-execution-env.d.ts.map +1 -1
  32. package/packages/server/dist/chat/stub-execution-env.js +6 -0
  33. package/packages/server/dist/chat/stub-execution-env.js.map +1 -1
  34. package/packages/server/dist/core/migrations/017-turn-number.d.ts +4 -0
  35. package/packages/server/dist/core/migrations/017-turn-number.d.ts.map +1 -0
  36. package/packages/server/dist/core/migrations/017-turn-number.js +113 -0
  37. package/packages/server/dist/core/migrations/017-turn-number.js.map +1 -0
  38. package/packages/server/dist/core/migrations/018-turn-number-fork-seed.d.ts +4 -0
  39. package/packages/server/dist/core/migrations/018-turn-number-fork-seed.d.ts.map +1 -0
  40. package/packages/server/dist/core/migrations/018-turn-number-fork-seed.js +100 -0
  41. package/packages/server/dist/core/migrations/018-turn-number-fork-seed.js.map +1 -0
  42. package/packages/server/dist/core/migrations/019-turn-number-chain-absolute.d.ts +4 -0
  43. package/packages/server/dist/core/migrations/019-turn-number-chain-absolute.d.ts.map +1 -0
  44. package/packages/server/dist/core/migrations/019-turn-number-chain-absolute.js +131 -0
  45. package/packages/server/dist/core/migrations/019-turn-number-chain-absolute.js.map +1 -0
  46. package/packages/server/dist/core/migrations/index.d.ts.map +1 -1
  47. package/packages/server/dist/core/migrations/index.js +6 -0
  48. package/packages/server/dist/core/migrations/index.js.map +1 -1
  49. package/packages/server/package.json +2 -2
  50. package/packages/web/dist/assets/{DataSourceConfigForm-B6Utzx30.js → DataSourceConfigForm-Z8nbAGTn.js} +1 -1
  51. package/packages/web/dist/assets/{bundle-web-CRB6FynO.js → bundle-web-BD-4HiDx.js} +1 -1
  52. package/packages/web/dist/assets/{index-7C5svtcO.js → index-sNjG7p-K.js} +5 -5
  53. package/packages/web/dist/assets/{react-force-graph-2d-BobL8wfd.js → react-force-graph-2d-DL58tQmv.js} +1 -1
  54. package/packages/web/dist/index.html +1 -1
  55. package/plugins/board/dist/server.js +243 -212
  56. package/plugins/board/dist/server.js.map +4 -4
  57. package/plugins/cron/dist/server.js +243 -212
  58. package/plugins/cron/dist/server.js.map +4 -4
  59. package/plugins/microsandbox/dist/server.js +243 -212
  60. package/plugins/microsandbox/dist/server.js.map +4 -4
  61. package/plugins/wiki/dist/server.d.ts.map +1 -1
  62. package/plugins/wiki/dist/server.js +258 -223
  63. package/plugins/wiki/dist/server.js.map +4 -4
  64. package/plugins/wiki/dist/sessions.d.ts +6 -1
  65. package/plugins/wiki/dist/sessions.d.ts.map +1 -1
  66. package/plugins/wiki/dist/sessions.js +12 -8
  67. package/plugins/wiki/dist/sessions.js.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tianshu-ai/tianshu",
3
- "version": "0.65.0",
3
+ "version": "0.66.0",
4
4
  "description": "An open AI agent platform with a sidecar browser. Built in public.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/tianshu-ai/tianshu",
@@ -69,8 +69,8 @@
69
69
  "dependencies": {
70
70
  "@andresaya/edge-tts": "^1.8.0",
71
71
  "@clack/prompts": "^1.5.1",
72
- "@earendil-works/pi-agent-core": "^0.85.1",
73
- "@earendil-works/pi-ai": "^0.85.1",
72
+ "@earendil-works/pi-agent-core": "^0.87.1",
73
+ "@earendil-works/pi-ai": "^0.87.1",
74
74
  "@modelcontextprotocol/sdk": "^1.29.0",
75
75
  "@tianshu-ai/plugin-sdk": "*",
76
76
  "better-sqlite3": "^13.0.3",
@@ -74,6 +74,11 @@ export interface AutoCompactDecision {
74
74
  */
75
75
  reason?: "compacted" | "below_threshold" | "nothing_to_compact" | "error";
76
76
  }
77
+ /** pi 0.80's `harness.compact()` message when `prepareCompaction`
78
+ * yields no cut point. Matched loosely (case-insensitive substring)
79
+ * so a future rephrasing of the harness error doesn't silently break
80
+ * the fallback path. */
81
+ export declare function isNothingToCompact(err: unknown): boolean;
77
82
  export declare function tryAutoCompact(args: {
78
83
  piSession: PiSession;
79
84
  harness: AgentHarness;
@@ -1 +1 @@
1
- {"version":3,"file":"compact-decision.d.ts","sourceRoot":"","sources":["../../src/chat/compact-decision.ts"],"names":[],"mappings":"AAsBA,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,SAAS,EAEd,KAAK,kBAAkB,EACvB,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,OAAO,IAAI,SAAS,EAC1B,MAAM,+BAA+B,CAAC;AAuBvC,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAoBT;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC,GAAG,OAAO,CAAC,OAAO,CAAC,CASnB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EACH,WAAW,GACX,iBAAiB,GACjB,oBAAoB,GACpB,OAAO,CAAC;CACb;AAWD,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,YAAY,CAAC;IACtB,gEAAgE;IAChE,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA6D/B"}
1
+ {"version":3,"file":"compact-decision.d.ts","sourceRoot":"","sources":["../../src/chat/compact-decision.ts"],"names":[],"mappings":"AAsBA,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,SAAS,EAEd,KAAK,kBAAkB,EACvB,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,OAAO,IAAI,SAAS,EAC1B,MAAM,+BAA+B,CAAC;AAuBvC,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAoBT;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC,GAAG,OAAO,CAAC,OAAO,CAAC,CASnB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EACH,WAAW,GACX,iBAAiB,GACjB,oBAAoB,GACpB,OAAO,CAAC;CACb;AAED;;;yBAGyB;AACzB,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAGxD;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,YAAY,CAAC;IACtB,gEAAgE;IAChE,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA6D/B"}
@@ -76,7 +76,7 @@ export async function branchStillOverWindow(args) {
76
76
  * yields no cut point. Matched loosely (case-insensitive substring)
77
77
  * so a future rephrasing of the harness error doesn't silently break
78
78
  * the fallback path. */
79
- function isNothingToCompact(err) {
79
+ export function isNothingToCompact(err) {
80
80
  const msg = err instanceof Error ? err.message : String(err);
81
81
  return /nothing to compact/i.test(msg);
82
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"compact-decision.js","sourceRoot":"","sources":["../../src/chat/compact-decision.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,EAAE;AACF,kEAAkE;AAClE,kEAAkE;AAClE,kEAAkE;AAClE,mEAAmE;AACnE,iEAAiE;AACjE,6DAA6D;AAC7D,0CAA0C;AAC1C,EAAE;AACF,2BAA2B;AAC3B,oDAAoD;AACpD,oEAAoE;AACpE,gEAAgE;AAChE,oCAAoC;AACpC,EAAE;AACF,cAAc;AACd,oEAAoE;AACpE,wCAAwC;AACxC,oEAAoE;AACpE,kEAAkE;AAElE,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACrB,aAAa,GAQd,MAAM,+BAA+B,CAAC;AA6BvC;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAA+B;IAE/B,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,2BAA2B,CAAC;IAC/D,IAAI,CAAC,QAAQ,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACnE,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7D,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,MAAM,KAAK,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAE9C,0EAA0E;IAC1E,qEAAqE;IACrE,+DAA+D;IAC/D,MAAM,UAAU,GAAI,QAA6D,CAAC,cAAc,CAAC;IACjG,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,GAAG,CAAC,IAAI,UAAU,GAAG,GAAG,EAAE,CAAC;QACzE,OAAO,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,aAAa,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;AACpE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAI3C;IACC,IAAI,CAAC;QACH,+DAA+D;QAC/D,4DAA4D;QAC5D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACzE,OAAO,mBAAmB,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAqDD;;;yBAGyB;AACzB,SAAS,kBAAkB,CAAC,GAAY;IACtC,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAQpC;IACC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IACnE,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CACV,wCAAwC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC3F,CAAC;QACF,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;IACD,IAAI,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QAC9D,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACzD,CAAC;IACD,mEAAmE;IACnE,0DAA0D;IAC1D,MAAM,cAAc,GAAG,MAAM;SAC1B,MAAM,CAAC,CAAC,CAAC,EAAoC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;SACrE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAA0B,CAAC,OAAgB,CAAC,CAAC;IAC5D,MAAM,YAAY,GAAG,qBAAqB,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC;IAClE,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QACrE,kEAAkE;QAClE,kEAAkE;QAClE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,8DAA8D;YAC9D,+DAA+D;YAC/D,MAAM,OAAO,GAAI,MAAM,CAAC,KAA2B,CAAC,IAAI,CAAC;YACzD,IAAI,OAAO,KAAK,kBAAkB,EAAE,CAAC;gBACnC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;YAC5D,CAAC;YACD,OAAO;gBACL,SAAS,EAAE,KAAK;gBAChB,MAAM,EAAE,OAAO;gBACf,KAAK,EAAG,MAAM,CAAC,KAAe,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;aAC/D,CAAC;QACJ,CAAC;QACD,yBAAyB;QACzB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACpE,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;QAC7B,OAAO;YACL,SAAS,EAAE,IAAI;YACf,YAAY;YACZ,eAAe,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;YACpD,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,WAAW;SACpB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,OAAO;YACf,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"compact-decision.js","sourceRoot":"","sources":["../../src/chat/compact-decision.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/chat/handler.ts"],"names":[],"mappings":"AAqDA,OAAO,EACL,mBAAmB,EACnB,cAAc,EAEd,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC9B,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,GAC9B,CAAC;AAGF,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACxB,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,yBAAyB,EACzB,6BAA6B,EAC7B,2BAA2B,EAC3B,4BAA4B,EAC5B,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAQL,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AA6B1B,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAOL,KAAK,WAAW,EAEjB,MAAM,eAAe,CAAC;AAWvB,OAAO,EAGL,KAAK,SAAS,EAEd,KAAK,cAAc,EAEpB,MAAM,kBAAkB,CAAC;AA6B1B,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,aAAa,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,CAAC;IAClB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC;IACtE,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAkQ7D;AAED,UAAU,aAAa;IACrB,GAAG,EAAE,aAAa,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,MAAM,EAAE,WAAW,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;4BAGwB;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,OAAO,eAAe,EAAE,WAAW,CAAC;IAC9C;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAguClE;AAsWD,wBAAgB,uBAAuB,CACrC,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAC3D,2BAA2B,CAAC,EAAE,MAAM,GACnC,MAAM,CAuCR;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,oBAAoB,EAAE,MAAM,GAAG,MAAM,EAAE,CAgB3E;AA0ED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CA0Ef;AAgRD,wBAAgB,cAAc,IAAI,WAAW,EAAE,CAkC9C;AAGD,YAAY,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/chat/handler.ts"],"names":[],"mappings":"AAqDA,OAAO,EACL,mBAAmB,EACnB,cAAc,EAGd,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC9B,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,GAC9B,CAAC;AAGF,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACxB,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,yBAAyB,EACzB,6BAA6B,EAC7B,2BAA2B,EAC3B,4BAA4B,EAC5B,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAQL,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AA6B1B,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAOL,KAAK,WAAW,EAEjB,MAAM,eAAe,CAAC;AAYvB,OAAO,EAGL,KAAK,SAAS,EAEd,KAAK,cAAc,EAEpB,MAAM,kBAAkB,CAAC;AA6B1B,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,aAAa,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,CAAC;IAClB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC;IACtE,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAkQ7D;AAED,UAAU,aAAa;IACrB,GAAG,EAAE,aAAa,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,MAAM,EAAE,WAAW,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;4BAGwB;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,OAAO,eAAe,EAAE,WAAW,CAAC;IAC9C;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAwvClE;AAsWD,wBAAgB,uBAAuB,CACrC,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAC3D,2BAA2B,CAAC,EAAE,MAAM,GACnC,MAAM,CAuCR;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,oBAAoB,EAAE,MAAM,GAAG,MAAM,EAAE,CAgB3E;AA0ED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CA0Ef;AA2XD,wBAAgB,cAAc,IAAI,WAAW,EAAE,CAkC9C;AAGD,YAAY,EAAE,WAAW,EAAE,CAAC"}
@@ -22,7 +22,7 @@ import fs from "node:fs";
22
22
  import path from "node:path";
23
23
  import { requireHomeDir } from "./require-home-dir.js";
24
24
  import { defaultSystemPrompt, } from "./system-prompt.js";
25
- import { shouldCompactBranch, tryAutoCompact, branchStillOverWindow, } from "./compact-decision.js";
25
+ import { shouldCompactBranch, tryAutoCompact, branchStillOverWindow, isNothingToCompact, } from "./compact-decision.js";
26
26
  // Re-export the compaction-decision API at the handler boundary so
27
27
  // callers that imported it from handler.ts (agent-loop.ts, tests)
28
28
  // keep working without churn.
@@ -54,6 +54,7 @@ import { getUserStore } from "../core/auth/user-store.js";
54
54
  import { resolveTenantRole } from "../core/auth/identity.js";
55
55
  import { buildHostTools, buildRecallHostTools, getCompactRef } from "./host-tools.js";
56
56
  import { progressiveHistoryTransform } from "./progressive-history.js";
57
+ import { installStructuredCompactionHook } from "./structured-compaction.js";
57
58
  import { toWire, } from "./ws-protocol.js";
58
59
  import { cacheGet, cachePut, fitToLimit, imageFitCacheKey, } from "./image-fit.js";
59
60
  const MAX_TURNS = 9999;
@@ -692,6 +693,21 @@ export async function runPrompt(args) {
692
693
  // compact, followUp, etc.) moved from harness onto AgentLane. Use
693
694
  // one "main" lane for the whole chat session.
694
695
  const lane = await harness.lane("main", piContext);
696
+ // Structured compaction: intercept pi's default free-form summary
697
+ // with a turn-numbered markdown block that lets the model use
698
+ // recall_range(A, B) against exact session turns. Falls through
699
+ // to pi's default summarizer on any hook failure; unsubscribed
700
+ // in the finally block below (see hookUnsubscribes).
701
+ const unsubStructuredCompaction = installStructuredCompactionHook({
702
+ harness,
703
+ session: { id: session.id },
704
+ db: ctx.db,
705
+ model: piModel,
706
+ apiKey,
707
+ onFallback: (reason) => {
708
+ log.warn(`structured_compaction fallback session=${session.id} reason=${reason}`);
709
+ },
710
+ });
695
711
  // Tool-result aging + progressive-history stubbing are now handled
696
712
  // inside `toProviderMessages` above (pi 0.85 removed the `context`
697
713
  // hook + `entryTransforms`); no separate unsubscribe needed.
@@ -1297,6 +1313,7 @@ export async function runPrompt(args) {
1297
1313
  }
1298
1314
  outstandingToolCalls.clear();
1299
1315
  unsubscribe();
1316
+ unsubStructuredCompaction();
1300
1317
  unregisterHarness();
1301
1318
  signal.removeEventListener("abort", onAbort);
1302
1319
  if (storage)
@@ -1409,7 +1426,12 @@ export async function runPrompt(args) {
1409
1426
  send({ type: "stream_end", message: lastWire });
1410
1427
  }
1411
1428
  else {
1412
- // Synthetic placeholder so the UI doesn't get stuck.
1429
+ // Synthetic placeholder so the UI doesn't get stuck. The id
1430
+ // prefix `msg_empty_` is the sentinel chat-store.ts's
1431
+ // stream_end handler matches on to *skip* appending this row
1432
+ // to the transcript (see `isSyntheticEmpty` there). Real
1433
+ // persisted rows use UUIDv7 ids (01a0…), so the prefix check
1434
+ // is unambiguous. Keep both sides in sync when renaming.
1413
1435
  send({
1414
1436
  type: "stream_end",
1415
1437
  message: toWire({
@@ -2064,45 +2086,122 @@ async function runManualCompact(args) {
2064
2086
  const modelInfo = (modelId ? findModel(ctx.config, modelId) : undefined) ??
2065
2087
  getDefaultModel(ctx.config);
2066
2088
  if (!modelInfo) {
2067
- send({
2068
- type: "stream_error",
2069
- reason: "no models configured",
2070
- });
2089
+ send({ type: "stream_error", reason: "no models configured" });
2071
2090
  return;
2072
2091
  }
2073
- const { messages, rows } = loadAgentHistoryForSession(ctx, session.id, {
2074
- api: modelInfo.api,
2075
- provider: modelInfo.providerId,
2076
- model: modelInfo.modelId,
2077
- });
2078
- if (messages.length === 0) {
2079
- send({
2080
- type: "stream_error",
2081
- reason: "nothing to compact (no messages yet)",
2082
- });
2092
+ // Route manual /compact through pi's harness.compact() so the
2093
+ // before_compaction hook fires (see structured-compaction.ts).
2094
+ // Historically /compact went through the legacy fork+summarise
2095
+ // path in compact.ts; that path never triggered pi hooks and
2096
+ // therefore skipped the turn-numbered structured summary.
2097
+ //
2098
+ // We build a minimal, single-purpose harness here — no tools,
2099
+ // no progressive-history, no active-harness registration — just
2100
+ // enough to call `lane.compact()`. See runPrompt for the full
2101
+ // harness setup used during real turns; this deliberately mirrors
2102
+ // only the pieces compact needs (piStorage / piSession / piContext
2103
+ // / harness / lane) so future pi API changes are easy to trace.
2104
+ const piStorage = new SqliteStorage(ctx.db, session.id);
2105
+ // Build a minimal SessionMetadata by hand rather than instantiating
2106
+ // SqliteSessionStorage (which needs a real userHome for image
2107
+ // inflation — not relevant to compaction). Only pi's storageVersion
2108
+ // + id + createdAt are consulted by StorageBackedSession; the rest
2109
+ // are optional and let pi thread parent-session pointers when they
2110
+ // exist.
2111
+ const sessionRow = ctx.db
2112
+ .prepare(`SELECT created_at, parent_id FROM sessions WHERE id = ?`)
2113
+ .get(session.id);
2114
+ if (!sessionRow) {
2115
+ send({ type: "stream_error", reason: `compact: session not found: ${session.id}` });
2083
2116
  return;
2084
2117
  }
2118
+ const piSessionMetadata = {
2119
+ id: session.id,
2120
+ createdAt: sessionRow.created_at,
2121
+ storageVersion: 2, // matches migration 015-pi-storage-v2
2122
+ parentSessionId: sessionRow.parent_id ?? undefined,
2123
+ };
2124
+ const piSession = new StorageBackedSession(piSessionMetadata, piStorage);
2125
+ const piModel = buildModel(modelInfo);
2126
+ const apiKey = resolveApiKey(modelInfo);
2127
+ const piContext = withAbortSignal(signal, BACKGROUND_CONTEXT);
2128
+ let harness;
2129
+ let unsubStructuredCompaction;
2130
+ const t0 = Date.now();
2085
2131
  try {
2086
- const result = await compactSession({
2087
- ctx,
2088
- userId,
2089
- oldSession: session,
2090
- pi: messages,
2091
- rows,
2092
- modelInfo,
2093
- signal,
2132
+ const created = await AgentHarness.create({
2133
+ session: piSession,
2134
+ tools: undefined,
2135
+ model: piModel,
2136
+ models: buildModels(piModel, apiKey, {
2137
+ resilience: ctx.config.models?.resilience,
2138
+ reResolveApiKey: () => resolveApiKey(modelInfo),
2139
+ additionalModels: listModels(ctx.config)
2140
+ .filter((m) => !(m.modelId === modelInfo.modelId && m.providerId === modelInfo.providerId))
2141
+ .map((m) => ({ model: buildModel(m), apiKey: resolveApiKey(m) })),
2142
+ }),
2143
+ }, piContext);
2144
+ harness = created.harness;
2145
+ const lane = await harness.lane("main", piContext);
2146
+ unsubStructuredCompaction = installStructuredCompactionHook({
2147
+ harness,
2148
+ session: { id: session.id },
2149
+ db: ctx.db,
2150
+ model: piModel,
2151
+ apiKey,
2152
+ onFallback: (reason) => {
2153
+ log.warn(`structured_compaction fallback session=${session.id} reason=${reason} (manual)`);
2154
+ },
2094
2155
  });
2156
+ // Snapshot pre-compaction message count so we can report
2157
+ // summarisedCount/keptCount without re-reading model context.
2158
+ const branchBefore = await piSession.findEntries(undefined, piContext);
2159
+ const msgsBefore = branchBefore.filter((e) => e.type === "message").length;
2160
+ if (msgsBefore === 0) {
2161
+ send({
2162
+ type: "stream_error",
2163
+ reason: "nothing to compact (no messages yet)",
2164
+ });
2165
+ return;
2166
+ }
2167
+ // pi 0.85+: lane.compact() returns Result<{compaction, run?}, err>.
2168
+ // NothingToCompact means the tail is already a compaction entry
2169
+ // — nothing new to fold in.
2170
+ const result = await lane.compact(undefined, piContext);
2171
+ if (!result.ok) {
2172
+ const errTag = result.error._tag;
2173
+ if (errTag === "NothingToCompact") {
2174
+ send({
2175
+ type: "stream_error",
2176
+ reason: "nothing to compact (nothing new since last compaction)",
2177
+ });
2178
+ return;
2179
+ }
2180
+ send({
2181
+ type: "stream_error",
2182
+ reason: `compact failed: ${result.error.message ?? String(result.error)}`,
2183
+ });
2184
+ return;
2185
+ }
2186
+ const branchAfter = await piSession.findEntries(undefined, piContext);
2187
+ const msgsAfter = branchAfter.filter((e) => e.type === "message").length;
2188
+ const summarisedCount = Math.max(0, msgsBefore - msgsAfter);
2189
+ const keptCount = msgsAfter;
2190
+ const durationMs = Date.now() - t0;
2191
+ // Manual /compact used to fork a new session; pi 0.87 writes the
2192
+ // compaction entry into the SAME session. Send old==new here —
2193
+ // chat-store.ts:698 already handles this shape (see the auto-
2194
+ // compact path which has done old==new since the pi 0.85 migration).
2095
2195
  send({
2096
2196
  type: "history_compacted",
2097
2197
  reason: "manual",
2098
- oldSessionId: result.oldSessionId,
2099
- newSessionId: result.newSession.id,
2100
- summarisedCount: result.summarisedCount,
2101
- keptCount: result.keptCount,
2102
- durationMs: result.durationMs,
2198
+ oldSessionId: session.id,
2199
+ newSessionId: session.id,
2200
+ summarisedCount,
2201
+ keptCount,
2202
+ durationMs,
2103
2203
  });
2104
- // Push a refreshed history so the UI swaps to the new session
2105
- // immediately (the fork ack + summary stub plus any kept tail).
2204
+ // Refresh so the UI drops any stale streaming placeholder.
2106
2205
  const page = listMessagesForUserPage(ctx, userId);
2107
2206
  send({
2108
2207
  type: "history",
@@ -2111,8 +2210,11 @@ async function runManualCompact(args) {
2111
2210
  });
2112
2211
  }
2113
2212
  catch (err) {
2114
- if (err instanceof CompactSkippedError) {
2115
- send({ type: "stream_error", reason: `compact skipped: ${err.message}` });
2213
+ if (isNothingToCompact(err)) {
2214
+ send({
2215
+ type: "stream_error",
2216
+ reason: "nothing to compact (nothing new since last compaction)",
2217
+ });
2116
2218
  return;
2117
2219
  }
2118
2220
  send({
@@ -2120,6 +2222,17 @@ async function runManualCompact(args) {
2120
2222
  reason: `compact failed: ${err instanceof Error ? err.message : String(err)}`,
2121
2223
  });
2122
2224
  }
2225
+ finally {
2226
+ unsubStructuredCompaction?.();
2227
+ if (harness) {
2228
+ try {
2229
+ await harness.close(piContext);
2230
+ }
2231
+ catch (closeErr) {
2232
+ log.warn(`runManualCompact: harness.close failed session=${session.id}: ${closeErr instanceof Error ? closeErr.message : String(closeErr)}`);
2233
+ }
2234
+ }
2235
+ }
2123
2236
  }
2124
2237
  /**
2125
2238
  * Load skills shipped with the host repo (under `<repoRoot>/skills/`).