@lemoncat7/dsh-knowledge 2.6.1 → 2.8.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 (66) hide show
  1. package/README.md +42 -0
  2. package/lib/api.d.ts.map +1 -1
  3. package/lib/api.js +13 -2
  4. package/lib/api.js.map +1 -1
  5. package/lib/client.d.ts +3 -0
  6. package/lib/client.d.ts.map +1 -1
  7. package/lib/client.js +102 -7
  8. package/lib/client.js.map +4 -4
  9. package/lib/extraction.d.ts.map +1 -1
  10. package/lib/extraction.js +1 -0
  11. package/lib/extraction.js.map +1 -1
  12. package/lib/index.d.ts.map +1 -1
  13. package/lib/index.js +16 -1
  14. package/lib/index.js.map +1 -1
  15. package/lib/local-provider.d.ts +2 -2
  16. package/lib/local-provider.d.ts.map +1 -1
  17. package/lib/local-provider.js +12 -5
  18. package/lib/local-provider.js.map +1 -1
  19. package/lib/note-recording.d.ts +21 -0
  20. package/lib/note-recording.d.ts.map +1 -0
  21. package/lib/note-recording.js +32 -0
  22. package/lib/note-recording.js.map +1 -0
  23. package/lib/note-reference-tools.js +3 -2
  24. package/lib/note-reference-tools.js.map +1 -1
  25. package/lib/note-tools.d.ts +3 -2
  26. package/lib/note-tools.d.ts.map +1 -1
  27. package/lib/note-tools.js +35 -12
  28. package/lib/note-tools.js.map +1 -1
  29. package/lib/notes/store.d.ts +5 -1
  30. package/lib/notes/store.d.ts.map +1 -1
  31. package/lib/notes/store.js +11 -2
  32. package/lib/notes/store.js.map +1 -1
  33. package/lib/provider.d.ts +2 -2
  34. package/lib/provider.d.ts.map +1 -1
  35. package/lib/remote-provider.d.ts +2 -2
  36. package/lib/remote-provider.d.ts.map +1 -1
  37. package/lib/remote-provider.js +6 -5
  38. package/lib/remote-provider.js.map +1 -1
  39. package/lib/tools.js +1 -1
  40. package/lib/tools.js.map +1 -1
  41. package/lib/web.js +1 -1
  42. package/lib/web.js.map +1 -1
  43. package/lib/writeback/control.d.ts +5 -0
  44. package/lib/writeback/control.d.ts.map +1 -0
  45. package/lib/writeback/control.js +39 -0
  46. package/lib/writeback/control.js.map +1 -0
  47. package/lib/writeback/live-control.d.ts +5 -0
  48. package/lib/writeback/live-control.d.ts.map +1 -0
  49. package/lib/writeback/live-control.js +63 -0
  50. package/lib/writeback/live-control.js.map +1 -0
  51. package/lib/writeback/queue.d.ts +27 -1
  52. package/lib/writeback/queue.d.ts.map +1 -1
  53. package/lib/writeback/queue.js +97 -7
  54. package/lib/writeback/queue.js.map +1 -1
  55. package/lib/writeback/status-client.d.ts +3 -0
  56. package/lib/writeback/status-client.d.ts.map +1 -1
  57. package/lib/writeback/status-client.js +30 -4
  58. package/lib/writeback/status-client.js.map +1 -1
  59. package/package.json +1 -1
  60. package/web/app.js +186 -26
  61. package/web/document-sync-ui.js +23 -0
  62. package/web/document-sync.js +43 -0
  63. package/web/styles.css +23 -0
  64. package/web/writeback-live.d.ts +1 -0
  65. package/web/writeback-live.js +52 -0
  66. package/web/writeback-workspace.js +76 -0
@@ -1 +1 @@
1
- {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/writeback/queue.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/writeback/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAmB1C,MAAM,QAAQ,GAAG,MAAM,CAAA;AACvB,MAAM,UAAU,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAE,CAAA;AACxH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;CAAG;AAE/C,iFAAiF;AACjF,MAAM,OAAO,cAAc;IA4BkB;IAAoI;IA3B9J,EAAE,CAAc;IAChB,KAAK,GAAG,UAAU,EAAE,CAAA;IAC7B,KAAK,CAA4B;IACjC,MAAM,CAA2B;IACjC,UAAU,CAA6B;IACvC,SAAS,CAAoB;IAC7B,MAAM,GAAG,KAAK,CAAA;IACd,OAAO,CAA2B;IACzB,SAAS,GAAG,IAAI,GAAG,EAAc,CAAA;IAElD,SAAS,CAAC,QAAoB;QAC5B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC5B,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA,CAAC,CAAC,CAAA;IAClD,CAAC;IAED,IAAI,QAAQ;QACV,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,IAAI,CAAC,KAAK,SAAS,CAAA;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,GAAG,EAA8B,CAAA;QACzF,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC,GAAG,EAAyB,CAAA;QAC/F,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,YAAY,IAAI,KAAK,CAAC,OAAO,EAAE,CAAA;IAClE,CAAC;IAEO,MAAM;QACZ,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC;gBAAC,QAAQ,EAAE,CAAA;YAAC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,IAAI,CAAC,IAAI,CAAC,kCAAkC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;YAAC,CAAC;QACnG,CAAC;IACH,CAAC;IACD,YAAY,IAAY,EAAmB,OAAiH,EAAmB,OAAkC,GAAG,EAAE,GAAE,CAAC;QAA9K,YAAO,GAAP,OAAO,CAA0G;QAAmB,SAAI,GAAJ,IAAI,CAAsC;QACvN,IAAI,IAAI,KAAK,UAAU;YAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QACnF,IAAI,CAAC,EAAE,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAA;QAChC,IAAI,IAAI,KAAK,UAAU;YAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAC/C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;wDAOuC,CAAC,CAAA;QACrD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QAC/B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC,GAAG,EAAwB,CAAA;YAC5F,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,CAAC;gBAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAA;YAC9J,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,CAAC;gBAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAA;YAC/H,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAA;YAC3D,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAAC,MAAM,KAAK,CAAA;QAAC,CAAC;IAC5E,CAAC;IAED,OAAO,CAAC,IAAmB;QACzB,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAA;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;QACrD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAA;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,wFAAwF,CAAC,CAAC,GAAG,EAAuB,CAAA;QAClJ,IAAI,KAAK,CAAC,KAAK,IAAI,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;QACtE,MAAM,IAAI,GAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;QAC7F,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,4GAA4G,CAAC;aAC1H,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QAC1H,IAAI,CAAC,IAAI,EAAE,CAAA;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAE,CAAA;IAC9C,CAAC;IAED,aAAa,CAAC,SAAiB,EAAE,SAAiB;QAChD,MAAM,IAAI,GAAoB,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;QACtG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,kGAAkG,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QAC5L,IAAI,CAAC,MAAM,EAAE,CAAA;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAE,CAAA;IAChC,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,qEAAqE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAmE,CAAA;QAC7K,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAA;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAoB,CAAA;QACpD,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,+HAA+H,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,CAAuC,CAAC,CAAC,CAAC,SAAS,CAAA;QACxQ,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAA;QACpG,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK,CAAC,GAAW;QACf,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAA;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAC,GAAG,CAAC,GAAG,CAA+B,CAAA;QACjH,IAAI,CAAC,GAAG;YAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAChF,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAE,CAAA;QACrD,IAAI,CAAC,GAAG,CAAC,OAAO;YAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC9E,MAAM,IAAI,GAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;QAC9F,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,0GAA0G,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;QAC1J,IAAI,CAAC,IAAI,EAAE,CAAA;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAE,CAAA;IAC1B,CAAC;IAED,IAAI,CAAC,SAAS,GAAG,EAAE,EAAE,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE;QACzC,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAA;QACnD,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QACzC,MAAM,KAAK,GAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,4CAA4C,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAuB,CAAC,KAAK,CAAA;QAC5H,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,oEAAoE,KAAK,oCAAoC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,CAA8F,CAAA;QACpQ,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAE,EAAE,CAAC,CAAC,EAAE,CAAA;IAC1L,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAA;QAC9C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QAC/B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAChC,IAAI,CAAC,OAAO;gBAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YACxE,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,oEAAoE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,EAAE,GAAG,CAAC,CAAA;YACzL,CAAC;iBAAM,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAC5E,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAAC,MAAM,KAAK,CAAA;QAAC,CAAC;QACzD,IAAI,IAAI,CAAC,SAAS,KAAK,GAAG;YAAE,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;QACvE,IAAI,CAAC,IAAI,EAAE,CAAA;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAE,CAAA;IAC1B,CAAC;IAEO,kBAAkB,CAAC,GAAW;QACpC,MAAM,IAAI,GAAoB,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,wBAAwB,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;QAC1G,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2FAA2F,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;IAC7I,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM;YAAE,OAAM;QACrC,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,CAAA;QAClD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAA;QACpB,IAAI,CAAC,IAAI,EAAE,CAAA;IACb,CAAC;IAED,IAAI,SAAS,KAAc,OAAO,IAAI,CAAC,UAAU,KAAK,SAAS,CAAA,CAAC,CAAC;IAEzD,IAAI;QACV,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,MAAM,EAAE,CAAA;QAC/B,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM;YAAE,OAAM;QACtC,0EAA0E;QAC1E,IAAI,CAAC,MAAM,GAAG,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;aACvF,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,+BAA+B,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA,CAAC,CAAC,CAAC,CAAA;IACzH,CAAC;IAEO,KAAK;QACX,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QAC/B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACtB,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,kDAAkD,CAAC,CAAC,GAAG,EAAwC,CAAA;YAC7H,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC;gBAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAAC,OAAO,SAAS,CAAA;YAAC,CAAC;YACnG,6EAA6E;YAC7E,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iFAAiF,CAAC,CAAC,GAAG,EAA8B;gBAAE,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;YAC3M,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,+EAA+E,CAAC;iBAC7F,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;YAC1F,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;8BAEJ,CAAC,CAAC,GAAG,CAAC,GAAG,CAA+B,CAAA;YAChE,IAAI,CAAC,GAAG,EAAE,CAAC;gBAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAAC,OAAO,SAAS,CAAA;YAAC,CAAC;YACtD,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,qDAAqD,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,QAAQ,CAAC,CAAA;YACtG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,8EAA8E,CAAC;iBAC5F,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;YAC/F,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YACtB,OAAO,EAAE,GAAG,GAAG,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAA;QAC/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAAC,MAAM,KAAK,CAAA;QAAC,CAAC;IAC3D,CAAC;IAEO,KAAK,CAAC,KAAK;QACjB,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;YACxB,IAAI,CAAC,GAAG;gBAAE,MAAK;YACf,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;YACxC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;YAC5B,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,UAAU,CAAA;YAC/B,IAAI,CAAC,MAAM,EAAE,CAAA;YACb,MAAM,WAAW,GAAG,GAAS,EAAE;gBAC7B,UAAU,CAAC,MAAM,CAAC,cAAc,EAAE,CAAA;gBAClC,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,kDAAkD,CAAC,CAAC,GAAG,EAAwC,CAAA;gBAC7H,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE;oBAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAA;gBAC1F,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,4DAA4D,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAA;YAC1H,CAAC,CAAA;YACD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;gBAC/B,IAAI,CAAC;oBACH,WAAW,EAAE,CAAA;oBACb,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,yDAAyD,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;gBACnH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;gBAAC,CAAC;YAC7C,CAAC,EAAE,MAAM,CAAC,CAAA;YACV,OAAO,CAAC,KAAK,EAAE,EAAE,CAAA;YACjB,IAAI,CAAC;gBACH,IAAI,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAmB,CAAC,CAAC,CAAC,SAAS,CAAA;gBACxE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAQ,CAAkB,EAAE;oBACzE,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI;oBAChB,IAAI,EAAE,KAAK,CAAC,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA,CAAC,CAAC;iBAC/J,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;gBACrB,WAAW,EAAE,CAAA;gBACb,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW;oBAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,CAAA;gBAC1E,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mFAAmF,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;YACxI,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC,GAAG,EAAuB,CAAA;gBACpG,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK;oBAAE,OAAM;gBACtC,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,4DAA4D,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC9F,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;oBACvC,SAAQ;gBACV,CAAC;gBACD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACtE,MAAM,OAAO,GAAG,KAAK,YAAY,iBAAiB,CAAA;gBAClD,MAAM,SAAS,GAAG,wIAAwI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBACxK,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAA;gBACvE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;gBACzF,MAAM,IAAI,GAAoB,KAAK;oBACjC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE;oBAC1I,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;gBAClF,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,uEAAuE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;YACzM,CAAC;oBAAS,CAAC;gBACT,aAAa,CAAC,OAAO,CAAC,CAAA;gBACtB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAA;gBAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;gBAC1B,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2DAA2D,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC5F,IAAI,CAAC,MAAM,EAAE,CAAA;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC,OAAO,CAAA;QACrC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,IAAI,CAAC,KAAK;YAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACzC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAA;QACpD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;QAC3E,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;CACF"}
@@ -12,9 +12,12 @@ export declare class WritebackStatusClient {
12
12
  private failures;
13
13
  private value;
14
14
  private readError;
15
+ private missing;
16
+ private invalidated;
15
17
  constructor(url: string, change: (value: WritebackStatus | undefined, retrying: boolean, readError?: string) => void, fetcher?: typeof fetch);
16
18
  setVisible(visible: boolean): void;
17
19
  refresh(): void;
20
+ invalidate(): void;
18
21
  retry(): void;
19
22
  private load;
20
23
  dispose(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"status-client.d.ts","sourceRoot":"","sources":["../../src/writeback/status-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,uFAAuF;AACvF,qBAAa,qBAAqB;IAWpB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAU,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAuF,OAAO,CAAC,QAAQ,CAAC,OAAO;IAVhL,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,OAAO,CAAO;IACtB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,SAAS,CAAoB;gBAGR,GAAG,EAAE,MAAM,EAAmB,MAAM,EAAE,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,EAAmB,OAAO,GAAE,OAAO,KAA8C;IAEvO,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAMlC,OAAO,IAAI,IAAI;IAKf,KAAK,IAAI,IAAI;YAQC,IAAI;IAsClB,OAAO,IAAI,IAAI;CAKhB"}
1
+ {"version":3,"file":"status-client.d.ts","sourceRoot":"","sources":["../../src/writeback/status-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,uFAAuF;AACvF,qBAAa,qBAAqB;IAapB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAU,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAuF,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZhL,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,OAAO,CAAO;IACtB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,WAAW,CAAQ;gBAGE,GAAG,EAAE,MAAM,EAAmB,MAAM,EAAE,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,EAAmB,OAAO,GAAE,OAAO,KAA8C;IAEvO,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAMlC,OAAO,IAAI,IAAI;IAKf,UAAU,IAAI,IAAI;IAMlB,KAAK,IAAI,IAAI;YAQC,IAAI;IAkDlB,OAAO,IAAI,IAAI;CAKhB"}
@@ -11,6 +11,8 @@ export class WritebackStatusClient {
11
11
  failures = 0;
12
12
  value;
13
13
  readError;
14
+ missing = false;
15
+ invalidated = false;
14
16
  // Browser fetch checks its Window receiver. Never store it as an unbound
15
17
  // instance method: this.fetcher() would supply the client as its receiver.
16
18
  constructor(url, change, fetcher = (...args) => globalThis.fetch(...args)) {
@@ -33,6 +35,14 @@ export class WritebackStatusClient {
33
35
  return;
34
36
  void this.load(false);
35
37
  }
38
+ invalidate() {
39
+ if (this.disposed || !this.visible)
40
+ return;
41
+ if (this.retrying || this.request && !this.request.signal.aborted)
42
+ this.invalidated = true;
43
+ else
44
+ this.refresh();
45
+ }
36
46
  retry() {
37
47
  if (this.disposed || this.retrying || !this.value?.retryable)
38
48
  return;
@@ -55,15 +65,27 @@ export class WritebackStatusClient {
55
65
  const body = await response.json();
56
66
  if (this.request !== controller || this.disposed)
57
67
  return;
58
- if (!response.ok && (retry || response.status !== 404))
68
+ if (!response.ok && (retry || response.status !== 404 || String(body.status) !== 'missing'))
59
69
  throw new Error(body.error ?? `状态请求失败(HTTP ${response.status})`);
60
- this.readError = undefined;
70
+ if (response.ok && !body.summary)
71
+ throw new Error('无效的回写状态响应');
61
72
  if (response.ok && body.summary) {
73
+ this.readError = undefined;
74
+ this.missing = false;
62
75
  this.value = body;
63
76
  this.failures = 0;
64
- delay = body.status === 'completed' ? 0 : body.status === 'failed' ? 15_000 : 1_500;
77
+ delay = body.status === 'completed' || body.status === 'cancelled' ? 0 : body.status === 'failed' ? 15_000 : 1_500;
65
78
  }
66
79
  else {
80
+ // A definitive missing response must invalidate a previously displayed state.
81
+ // Initial absence is normal before turn-stopping has persisted the snapshot.
82
+ if (this.value || this.missing) {
83
+ this.missing = true;
84
+ this.value = undefined;
85
+ this.readError = '当前客户端找不到这轮回写记录;旧等待状态已失效,请在回写任务中核对。';
86
+ }
87
+ else
88
+ this.readError = undefined;
67
89
  delay = ++this.failures <= 3 ? 1_500 : 60_000;
68
90
  }
69
91
  }
@@ -83,7 +105,11 @@ export class WritebackStatusClient {
83
105
  if (retry)
84
106
  this.retrying = false;
85
107
  this.change(this.value, this.retrying, this.readError);
86
- if (delay && this.visible)
108
+ if (this.invalidated && this.visible) {
109
+ this.invalidated = false;
110
+ this.refresh();
111
+ }
112
+ else if (delay && this.visible)
87
113
  this.timer = setTimeout(() => this.refresh(), delay);
88
114
  }
89
115
  }
@@ -1 +1 @@
1
- {"version":3,"file":"status-client.js","sourceRoot":"","sources":["../../src/writeback/status-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"status-client.js","sourceRoot":"","sources":["../../src/writeback/status-client.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lemoncat7/dsh-knowledge",
3
- "version": "2.6.1",
3
+ "version": "2.8.0",
4
4
  "description": "Local and remote knowledge bases for DeepSeek Harness, with scoped recall, controlled write-back, and a Web management console",
5
5
  "keywords": [
6
6
  "deepseek-harness",
package/web/app.js CHANGED
@@ -17,6 +17,9 @@ const { installHostThemeBridge } = themeModule
17
17
  const { actionButton, badge, createToastPresenter, element, interfaceIcon, paneToggleButton } = uiModule
18
18
  const { renderMenu: renderDocumentMenu, closeMenus: closeDocumentMenus } = documentActionsModule.createDocumentMenuPresenter(uiModule)
19
19
  const readModelCatalog = modelCatalogModule.createModelCatalogLoader()
20
+ const { createWritebackWorkspace } = await import(moduleUrl('writeback-workspace'))
21
+ const { createDocumentSync } = await import(moduleUrl('document-sync'))
22
+ let writebackWorkspace
20
23
  const TOKEN_KEY = 'dsh-knowledge.session-token'
21
24
  const TYPES = ['preference', 'fact', 'decision', 'procedure', 'lesson']
22
25
  const TYPE_LABELS = { preference: '偏好', fact: '事实', decision: '决策', procedure: '流程', lesson: '经验' }
@@ -32,7 +35,7 @@ const NOTE_MAX_FILE_SIZE = 64 * 1024 * 1024
32
35
  const pageParams = new URLSearchParams(location.search)
33
36
  const initialKnowledgeBaseId = pageParams.get('knowledgeBaseId')?.trim() || ''
34
37
  const initialDocumentId = pageParams.get('documentId')?.trim() || ''
35
- const initialView = pageParams.get('view') === 'notes' ? 'notes' : 'entries'
38
+ const initialView = ['notes', 'writeback'].includes(pageParams.get('view')) ? pageParams.get('view') : 'entries'
36
39
  const initialNoteId = pageParams.get('noteId')?.trim() || ''
37
40
  const mountContext = {
38
41
  sessionId: pageParams.get('sessionId')?.trim() || '',
@@ -350,7 +353,7 @@ function updateLoadingPhase(request, label, progress) {
350
353
  }
351
354
 
352
355
  async function saveBeforeNavigation() {
353
- if (state.view === 'notes' && state.notes.dirty) return saveNoteDocument()
356
+ if (state.view === 'notes' && (state.notes.dirty || state.notes.titleDirty || state.notes.renaming)) return saveNoteDocument()
354
357
  return saveBeforeLeavingDocument()
355
358
  }
356
359
 
@@ -794,6 +797,7 @@ async function saveDocumentEditor(workspace = activeDocumentWorkspace()) {
794
797
  if (!workspace) return false
795
798
  const editor = workspace.view.editor
796
799
  if (!editor || !editor.dirty) return true
800
+ if (editor.saving) return false
797
801
  if (!editor.isNew && editor.documentState !== 'open') {
798
802
  showToast('这篇文档已经结束并封存;请先重新打开。', 'error')
799
803
  return false
@@ -803,26 +807,32 @@ async function saveDocumentEditor(workspace = activeDocumentWorkspace()) {
803
807
  return false
804
808
  }
805
809
  editor.saveState = '正在保存…'
810
+ editor.saving = true
806
811
  updateEditorSaveState(editor.saveState)
807
812
  try {
808
813
  const draft = editorDraft(editor)
809
814
  const saved = editor.isNew
810
815
  ? await api('entries', { method: 'POST', body: { draft } })
811
- : await api(`entries/${encodeURIComponent(editor.id)}`, { method: 'PUT', body: { draft } })
816
+ : await api(`entries/${encodeURIComponent(editor.id)}`, { method: 'PUT', body: { draft, expectedVersion: editor.version } })
812
817
  editor.id = saved.id
813
818
  editor.isNew = false
814
- editor.dirty = false
819
+ editor.dirty = JSON.stringify(editorDraft(editor)) !== JSON.stringify(draft)
820
+ editor.version = saved.version
821
+ editor.documentState = saved.documentState
815
822
  editor.updatedAt = saved.updatedAt
816
- editor.saveState = '已保存'
823
+ editor.saveState = editor.dirty ? '未保存' : '已保存'
817
824
  workspace.view.documentId = saved.id
818
825
  updateEditorSaveState(editor.saveState)
819
826
  await reloadDocumentWorkspace(workspace)
820
- return true
827
+ return !editor.dirty
821
828
  } catch (error) {
822
829
  editor.saveState = '保存失败'
823
830
  updateEditorSaveState(editor.saveState)
824
831
  showToast(friendlyError(error), 'error')
832
+ if (error.status === 409) void openDocumentSyncConflict()
825
833
  return false
834
+ } finally {
835
+ editor.saving = false
826
836
  }
827
837
  }
828
838
 
@@ -950,6 +960,8 @@ async function loadTokens(signal) {
950
960
  }
951
961
 
952
962
  function renderShell() {
963
+ writebackWorkspace?.dispose()
964
+ writebackWorkspace = undefined
953
965
  closeDocumentMenus()
954
966
  releaseNoteEditors()
955
967
  captureScrollPosition()
@@ -960,10 +972,11 @@ function renderShell() {
960
972
  notes: ['笔记文档', '像本地目录一样整理笔记和资料,并按需关联到知识文档'],
961
973
  shares: ['已分享', '管理只读分享链接,也可以导入别人分享的笔记和目录'],
962
974
  candidates: ['待审核', '确认 AI 提取结果后再写入知识文档'],
975
+ writeback: ['回写任务', '查看本机队列,处理失败和阻塞的回写'],
963
976
  tokens: ['访问管理', '管理其他客户端连接中央知识库的权限'],
964
977
  }
965
978
  const [title, subtitle] = titles[state.view]
966
- const viewIndexes = { overview: '00', notes: '01', shares: '02', entries: '03', candidates: '04', bases: '05', tokens: '06' }
979
+ const viewIndexes = { overview: '00', notes: '01', shares: '02', entries: '03', candidates: '04', writeback: '05', bases: '06', tokens: '07' }
967
980
  const shell = element('div', {
968
981
  class: 'app-shell', 'data-menu-open': String(state.menuOpen),
969
982
  'data-view': state.view, 'data-loading': String(state.loading),
@@ -1004,6 +1017,7 @@ function renderShell() {
1004
1017
  app.replaceChildren(shell)
1005
1018
  applySidebarVisibility(shell, state.documentView.sidebarHidden)
1006
1019
  restoreScrollPosition(currentScrollState())
1020
+ renderDocumentSyncNotice()
1007
1021
  }
1008
1022
 
1009
1023
  function renderContextPaneToggle() {
@@ -1146,7 +1160,7 @@ function renderSidebar() {
1146
1160
  const pending = state.stats?.candidates.pending
1147
1161
  const navGroups = [
1148
1162
  ['笔记工作区', [['notes', '笔记文档'], ['shares', '已分享']]],
1149
- ['知识工作区', [['entries', '知识文档'], ['candidates', '待审核'], ['bases', '知识库与挂载']]],
1163
+ ['知识工作区', [['entries', '知识文档'], ['candidates', '待审核'], ['writeback', '回写任务'], ['bases', '知识库与挂载']]],
1150
1164
  ['连接', [['tokens', '访问管理']].filter(([id]) => id !== 'tokens' || !state.service.remote)],
1151
1165
  ].filter(([, items]) => items.length)
1152
1166
  let navIndex = 0
@@ -1172,6 +1186,10 @@ function renderSidebar() {
1172
1186
  function renderCurrentView() {
1173
1187
  if (state.loading) return loadingView(state.view, state.loadingPhase, state.loadingProgress)
1174
1188
  if (state.error) return errorView(state.error, () => navigate(state.view))
1189
+ if (state.view === 'writeback') {
1190
+ writebackWorkspace = createWritebackWorkspace({ element, actionButton, openConfirm, sessionId: mountContext.sessionId })
1191
+ return writebackWorkspace.root
1192
+ }
1175
1193
  if (state.view === 'overview') return renderOverview()
1176
1194
  if (state.view === 'bases') return renderKnowledgeBases()
1177
1195
  if (state.view === 'entries') return renderEntries()
@@ -1741,7 +1759,7 @@ function renderNoteEditor(workspace, editor, base) {
1741
1759
  const update = (key, value) => {
1742
1760
  editor[key] = value
1743
1761
  editor.dirty = true
1744
- editor.saveState = '未保存'
1762
+ editor.saveState = editor.saving ? '正在保存…' : '未保存'
1745
1763
  updateEditorSaveState(editor.saveState)
1746
1764
  }
1747
1765
  const title = element('input', {
@@ -2510,10 +2528,11 @@ function renderEditableNote(node) {
2510
2528
  element('h1', {
2511
2529
  class: 'notes-document-title', contenteditable: 'plaintext-only', spellcheck: 'false',
2512
2530
  'aria-label': `修改 ${node.name} 的标题`, title: '点击修改标题',
2531
+ onInput: () => { state.notes.titleDirty = true },
2513
2532
  onBlur: event => { void saveEditableNoteTitle(event.currentTarget, node) },
2514
2533
  onKeyDown: event => {
2515
2534
  if (event.key === 'Enter') { event.preventDefault(); event.currentTarget.blur() }
2516
- if (event.key === 'Escape') { event.preventDefault(); event.currentTarget.textContent = title; event.currentTarget.blur() }
2535
+ if (event.key === 'Escape') { event.preventDefault(); event.currentTarget.textContent = editableNoteTitle(state.notes.selectedNode || node); state.notes.titleDirty = false; event.currentTarget.blur() }
2517
2536
  },
2518
2537
  }, title),
2519
2538
  editor,
@@ -2536,21 +2555,25 @@ function editableNoteTitle(node) {
2536
2555
  }
2537
2556
 
2538
2557
  async function saveEditableNoteTitle(editor, node) {
2558
+ node = state.notes.selectedNode?.id === node.id ? state.notes.selectedNode : node
2539
2559
  const title = readPlainTextEditor(editor).replace(/\s+/g, ' ').trim()
2540
2560
  const name = node.kind === 'document' && title ? `${title.replace(/\.md$/i, '')}.md` : title
2541
2561
  if (!name) {
2542
2562
  editor.textContent = editableNoteTitle(node)
2563
+ state.notes.titleDirty = false
2543
2564
  showToast('标题不能为空。', 'error')
2544
2565
  return
2545
2566
  }
2546
2567
  if (name === node.name) {
2547
2568
  editor.textContent = editableNoteTitle(node)
2569
+ state.notes.titleDirty = false
2548
2570
  return
2549
2571
  }
2550
2572
  editor.setAttribute('contenteditable', 'false')
2573
+ state.notes.renaming = true
2551
2574
  try {
2552
- const updated = await api(`notes/${encodeURIComponent(node.id)}`, { method: 'PATCH', body: { name } })
2553
- if (state.notes.selectedNode?.id === node.id) state.notes.selectedNode = updated
2575
+ const updated = await api(`notes/${encodeURIComponent(node.id)}`, { method: 'PATCH', body: { name, expectedName: node.name } })
2576
+ if (state.notes.selectedNode?.id === node.id) { state.notes.selectedNode = updated; state.notes.titleDirty = false }
2554
2577
  editor.textContent = editableNoteTitle(updated)
2555
2578
  const breadcrumb = document.querySelector('.notes-document-toolbar .notes-breadcrumb strong')
2556
2579
  if (breadcrumb) breadcrumb.textContent = updated.name
@@ -2559,9 +2582,10 @@ async function saveEditableNoteTitle(editor, node) {
2559
2582
  if (treeName) treeName.textContent = updated.name
2560
2583
  showToast('标题已更新。')
2561
2584
  } catch (error) {
2562
- editor.textContent = editableNoteTitle(node)
2585
+ // Keep the user's title available to copy/retry, rather than silently losing it.
2563
2586
  showToast(friendlyError(error), 'error')
2564
2587
  } finally {
2588
+ state.notes.renaming = false
2565
2589
  if (editor.isConnected) editor.setAttribute('contenteditable', 'plaintext-only')
2566
2590
  }
2567
2591
  }
@@ -2685,11 +2709,11 @@ function releaseNoteEditors() {
2685
2709
  function syncNoteEditorChrome() {
2686
2710
  const status = document.querySelector('[data-note-save-state]')
2687
2711
  if (status) {
2688
- status.textContent = state.notes.dirty ? '未保存' : '已保存'
2712
+ status.textContent = state.notes.saving ? '正在保存…' : state.notes.dirty ? '未保存' : '已保存'
2689
2713
  status.dataset.dirty = String(state.notes.dirty)
2690
2714
  }
2691
2715
  const save = document.querySelector('[data-note-save]')
2692
- if (save) save.disabled = !state.notes.dirty
2716
+ if (save) save.disabled = state.notes.saving || !state.notes.dirty
2693
2717
  }
2694
2718
 
2695
2719
  function renderNoteDocumentBreadcrumb(node) {
@@ -2791,6 +2815,7 @@ function noteFilePreviewKind(node) {
2791
2815
  }
2792
2816
 
2793
2817
  async function selectNoteNode(node, options = {}) {
2818
+ if (state.notes.titleDirty || state.notes.renaming) return showToast('请先保存标题;若要放弃标题修改,请在标题中按 Escape。', 'error')
2794
2819
  if (state.notes.dirty && !await saveNoteDocument()) return
2795
2820
  const request = ++noteSelectionRequest
2796
2821
  releaseNoteAsset()
@@ -2813,10 +2838,12 @@ async function selectNoteNode(node, options = {}) {
2813
2838
  }
2814
2839
  await loadNoteChildren(node.id)
2815
2840
  } else if (node.editable) {
2816
- const blob = await binaryRequest(`notes/${encodeURIComponent(node.id)}/content`, { responseType: 'blob', accept: node.mediaType || 'text/plain' })
2817
- const content = await blob.text()
2841
+ const snapshot = await readNoteSnapshot(node.id)
2842
+ const content = snapshot.content
2818
2843
  if (request !== noteSelectionRequest || state.notes.selectedId !== node.id) return
2819
2844
  state.notes.content = content
2845
+ state.notes.selectedNode = snapshot.node
2846
+ state.notes.contentVersion = snapshot.node.version
2820
2847
  state.notes.draft = content
2821
2848
  state.notes.dirty = false
2822
2849
  state.notes.currentFolderId = node.parentId
@@ -2872,6 +2899,7 @@ function findCachedNote(id) {
2872
2899
  }
2873
2900
 
2874
2901
  async function openNoteRoot() {
2902
+ if (state.notes.titleDirty || state.notes.renaming) return showToast('请先保存标题;若要放弃标题修改,请在标题中按 Escape。', 'error')
2875
2903
  if (state.notes.dirty && !await saveNoteDocument()) return
2876
2904
  noteSelectionRequest += 1
2877
2905
  clearNoteSelection()
@@ -3266,15 +3294,22 @@ function showNoteImportResult(summary) {
3266
3294
  }
3267
3295
 
3268
3296
  async function saveNoteDocument() {
3297
+ if (state.notes.titleDirty || state.notes.renaming) { showToast('请先完成标题修改,或在标题中按 Escape 放弃。', 'error'); return false }
3269
3298
  const node = state.notes.selectedNode
3270
3299
  if (!node || !node.editable || !state.notes.dirty) return true
3300
+ if (state.notes.saving) return false
3301
+ state.notes.saving = true
3302
+ syncNoteEditorChrome()
3303
+ const submitted = state.notes.draft
3271
3304
  try {
3272
- const updated = await binaryRequest(`notes/${encodeURIComponent(node.id)}/content`, {
3273
- method: 'PUT', body: new Blob([state.notes.draft], { type: node.mediaType || 'text/plain' }), contentType: node.mediaType || 'text/plain',
3305
+ const updated = await binaryRequest(`notes/${encodeURIComponent(node.id)}/content?expectedVersion=${state.notes.contentVersion ?? node.version}`, {
3306
+ method: 'PUT', body: new Blob([submitted], { type: node.mediaType || 'text/plain' }), contentType: node.mediaType || 'text/plain',
3274
3307
  })
3308
+ if (state.notes.selectedNode?.id !== node.id) return false
3275
3309
  state.notes.selectedNode = updated
3276
- state.notes.content = state.notes.draft
3277
- state.notes.dirty = false
3310
+ state.notes.content = submitted
3311
+ state.notes.contentVersion = updated.version
3312
+ state.notes.dirty = state.notes.draft !== submitted
3278
3313
  await loadNoteChildren(node.parentId, true)
3279
3314
  const size = document.querySelector('[data-note-info="size"] > span')
3280
3315
  const updatedAt = document.querySelector('[data-note-info="updated"] > span')
@@ -3282,10 +3317,14 @@ async function saveNoteDocument() {
3282
3317
  if (updatedAt) updatedAt.textContent = formatDate(updated.updatedAt)
3283
3318
  syncNoteEditorChrome()
3284
3319
  showToast('文件已保存。')
3285
- return true
3320
+ return !state.notes.dirty
3286
3321
  } catch (error) {
3287
3322
  showToast(friendlyError(error), 'error')
3323
+ if (error.status === 409) void openDocumentSyncConflict()
3288
3324
  return false
3325
+ } finally {
3326
+ state.notes.saving = false
3327
+ syncNoteEditorChrome()
3289
3328
  }
3290
3329
  }
3291
3330
 
@@ -3358,12 +3397,12 @@ function renderHistoricalNotePreview(content, markdown) {
3358
3397
  return rendered
3359
3398
  }
3360
3399
 
3361
- function renderNoteHistoryDiff(historical, current) {
3400
+ function renderNoteHistoryDiff(historical, current, heading = '历史版本 → 当前版本') {
3362
3401
  const diff = window.DshKnowledgeReview.createLineDiff(historical, current)
3363
3402
  const lines = window.DshKnowledgeReview.compactDiffLines(diff.lines, 3)
3364
3403
  return element('section', { class: 'note-history-diff', 'aria-label': '历史版本与当前版本的逐行差异' },
3365
3404
  element('div', { class: 'note-history-diff-summary' },
3366
- element('strong', {}, '历史版本 → 当前版本'),
3405
+ element('strong', {}, heading),
3367
3406
  element('div', { class: 'diff-summary', 'aria-label': `新增 ${diff.additions} 行,删除 ${diff.deletions} 行` },
3368
3407
  element('span', { class: 'diff-stat additions' }, `+${diff.additions}`),
3369
3408
  element('span', { class: 'diff-stat deletions' }, `-${diff.deletions}`),
@@ -4465,12 +4504,133 @@ function friendlyError(error) {
4465
4504
  return error.message || '操作失败,请稍后重试。'
4466
4505
  }
4467
4506
 
4507
+ let documentSyncState = { key: '', status: '' }
4508
+ let syncConflictLoading = false
4509
+
4510
+ function currentSyncTarget() {
4511
+ if (state.loading || (AUTH_MODE !== 'same-origin' && !state.token)) return null
4512
+ const focused = () => !!document.activeElement?.closest('.note-editor, .notes-content, [role="dialog"]')
4513
+ if (state.view === 'notes') {
4514
+ const node = state.notes.selectedNode
4515
+ if (!node?.editable || state.notes.loadingNodeId) return null
4516
+ return { key: `note:${node.id}`, id: node.id, kind: 'note', identity: node,
4517
+ version: state.notes.contentVersion ?? node.version, updatedAt: node.updatedAt,
4518
+ busy: () => state.notes.dirty || state.notes.saving || state.notes.titleDirty || state.notes.renaming || focused() }
4519
+ }
4520
+ const workspace = activeDocumentWorkspace()
4521
+ const editor = workspace?.view.editor
4522
+ if (!editor?.id || editor.isNew || workspace.view.editorLoading) return null
4523
+ return { key: `${workspace.kind}:${editor.id}`, id: editor.id, kind: 'knowledge', identity: editor, workspace,
4524
+ version: editor.version, updatedAt: editor.updatedAt,
4525
+ busy: () => editor.dirty || editor.saving || focused() }
4526
+ }
4527
+
4528
+ async function readNoteSnapshot(id, signal) {
4529
+ const node = await api(`notes/${encodeURIComponent(id)}`, { signal })
4530
+ if (!node.editable) throw new Error('该文件不再支持文本编辑')
4531
+ const blob = await binaryRequest(`notes/${encodeURIComponent(id)}/versions/${node.version}/content`, { responseType: 'blob', signal })
4532
+ return { node, content: await blob.text() }
4533
+ }
4534
+
4535
+ async function readSyncSnapshot(target, signal) {
4536
+ if (target.kind === 'note') return readNoteSnapshot(target.id, signal)
4537
+ const [entry, noteReferences] = await Promise.all([
4538
+ api(`entries/${encodeURIComponent(target.id)}`, { signal }),
4539
+ api(`entries/${encodeURIComponent(target.id)}/note-references`, { signal }),
4540
+ ])
4541
+ return { entry, noteReferences }
4542
+ }
4543
+
4544
+ function applySyncSnapshot(target, snapshot, draft) {
4545
+ if (target.kind === 'note') {
4546
+ Object.assign(state.notes, { selectedNode: snapshot.node, content: snapshot.content, contentVersion: snapshot.node.version,
4547
+ draft: draft?.content ?? snapshot.content, dirty: draft !== undefined && draft.content !== snapshot.content })
4548
+ for (const [key, nodes] of state.notes.children) state.notes.children.set(key, nodes.map(node => node.id === target.id ? snapshot.node : node))
4549
+ } else {
4550
+ const entry = snapshot.entry
4551
+ Object.assign(target.identity, entry, { noteReferences: snapshot.noteReferences, tagsText: entry.tags.join(', '), dirty: !!draft,
4552
+ ...(draft ? { title: draft.title, body: draft.content } : {}), saveState: draft ? '未保存' : '已同步' })
4553
+ const items = documentWorkspaceDocuments(target.workspace)
4554
+ setDocumentWorkspaceDocuments(target.workspace, items.map(item => item.id === target.id ? { ...item, title: target.identity.title, version: entry.version, updatedAt: entry.updatedAt } : item))
4555
+ }
4556
+ documentSyncState = { key: target.key, status: draft ? '' : 'synced' }
4557
+ renderShell()
4558
+ }
4559
+
4560
+ function renderDocumentSyncNotice() {
4561
+ const target = currentSyncTarget()
4562
+ const status = target?.key === documentSyncState.key ? documentSyncState.status : ''
4563
+ const host = document.querySelector('.note-editor-toolbar, .notes-document-toolbar')
4564
+ let notice = host?.querySelector('.document-sync-notice')
4565
+ if (!target || !status) { notice?.remove(); return }
4566
+ const labels = { changed: '文档有新版本,当前内容已保留', missing: '文档已删除或不可访问,草稿仍保留', offline: '同步暂不可用,将自动重试', synced: '已同步最新版本' }
4567
+ if (notice?.dataset.status === status) return
4568
+ if (!notice) { notice = element('div', { class: 'document-sync-notice' }); host?.append(notice) }
4569
+ notice.dataset.status = status
4570
+ notice.replaceChildren(element('span', { role: 'status' }, labels[status] || ''))
4571
+ if (status === 'changed') notice.append(actionButton('查看并处理', () => { void openDocumentSyncConflict() }, 'small'))
4572
+ }
4573
+
4574
+ async function openDocumentSyncConflict() {
4575
+ const target = currentSyncTarget()
4576
+ if (!target || syncConflictLoading) return
4577
+ if (target.kind === 'note' && (state.notes.titleDirty || state.notes.renaming)) return showToast('标题修改尚未保存,请先复制保留;在标题中按 Escape 可恢复原标题,再处理文档新版本。', 'error')
4578
+ syncConflictLoading = true
4579
+ try {
4580
+ const snapshot = await readSyncSnapshot(target, AbortSignal.timeout(10000))
4581
+ if (currentSyncTarget()?.identity !== target.identity) return
4582
+ const local = target.kind === 'note' ? { title: state.notes.selectedNode.name, content: state.notes.draft }
4583
+ : { title: target.identity.title, content: target.identity.body }
4584
+ const remote = target.kind === 'note' ? { title: snapshot.node.name, content: snapshot.content }
4585
+ : { title: snapshot.entry.title, content: snapshot.entry.body }
4586
+ const { openSyncConflict } = await import(moduleUrl('document-sync-ui'))
4587
+ const stillCurrent = () => {
4588
+ if (currentSyncTarget()?.identity !== target.identity) throw new Error('当前文档已切换,请重新打开差异')
4589
+ if ((target.kind === 'note' ? state.notes.draft : target.identity.body) !== local.content
4590
+ || (target.kind === 'knowledge' && target.identity.title !== local.title)) throw new Error('本地草稿已有新修改,请关闭后重新查看差异')
4591
+ }
4592
+ openSyncConflict({ element, actionButton, openModal, openConfirm, renderDiff: renderNoteHistoryDiff, local, remote,
4593
+ allowTitle: target.kind === 'knowledge',
4594
+ canEdit: target.kind === 'note' || (snapshot.entry.documentState === 'open' && snapshot.entry.status === 'active' && !documentWorkspaceReadOnly(target.workspace)),
4595
+ apply: draft => { stillCurrent(); applySyncSnapshot(target, snapshot, draft) },
4596
+ useRemote: () => { stillCurrent(); applySyncSnapshot(target, snapshot) },
4597
+ })
4598
+ } catch (error) { showToast(friendlyError(error), 'error') }
4599
+ finally { syncConflictLoading = false }
4600
+ }
4601
+
4602
+ const documentSync = createDocumentSync({
4603
+ current: currentSyncTarget,
4604
+ check: (target, signal) => api(target.kind === 'note' ? `notes/${encodeURIComponent(target.id)}` : `entries/${encodeURIComponent(target.id)}/revision`, { signal }),
4605
+ refresh: async (target, signal, valid) => {
4606
+ const snapshot = await readSyncSnapshot(target, signal)
4607
+ if (valid()) applySyncSnapshot(target, snapshot)
4608
+ else if (currentSyncTarget()?.identity === target.identity) {
4609
+ documentSyncState = { key: target.key, status: 'changed' }
4610
+ renderDocumentSyncNotice()
4611
+ }
4612
+ },
4613
+ notify: (target, status) => {
4614
+ if (status === 'current') {
4615
+ if (documentSyncState.key !== target.key || documentSyncState.status === 'synced') return
4616
+ status = ''
4617
+ }
4618
+ documentSyncState = { key: target.key, status }
4619
+ renderDocumentSyncNotice()
4620
+ },
4621
+ })
4622
+ document.addEventListener('visibilitychange', () => { if (document.hidden) documentSync.pause(); else documentSync.wake() })
4623
+ window.addEventListener('focus', () => documentSync.wake())
4624
+ window.addEventListener('online', () => documentSync.wake())
4625
+ window.addEventListener('pagehide', () => documentSync.pause())
4626
+ window.addEventListener('pageshow', () => documentSync.wake())
4627
+
4468
4628
  window.addEventListener('beforeunload', event => {
4469
4629
  const editor = activeDocumentWorkspace()?.view.editor
4470
- if (!editor?.dirty && !state.notes.dirty) return
4630
+ if (!editor?.dirty && !state.notes.dirty && !state.notes.titleDirty) return
4471
4631
  event.preventDefault()
4472
4632
  event.returnValue = ''
4473
4633
  })
4474
4634
 
4475
4635
  installDragRecovery()
4476
- void installHostThemeBridge().then(() => boot())
4636
+ void installHostThemeBridge().then(() => boot()).then(() => documentSync.wake())
@@ -0,0 +1,23 @@
1
+ /** Conflict resolution is explicit: the remote version becomes the new base,
2
+ * and the user's chosen text remains a draft until saved with a version check. */
3
+ export function openSyncConflict({ element, actionButton, openModal, openConfirm, renderDiff, local, remote, apply, useRemote, canEdit = true, allowTitle = true }) {
4
+ const title = element('input', { class: 'input', value: local.title, 'aria-label': '合并后的标题', disabled: !canEdit || !allowTitle })
5
+ const content = element('textarea', { class: 'input sync-merge-content', 'aria-label': '合并后的正文', spellcheck: 'false', disabled: !canEdit }, local.content)
6
+ const remoteText = element('textarea', { class: 'input sync-merge-content', readonly: true, 'aria-label': '服务端最新正文', spellcheck: 'false' }, remote.content)
7
+ let modal
8
+ const body = element('div', { class: 'sync-conflict-body' },
9
+ element('p', {}, '你的未保存内容仍保留。请对照最新版本整理,应用后回到文档点击保存;保存时会再次检查版本。'),
10
+ element('details', {}, element('summary', {}, '查看最新版本与本地草稿的差异'), renderDiff(remote.content, local.content, '最新版本 → 本地草稿')),
11
+ element('div', { class: 'sync-merge-columns' },
12
+ element('section', {}, element('h3', {}, '服务端最新版本'), element('p', {}, remote.title), remoteText),
13
+ element('section', {}, element('h3', {}, '整理合并后的草稿'), title, content)),
14
+ !canEdit ? element('p', { role: 'status' }, '此知识文档已封存或归档,不能直接保存。你的草稿仍可在原编辑器中保留。') : null,
15
+ actionButton('放弃本地修改,使用最新版本', () => openConfirm({
16
+ title: '使用最新版本?', message: '将放弃这份未保存的本地草稿。', confirmLabel: '放弃草稿并加载', danger: true,
17
+ onConfirm: async () => { await useRemote(); modal.close(true) },
18
+ }), 'small'),
19
+ )
20
+ modal = openModal({ title: '文档有新版本', description: '不会自动覆盖任何一方的修改', body, className: 'sync-conflict-dialog', cancelLabel: '继续保留草稿',
21
+ ...(canEdit ? { primaryLabel: '应用到草稿', onPrimary: async () => { await apply({ title: title.value, content: content.value }); return true } } : {}),
22
+ })
23
+ }