@things-factory/ai-assistant 10.1.106 → 10.1.108
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/components/assistant-chat.ts +67 -2
- package/client/components/assistant-dock.ts +4 -4
- package/client/components/assistant-mode.ts +1 -1
- package/client/components/entry-review.ts +23 -3
- package/client/pages/assistant-workspace-page.ts +82 -2
- package/client/utils/attachment-policy.ts +22 -3
- package/client/utils/entry-hash.ts +35 -0
- package/client/utils/entry-proposal.ts +10 -3
- package/client/utils/entry-workspace.ts +70 -0
- package/client/utils/pasted-table.ts +145 -0
- package/client/utils/spreadsheet-text.ts +125 -0
- package/dist-client/components/assistant-chat.d.ts +2 -0
- package/dist-client/components/assistant-chat.js +63 -2
- package/dist-client/components/assistant-chat.js.map +1 -1
- package/dist-client/components/assistant-dock.js +4 -4
- package/dist-client/components/assistant-dock.js.map +1 -1
- package/dist-client/components/assistant-mode.d.ts +2 -1
- package/dist-client/components/assistant-mode.js.map +1 -1
- package/dist-client/components/entry-review.d.ts +2 -0
- package/dist-client/components/entry-review.js +30 -3
- package/dist-client/components/entry-review.js.map +1 -1
- package/dist-client/pages/assistant-workspace-page.d.ts +8 -0
- package/dist-client/pages/assistant-workspace-page.js +98 -2
- package/dist-client/pages/assistant-workspace-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/attachment-policy.d.ts +7 -1
- package/dist-client/utils/attachment-policy.js +14 -2
- package/dist-client/utils/attachment-policy.js.map +1 -1
- package/dist-client/utils/entry-hash.d.ts +2 -0
- package/dist-client/utils/entry-hash.js +36 -0
- package/dist-client/utils/entry-hash.js.map +1 -0
- package/dist-client/utils/entry-proposal.d.ts +1 -1
- package/dist-client/utils/entry-proposal.js +9 -2
- package/dist-client/utils/entry-proposal.js.map +1 -1
- package/dist-client/utils/entry-workspace.d.ts +20 -0
- package/dist-client/utils/entry-workspace.js +68 -0
- package/dist-client/utils/entry-workspace.js.map +1 -0
- package/dist-client/utils/pasted-table.d.ts +34 -0
- package/dist-client/utils/pasted-table.js +150 -0
- package/dist-client/utils/pasted-table.js.map +1 -0
- package/dist-client/utils/spreadsheet-text.d.ts +48 -0
- package/dist-client/utils/spreadsheet-text.js +110 -0
- package/dist-client/utils/spreadsheet-text.js.map +1 -0
- package/dist-server/service/assistant-chat-resolver.js +1 -1
- package/dist-server/service/assistant-chat-resolver.js.map +1 -1
- package/dist-server/service/assistant-mode/assistant-mode-resolver.js +1 -1
- package/dist-server/service/assistant-mode/assistant-mode-resolver.js.map +1 -1
- package/dist-server/service/chat-session/attachment-policy.d.ts +5 -2
- package/dist-server/service/chat-session/attachment-policy.js +10 -1
- package/dist-server/service/chat-session/attachment-policy.js.map +1 -1
- package/dist-server/service/chat-session/attachment-tools.js +3 -1
- package/dist-server/service/chat-session/attachment-tools.js.map +1 -1
- package/dist-server/service/chat-session/session-attachments.d.ts +3 -2
- package/dist-server/service/chat-session/session-attachments.js +5 -4
- package/dist-server/service/chat-session/session-attachments.js.map +1 -1
- package/dist-server/service/data-entry/entry-apply.d.ts +2 -0
- package/dist-server/service/data-entry/entry-apply.js +4 -0
- package/dist-server/service/data-entry/entry-apply.js.map +1 -1
- package/dist-server/service/data-entry/entry-hash.d.ts +2 -0
- package/dist-server/service/data-entry/entry-hash.js +39 -0
- package/dist-server/service/data-entry/entry-hash.js.map +1 -0
- package/dist-server/service/data-entry/entry-resolver.d.ts +1 -1
- package/dist-server/service/data-entry/entry-resolver.js +5 -3
- package/dist-server/service/data-entry/entry-resolver.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -4
- package/server/service/assistant-chat-resolver.ts +2 -2
- package/server/service/assistant-mode/assistant-mode-resolver.ts +1 -1
- package/server/service/chat-session/attachment-policy.ts +18 -2
- package/server/service/chat-session/attachment-tools.ts +3 -1
- package/server/service/chat-session/session-attachments.ts +5 -4
- package/server/service/data-entry/data-entry.test.ts +10 -0
- package/server/service/data-entry/entry-apply.ts +5 -0
- package/server/service/data-entry/entry-hash.ts +35 -0
- package/server/service/data-entry/entry-resolver.ts +4 -2
- package/test/entry-workspace.test.ts +89 -0
- package/test/pasted-table.test.ts +140 -0
- package/test/spreadsheet-text.test.ts +92 -0
- package/translations/en.json +12 -1
- package/translations/ja.json +12 -1
- package/translations/ko.json +12 -1
- package/translations/ms.json +12 -1
- package/translations/zh.json +12 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry-review.js","sourceRoot":"","sources":["../../client/components/entry-review.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;AACH,OAAO,4BAA4B,CAAA;AAEnC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAAE,eAAe,EAAE,aAAa,EAA+D,MAAM,4BAA4B,CAAA;AAExI,MAAM,KAAK,GAAG,EAAE,CAAA;AAEhB,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,YAAoB,EAAE,UAAmC,EAAE,EAAE,EAAE,CACrF,OAAO,CAAC,CAAC,CAAC,sBAAsB,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;AAEtE,SAAS,SAAS,CAAC,KAAqB;IACtC,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,EAAS,CAAA;IACjD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;QAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC1E,kFAAkF;IAClF,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;QAChE,IAAI,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;IAClK,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC,CAAA;AACzF,CAAC;AAED,+HAA+H;AAC/H,SAAS,UAAU,CAAC,MAAmE;IACrF,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC,eAAe,EAAE,0BAA0B,CAAC,CAAA;IACxE,OAAO,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,YAAY,IAAI,EAAE,CAAA;AAClD,CAAC;AAED,0GAA0G;AAC1G,SAAS,OAAO,CAAC,MAAmC,EAAE,KAAc;IAClE,IAAI,MAAM,CAAC,cAAc,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACpK,OAAO,KAAK,CAAC,KAAK,CAAC,CAAA;AACrB,CAAC;AAED,SAAS,KAAK,CAAC,KAAc;IAC3B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,CAAA;IACpD,mFAAmF;IACnF,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAE,KAAa,CAAC,KAAK,IAAK,KAAa,CAAC,IAAI,IAAK,KAAa,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;IACpH,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC,CAAA;IACzF,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;IACxD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;AACtB,CAAC;AAGM,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,UAAU;IAClD,2EAA2E;aACpE,WAAM,GAAG;QACd,eAAe;QACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgIJ;KACA,AAnIY,CAmIZ;IAID,iIAAiI;IACzH,YAAY,CAAC,MAAwB,EAAE,OAA8C;QAC3F,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,OAAO,OAAO,CAAA;QAClC,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE;YAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,KAAK,CAAC,CAAA;YACtD,OAAO,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QAC9D,CAAC,CAAA;QACD,OAAO,IAAI,CAAA;QACP,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAA;gBAChB,CAAC,CAAC,OAAO,EAAE,qBAAqB,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;UAC5F,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA,SAAS,CAAC,CAAC,aAAa,EAAE,eAAe,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;UAC1H,KAAK,CAAC,QAAQ,KAAK,SAAS;YAC5B,CAAC,CAAC,IAAI,CAAA,SAAS,KAAK,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,EAAE,yBAAyB,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,iBAAiB,EAAE,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBAC5S,KAAK,CAAC,UAAU;gBAChB,CAAC,CAAC,IAAI,CAAA,yBAAyB,CAAC,CAAC,eAAe,EAAE,kBAAkB,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,SAAS;gBAChH,CAAC,CAAC,IAAI,CAAA,qDAAqD,CAAC,CAAC,eAAe,EAAE,SAAS,CAAC,SAAS,EAAE;YACzG,CAAC,CAAC,OAAO;OACZ,CAAC;WACG,CAAA;IACT,CAAC;IAED;;;OAGG;IACK,aAAa,CAAC,CAAM;QAC1B,MAAM,OAAO,GAAiF,CAAC,CAAC,OAAO,IAAI,EAAE,CAAA;QAC7G,MAAM,IAAI,GAAU,CAAC,CAAC,IAAI,IAAI,EAAE,CAAA;QAChC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,CAAA;QAC7B,MAAM,GAAG,GAAG,CAAC,GAAQ,EAAE,EAAE,CACvB,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,2BAA2B,CAAC,CAAA;QAChL,OAAO,IAAI,CAAA;;gBAEC,CAAC,CAAC,SAAS,EAAE,iBAAiB,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBACtE,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;UAC/D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,yBAAyB,CAAC,CAAC,aAAa,EAAE,6BAA6B,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;;;;;;;oBAOjI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAA,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC;oBAC/F,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC;;;;cAI3B,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YAC/B,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAqB,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;YAClF,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;YAClC,OAAO,IAAI,CAAA,aAAa,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;kCAC5B,GAAG,CAAC,KAAK,GAAG,CAAC;sBACzB,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAA,0BAA0B,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC;kBAC1I,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;gBACrB,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;gBAChD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;gBAChD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAA;gBACjD,OAAO,IAAI,CAAA,cAAc,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;sBAC/K,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,wBAAwB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,qBAAqB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE;wBACzK,CAAA;YACR,CAAC,CAAC;qCACmB,GAAG,CAAC,GAAG,CAAC;oBACzB,CAAA;QACR,CAAC,CAAC;;;;KAIT,CAAA;IACH,CAAC;IAED,MAAM;QACJ,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAA;QAC7B,IAAI,CAAC,CAAC,EAAE,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,OAAO,GAAqG,CAAC,CAAC,OAAO,IAAI,EAAE,CAAA;QACjI,MAAM,IAAI,GAAmB,CAAC,CAAC,IAAI,IAAI,EAAE,CAAA;QACzC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,CAAA;QAC7B,OAAO,IAAI,CAAA;;UAEL,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA,SAAS,CAAC,CAAC,QAAQ,EAAE,iBAAiB,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;gBAClG,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;UACtE,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,WAAW,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA,yBAAyB,CAAC,CAAC,iBAAiB,EAAE,gCAAgC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;gBACvM,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;UAC/D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,yBAAyB,CAAC,CAAC,SAAS,EAAE,6BAA6B,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;UACvI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA,yBAAyB,CAAC,CAAC,KAAK,EAAE,iCAAiC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;UAC/H,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,sDAAsD,CAAC,CAAC,UAAU,EAAE,6BAA6B,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;UACvK,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAA,yBAAyB,CAAC,CAAC,WAAW,EAAE,+CAA+C,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;;;;;;;gBAOzJ,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAA,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;oBAC7H,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC;;;;cAIzB,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YAC/B,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;YAChE,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;YAClC,OAAO,IAAI,CAAA;4BACG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;oCAChB,GAAG,CAAC,KAAK,GAAG,CAAC;oBAC7B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;gBACrB,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;gBAChD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;gBAChD,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;gBACvC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;gBACnC,OAAO,IAAI,CAAA;+BACA,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;8BAChH,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;wBAEtC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,yBAAyB,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;0BAC5H,CAAA;YACR,CAAC,CAAC;6CACyB,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;sBACtE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,gCAAgC,CAAC,CAAC,UAAU,EAAE,kCAAkC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,sCAAsC,CAAC,CAAC,CAAC,OAAO;sBACjL,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;sBAC/C,KAAK;iBACJ,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC;iBAC3C,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAA,0BAA0B,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC;sBAC3G,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,2BAA2B,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;;;eAG5J,CAAA;QACH,CAAC,CAAC;;;;QAIN,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,OAAO,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA,qBAAqB,CAAC,CAAC,WAAW,EAAE,yDAAyD,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;QAC1K,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAA,6BAA6B,CAAC,CAAC,cAAc,EAAE,kFAAkF,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;KAC3K,CAAA;IACH,CAAC;;AAxI+B;IAA/B,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;sDAAc;AAvIlC,oBAAoB;IADhC,aAAa,CAAC,2BAA2B,CAAC;GAC9B,oBAAoB,CAgRhC","sourcesContent":["/*\n * The rows of a data entry proposal, as the person reviews them (operato-application/design/ai/data-entry.md §5).\n *\n * Read-only on purpose: a correction is said in the conversation (\"row 2 is 12,000\", \"drop the last one\")\n * and the model proposes again. What is wrong in a cell is marked on the cell - blocking in the error\n * colour, a note in the outline - and where each row came from is on the row.\n */\nimport '@material/web/icon/icon.js'\n\nimport { LitElement, css, html, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { entryCellIssues, entryIssueKey, type EntryIssueView, type EntryRowView, type EntryTotalView } from '../utils/entry-proposal.js'\n\nconst SHOWN = 50\n\nconst t = (key: string, defaultValue: string, options: Record<string, unknown> = {}) =>\n i18next.t(`ai-assistant.entry.${key}`, { defaultValue, ...options })\n\nfunction issueText(issue: EntryIssueView): string {\n const params = { ...(issue.params ?? {}) } as any\n if (Array.isArray(params.values)) params.values = params.values.join(', ')\n /* A code inside the message is worded by the key the application named for it. */\n for (const [name, prefix] of Object.entries(issue.paramKeys ?? {}))\n if (typeof params[name] === 'string' && params[name]) params[name] = String(i18next.t(`${prefix}${params[name].toLowerCase()}`, { defaultValue: params[name] }))\n return String(i18next.t(entryIssueKey(issue), { defaultValue: issue.code, ...params }))\n}\n\n/** Where a row came from, in the screen's words - \"said in the conversation\" is the framework's, never the model's English. */\nfunction sourceText(source: { attachmentId?: string; where?: string; person?: boolean }): string {\n if (source.person) return t('source-person', 'said in the conversation')\n return source.where || source.attachmentId || ''\n}\n\n/** An enum value in the person's words when the target names its key - the code only when it does not. */\nfunction valueOf(column: { valueKeyPrefix?: string }, value: unknown): string {\n if (column.valueKeyPrefix && typeof value === 'string' && value) return String(i18next.t(`${column.valueKeyPrefix}${value.toLowerCase()}`, { defaultValue: value }))\n return shown(value)\n}\n\nfunction shown(value: unknown): string {\n if (value === undefined || value === null) return ''\n /* A reference: the record's name the server found, or the text that found none. */\n if (typeof value === 'object') return String((value as any).label ?? (value as any).text ?? (value as any).id ?? '')\n if (typeof value === 'number') return value.toLocaleString(i18next.language || undefined)\n if (typeof value === 'boolean') return value ? '✓' : '—'\n return String(value)\n}\n\n@customElement('ox-assistant-entry-review')\nexport class AssistantEntryReview extends LitElement {\n /* The inner scroll areas wear the standard scrollbar, as the dock does. */\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n margin: 4px 0 2px;\n font-size: 12px;\n color: var(--md-sys-color-on-surface);\n }\n\n .summary {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 10px;\n margin-bottom: 6px;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n .summary .blocked {\n color: var(--md-sys-color-error);\n font-weight: 600;\n }\n\n .scroll {\n max-height: 320px;\n overflow: auto;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n\n table {\n width: 100%;\n border-collapse: collapse;\n }\n\n th,\n td {\n padding: 4px 6px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n text-align: start;\n vertical-align: top;\n white-space: nowrap;\n }\n\n th {\n position: sticky;\n top: 0;\n background: var(--md-sys-color-surface-container);\n font-weight: 600;\n }\n\n td.num {\n text-align: end;\n font-variant-numeric: tabular-nums;\n }\n\n tr.blocked td {\n background: color-mix(in srgb, var(--md-sys-color-error) 6%, transparent);\n }\n\n td.bad {\n color: var(--md-sys-color-error);\n text-decoration: underline wavy var(--md-sys-color-error);\n text-underline-offset: 3px;\n }\n\n td.note {\n text-decoration: underline dotted var(--md-sys-color-outline);\n text-underline-offset: 3px;\n }\n\n .before {\n color: var(--md-sys-color-on-surface-variant);\n text-decoration: line-through;\n }\n\n .missing {\n color: var(--md-sys-color-error);\n font-style: italic;\n }\n\n .source {\n color: var(--md-sys-color-on-surface-variant);\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .row-issue {\n display: block;\n color: var(--md-sys-color-on-surface-variant);\n white-space: normal;\n }\n\n .row-issue.blocking {\n color: var(--md-sys-color-error);\n }\n\n .verified {\n color: var(--md-sys-color-primary);\n }\n\n .verified md-icon,\n .totals md-icon {\n --md-icon-size: 14px;\n vertical-align: -2px;\n }\n\n .totals {\n display: flex;\n flex-wrap: wrap;\n gap: 2px 12px;\n margin: 6px 0 0;\n font-variant-numeric: tabular-nums;\n }\n\n .totals .differs {\n color: var(--md-sys-color-error);\n font-weight: 600;\n }\n\n .totals .matches {\n color: var(--md-sys-color-primary);\n }\n\n .more,\n .check-failed {\n margin-top: 4px;\n color: var(--md-sys-color-on-surface-variant);\n }\n `\n ]\n\n @property({ attribute: false }) proposal: any\n\n /** The sum of each totalled field, beside the total the material prints - a missing row shows here without reading every row. */\n private renderTotals(totals: EntryTotalView[], columns: { name: string; labelKey?: string }[]) {\n if (!totals.length) return nothing\n const name = (field: string) => {\n const column = columns.find(one => one.name === field)\n return column?.labelKey ? i18next.t(column.labelKey) : field\n }\n return html`<div class=\"totals\" role=\"status\">\n ${totals.map(total => html`\n <span>${t('total', '{field} total {sum}', { field: name(total.field), sum: shown(total.all) })}</span>\n ${total.ready !== total.all ? html`<span>${t('total-ready', 'entered {sum}', { sum: shown(total.ready) })}</span>` : nothing}\n ${total.declared !== undefined\n ? html`<span>${total.declaredBy === 'file' ? t('total-declared-file', \"the file's total line {sum}\", { sum: shown(total.declared) }) : t('total-declared', 'the material says {sum}', { sum: shown(total.declared) })}${total.declaredFound === false ? ` (${t('total-not-found', 'not found in the file')})` : ''}</span>\n ${total.difference\n ? html`<span class=\"differs\">${t('total-differs', 'differs by {sum}', { sum: shown(total.difference) })}</span>`\n : html`<span class=\"matches\"><md-icon>task_alt</md-icon> ${t('total-matches', 'matches')}</span>`}`\n : nothing}\n `)}\n </div>`\n }\n\n /**\n * A 수정안 - each record by its name, each changing field as what it holds now and what it becomes, and how the\n * record was picked. The \"now\" is the server's reading, never the model's memory.\n */\n private renderChanges(p: any) {\n const columns: { name: string; type: string; labelKey?: string; valueKeyPrefix?: string }[] = p.columns ?? []\n const rows: any[] = p.rows ?? []\n const counts = p.counts ?? {}\n const via = (row: any) =>\n row.via === 'current' ? t('via-current', 'the record on screen') : row.via === 'selected' ? t('via-selected', 'selected on screen') : t('via-id', 'found in the conversation')\n return html`\n <div class=\"summary\" role=\"status\">\n <span>${t('changes', '{count} records', { count: counts.rows ?? rows.length })}</span>\n <span>${t('ready', '{count} ready', { count: counts.ready ?? 0 })}</span>\n ${counts.blocked ? html`<span class=\"blocked\">${t('not-changed', '{count} will not be changed', { count: counts.blocked })}</span>` : nothing}\n </div>\n <div class=\"scroll\">\n <table>\n <thead>\n <tr>\n <th>#</th>\n <th>${t('record', 'record')}</th>\n ${columns.map(column => html`<th>${column.labelKey ? i18next.t(column.labelKey) : column.name}</th>`)}\n <th>${t('picked', 'picked')}</th>\n </tr>\n </thead>\n <tbody>\n ${rows.slice(0, SHOWN).map(row => {\n const blocked = (row.issues ?? []).some((issue: EntryIssueView) => issue.blocking)\n const whole = entryCellIssues(row)\n return html`<tr class=${blocked ? 'blocked' : ''}>\n <td class=\"num\">${row.index + 1}</td>\n <td>${row.label || row.id}${whole.map(issue => html`<span class=\"row-issue ${issue.blocking ? 'blocking' : ''}\">${issueText(issue)}</span>`)}</td>\n ${columns.map(column => {\n const issues = entryCellIssues(row, column.name)\n const bad = issues.some(issue => issue.blocking)\n const changes = column.name in (row.values ?? {})\n return html`<td class=\"${column.type === 'number' || column.type === 'integer' ? 'num' : ''} ${bad ? 'bad' : issues.length ? 'note' : ''}\" title=${issues.map(issueText).join('\\n')}>\n ${changes ? html`<span class=\"before\">${valueOf(column, row.before?.[column.name]) || '—'}</span> → <strong>${valueOf(column, row.values[column.name]) || '—'}</strong>` : ''}\n </td>`\n })}\n <td class=\"source\">${via(row)}</td>\n </tr>`\n })}\n </tbody>\n </table>\n </div>\n `\n }\n\n render() {\n const p = this.proposal ?? {}\n if (p.op === 'update') return this.renderChanges(p)\n const columns: { name: string; type: string; required?: boolean; labelKey?: string; valueKeyPrefix?: string }[] = p.columns ?? []\n const rows: EntryRowView[] = p.rows ?? []\n const counts = p.counts ?? {}\n return html`\n <div class=\"summary\" role=\"status\">\n ${counts.groups ? html`<span>${t('groups', '{count} records', { count: counts.groups })}</span>` : nothing}\n <span>${t('rows', '{count} rows', { count: counts.rows ?? rows.length })}</span>\n ${counts.groups && counts.groupsReady !== counts.groups ? html`<span class=\"blocked\">${t('groups-kept-out', '{count} records kept out whole', { count: counts.groups - counts.groupsReady })}</span>` : nothing}\n <span>${t('ready', '{count} ready', { count: counts.ready ?? 0 })}</span>\n ${counts.blocked ? html`<span class=\"blocked\">${t('blocked', '{count} will not be entered', { count: counts.blocked })}</span>` : nothing}\n ${counts.cut ? html`<span class=\"blocked\">${t('cut', '{count} left out over the limit', { count: counts.cut })}</span>` : nothing}\n ${counts.verified ? html`<span class=\"verified\"><md-icon>task_alt</md-icon> ${t('verified', '{count} found in their file', { count: counts.verified })}</span>` : nothing}\n ${counts.unmatched ? html`<span class=\"blocked\">${t('unmatched', '{count} with a value their file does not have', { count: counts.unmatched })}</span>` : nothing}\n </div>\n <div class=\"scroll\">\n <table>\n <thead>\n <tr>\n <th>#</th>\n ${columns.map(column => html`<th>${column.labelKey ? i18next.t(column.labelKey) : column.name}${column.required ? ' *' : ''}</th>`)}\n <th>${t('source', 'from')}</th>\n </tr>\n </thead>\n <tbody>\n ${rows.slice(0, SHOWN).map(row => {\n const blocked = (row.issues ?? []).some(issue => issue.blocking)\n const whole = entryCellIssues(row)\n return html`\n <tr class=${blocked ? 'blocked' : ''}>\n <td class=\"num\">${row.index + 1}</td>\n ${columns.map(column => {\n const issues = entryCellIssues(row, column.name)\n const bad = issues.some(issue => issue.blocking)\n const value = row.values?.[column.name]\n const text = valueOf(column, value)\n return html`<td\n class=\"${column.type === 'number' || column.type === 'integer' ? 'num' : ''} ${bad ? 'bad' : issues.length ? 'note' : ''}\"\n title=${issues.map(issueText).join('\\n')}\n >\n ${text || (issues.some(issue => issue.code === 'required') ? html`<span class=\"missing\">${t('missing', 'missing')}</span>` : '')}\n </td>`\n })}\n <td class=\"source\" title=${(row.sources ?? []).map(sourceText).join(' · ')}>\n ${row.evidence ? html`<span class=\"verified\" title=${t('evidence', 'found on line {line} of the file', { line: row.evidence.line })}><md-icon>task_alt</md-icon></span> ` : nothing}\n ${(row.sources ?? []).map(sourceText).join(' · ')}\n ${whole\n .filter(issue => issue.code !== 'no-source')\n .map(issue => html`<span class=\"row-issue ${issue.blocking ? 'blocking' : ''}\">${issueText(issue)}</span>`)}\n ${whole.some(issue => issue.code === 'no-source') ? html`<span class=\"row-issue\">${issueText({ code: 'no-source', blocking: false })}</span>` : nothing}\n </td>\n </tr>\n `\n })}\n </tbody>\n </table>\n </div>\n ${this.renderTotals(p.totals ?? [], columns)}\n ${rows.length > SHOWN ? html`<div class=\"more\">${t('more-rows', '{count} more rows are not shown - they are entered too.', { count: rows.length - SHOWN })}</div>` : nothing}\n ${p.checkFailed ? html`<div class=\"check-failed\">${t('check-failed', 'the application could not check these rows; they are checked again when entered.')}</div>` : nothing}\n `\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"entry-review.js","sourceRoot":"","sources":["../../client/components/entry-review.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The rows of a data entry proposal, as the person reviews them (operato-application/design/ai/data-entry.md §5).\n *\n * Read-only on purpose: a correction is said in the conversation (\"row 2 is 12,000\", \"drop the last one\")\n * and the model proposes again. What is wrong in a cell is marked on the cell - blocking in the error\n * colour, a note in the outline - and where each row came from is on the row.\n */\nimport '@material/web/icon/icon.js'\n\nimport { LitElement, css, html, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { entryCellIssues, entryIssueKey, type EntryIssueView, type EntryRowView, type EntryTotalView } from '../utils/entry-proposal.js'\n\nconst SHOWN = 50\n\nconst t = (key: string, defaultValue: string, options: Record<string, unknown> = {}) =>\n i18next.t(`ai-assistant.entry.${key}`, { defaultValue, ...options })\n\nfunction issueText(issue: EntryIssueView): string {\n const params = { ...(issue.params ?? {}) } as any\n if (Array.isArray(params.values)) params.values = params.values.join(', ')\n /* A code inside the message is worded by the key the application named for it. */\n for (const [name, prefix] of Object.entries(issue.paramKeys ?? {}))\n if (typeof params[name] === 'string' && params[name]) params[name] = String(i18next.t(`${prefix}${params[name].toLowerCase()}`, { defaultValue: params[name] }))\n return String(i18next.t(entryIssueKey(issue), { defaultValue: issue.code, ...params }))\n}\n\n/** Where a row came from, in the screen's words - \"said in the conversation\" is the framework's, never the model's English. */\nfunction sourceText(source: { attachmentId?: string; where?: string; person?: boolean }): string {\n if (source.person) return t('source-person', 'said in the conversation')\n return source.where || source.attachmentId || ''\n}\n\n/** An enum value in the person's words when the target names its key - the code only when it does not. */\nfunction valueOf(column: { valueKeyPrefix?: string }, value: unknown): string {\n if (column.valueKeyPrefix && typeof value === 'string' && value) return String(i18next.t(`${column.valueKeyPrefix}${value.toLowerCase()}`, { defaultValue: value }))\n return shown(value)\n}\n\nfunction shown(value: unknown): string {\n if (value === undefined || value === null) return ''\n /* A reference: the record's name the server found, or the text that found none. */\n if (typeof value === 'object') return String((value as any).label ?? (value as any).text ?? (value as any).id ?? '')\n if (typeof value === 'number') return value.toLocaleString(i18next.language || undefined)\n if (typeof value === 'boolean') return value ? '✓' : '—'\n return String(value)\n}\n\n@customElement('ox-assistant-entry-review')\nexport class AssistantEntryReview extends LitElement {\n /* The inner scroll areas wear the standard scrollbar, as the dock does. */\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n margin: 4px 0 2px;\n font-size: 12px;\n color: var(--md-sys-color-on-surface);\n }\n\n .summary {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 10px;\n margin-bottom: 6px;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n .summary .blocked {\n color: var(--md-sys-color-error);\n font-weight: 600;\n }\n\n .scroll {\n max-height: 320px;\n overflow: auto;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n\n table {\n width: 100%;\n border-collapse: collapse;\n }\n\n th,\n td {\n padding: 4px 6px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n text-align: start;\n vertical-align: top;\n white-space: nowrap;\n }\n\n th {\n position: sticky;\n top: 0;\n background: var(--md-sys-color-surface-container);\n font-weight: 600;\n }\n\n td.num {\n text-align: end;\n font-variant-numeric: tabular-nums;\n }\n\n tr.blocked td {\n background: color-mix(in srgb, var(--md-sys-color-error) 6%, transparent);\n }\n\n td.bad {\n color: var(--md-sys-color-error);\n text-decoration: underline wavy var(--md-sys-color-error);\n text-underline-offset: 3px;\n }\n\n td.note {\n text-decoration: underline dotted var(--md-sys-color-outline);\n text-underline-offset: 3px;\n }\n\n .before {\n color: var(--md-sys-color-on-surface-variant);\n text-decoration: line-through;\n }\n\n .missing {\n color: var(--md-sys-color-error);\n font-style: italic;\n }\n\n .source {\n color: var(--md-sys-color-on-surface-variant);\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .row-issue {\n display: block;\n color: var(--md-sys-color-on-surface-variant);\n white-space: normal;\n }\n\n .row-issue.blocking {\n color: var(--md-sys-color-error);\n }\n\n .verified {\n color: var(--md-sys-color-primary);\n }\n\n .verified md-icon,\n .totals md-icon {\n --md-icon-size: 14px;\n vertical-align: -2px;\n }\n\n .totals {\n display: flex;\n flex-wrap: wrap;\n gap: 2px 12px;\n margin: 6px 0 0;\n font-variant-numeric: tabular-nums;\n }\n\n .totals .differs {\n color: var(--md-sys-color-error);\n font-weight: 600;\n }\n\n .totals .matches {\n color: var(--md-sys-color-primary);\n }\n\n /* In the AI 작업판: every row, the page's height, the reading size of a page (design/ai/workspace.md §6-1). */\n :host([wide]) {\n font-size: 13px;\n }\n\n :host([wide]) .scroll {\n max-height: calc(100vh - 260px);\n }\n\n :host([wide]) th,\n :host([wide]) td {\n padding: 6px 10px;\n }\n\n :host([wide]) .source {\n max-width: 320px;\n }\n\n .more,\n .check-failed {\n margin-top: 4px;\n color: var(--md-sys-color-on-surface-variant);\n }\n `\n ]\n\n @property({ attribute: false }) proposal: any\n /** The 작업판's review - every row is drawn, not the first fifty. */\n @property({ type: Boolean, reflect: true }) wide = false\n\n /** The sum of each totalled field, beside the total the material prints - a missing row shows here without reading every row. */\n private renderTotals(totals: EntryTotalView[], columns: { name: string; labelKey?: string }[]) {\n if (!totals.length) return nothing\n const name = (field: string) => {\n const column = columns.find(one => one.name === field)\n return column?.labelKey ? i18next.t(column.labelKey) : field\n }\n return html`<div class=\"totals\" role=\"status\">\n ${totals.map(total => html`\n <span>${t('total', '{field} total {sum}', { field: name(total.field), sum: shown(total.all) })}</span>\n ${total.ready !== total.all ? html`<span>${t('total-ready', 'entered {sum}', { sum: shown(total.ready) })}</span>` : nothing}\n ${total.declared !== undefined\n ? html`<span>${total.declaredBy === 'file' ? t('total-declared-file', \"the file's total line {sum}\", { sum: shown(total.declared) }) : t('total-declared', 'the material says {sum}', { sum: shown(total.declared) })}${total.declaredFound === false ? ` (${t('total-not-found', 'not found in the file')})` : ''}</span>\n ${total.difference\n ? html`<span class=\"differs\">${t('total-differs', 'differs by {sum}', { sum: shown(total.difference) })}</span>`\n : html`<span class=\"matches\"><md-icon>task_alt</md-icon> ${t('total-matches', 'matches')}</span>`}`\n : nothing}\n `)}\n </div>`\n }\n\n /**\n * A 수정안 - each record by its name, each changing field as what it holds now and what it becomes, and how the\n * record was picked. The \"now\" is the server's reading, never the model's memory.\n */\n private renderChanges(p: any) {\n const columns: { name: string; type: string; labelKey?: string; valueKeyPrefix?: string }[] = p.columns ?? []\n const rows: any[] = p.rows ?? []\n const counts = p.counts ?? {}\n const via = (row: any) =>\n row.via === 'current' ? t('via-current', 'the record on screen') : row.via === 'selected' ? t('via-selected', 'selected on screen') : t('via-id', 'found in the conversation')\n return html`\n <div class=\"summary\" role=\"status\">\n <span>${t('changes', '{count} records', { count: counts.rows ?? rows.length })}</span>\n <span>${t('ready', '{count} ready', { count: counts.ready ?? 0 })}</span>\n ${counts.blocked ? html`<span class=\"blocked\">${t('not-changed', '{count} will not be changed', { count: counts.blocked })}</span>` : nothing}\n </div>\n <div class=\"scroll\">\n <table>\n <thead>\n <tr>\n <th>#</th>\n <th>${t('record', 'record')}</th>\n ${columns.map(column => html`<th>${column.labelKey ? i18next.t(column.labelKey) : column.name}</th>`)}\n <th>${t('picked', 'picked')}</th>\n </tr>\n </thead>\n <tbody>\n ${rows.slice(0, this.wide ? rows.length : SHOWN).map(row => {\n const blocked = (row.issues ?? []).some((issue: EntryIssueView) => issue.blocking)\n const whole = entryCellIssues(row)\n return html`<tr class=${blocked ? 'blocked' : ''}>\n <td class=\"num\">${row.index + 1}</td>\n <td>${row.label || row.id}${whole.map(issue => html`<span class=\"row-issue ${issue.blocking ? 'blocking' : ''}\">${issueText(issue)}</span>`)}</td>\n ${columns.map(column => {\n const issues = entryCellIssues(row, column.name)\n const bad = issues.some(issue => issue.blocking)\n const changes = column.name in (row.values ?? {})\n return html`<td class=\"${column.type === 'number' || column.type === 'integer' ? 'num' : ''} ${bad ? 'bad' : issues.length ? 'note' : ''}\" title=${issues.map(issueText).join('\\n')}>\n ${changes ? html`<span class=\"before\">${valueOf(column, row.before?.[column.name]) || '—'}</span> → <strong>${valueOf(column, row.values[column.name]) || '—'}</strong>` : ''}\n </td>`\n })}\n <td class=\"source\">${via(row)}</td>\n </tr>`\n })}\n </tbody>\n </table>\n </div>\n `\n }\n\n render() {\n const p = this.proposal ?? {}\n if (p.op === 'update') return this.renderChanges(p)\n const columns: { name: string; type: string; required?: boolean; labelKey?: string; valueKeyPrefix?: string }[] = p.columns ?? []\n const rows: EntryRowView[] = p.rows ?? []\n const counts = p.counts ?? {}\n return html`\n <div class=\"summary\" role=\"status\">\n ${counts.groups ? html`<span>${t('groups', '{count} records', { count: counts.groups })}</span>` : nothing}\n <span>${t('rows', '{count} rows', { count: counts.rows ?? rows.length })}</span>\n ${counts.groups && counts.groupsReady !== counts.groups ? html`<span class=\"blocked\">${t('groups-kept-out', '{count} records kept out whole', { count: counts.groups - counts.groupsReady })}</span>` : nothing}\n <span>${t('ready', '{count} ready', { count: counts.ready ?? 0 })}</span>\n ${counts.blocked ? html`<span class=\"blocked\">${t('blocked', '{count} will not be entered', { count: counts.blocked })}</span>` : nothing}\n ${counts.cut ? html`<span class=\"blocked\">${t('cut', '{count} left out over the limit', { count: counts.cut })}</span>` : nothing}\n ${counts.verified ? html`<span class=\"verified\"><md-icon>task_alt</md-icon> ${t('verified', '{count} found in their file', { count: counts.verified })}</span>` : nothing}\n ${counts.unmatched ? html`<span class=\"blocked\">${t('unmatched', '{count} with a value their file does not have', { count: counts.unmatched })}</span>` : nothing}\n </div>\n <div class=\"scroll\">\n <table>\n <thead>\n <tr>\n <th>#</th>\n ${columns.map(column => html`<th>${column.labelKey ? i18next.t(column.labelKey) : column.name}${column.required ? ' *' : ''}</th>`)}\n <th>${t('source', 'from')}</th>\n </tr>\n </thead>\n <tbody>\n ${rows.slice(0, this.wide ? rows.length : SHOWN).map(row => {\n const blocked = (row.issues ?? []).some(issue => issue.blocking)\n const whole = entryCellIssues(row)\n return html`\n <tr class=${blocked ? 'blocked' : ''}>\n <td class=\"num\">${row.index + 1}</td>\n ${columns.map(column => {\n const issues = entryCellIssues(row, column.name)\n const bad = issues.some(issue => issue.blocking)\n const value = row.values?.[column.name]\n const text = valueOf(column, value)\n return html`<td\n class=\"${column.type === 'number' || column.type === 'integer' ? 'num' : ''} ${bad ? 'bad' : issues.length ? 'note' : ''}\"\n title=${issues.map(issueText).join('\\n')}\n >\n ${text || (issues.some(issue => issue.code === 'required') ? html`<span class=\"missing\">${t('missing', 'missing')}</span>` : '')}\n </td>`\n })}\n <td class=\"source\" title=${(row.sources ?? []).map(sourceText).join(' · ')}>\n ${row.evidence ? html`<span class=\"verified\" title=${t('evidence', 'found on line {line} of the file', { line: row.evidence.line })}><md-icon>task_alt</md-icon></span> ` : nothing}\n ${(row.sources ?? []).map(sourceText).join(' · ')}\n ${whole\n .filter(issue => issue.code !== 'no-source')\n .map(issue => html`<span class=\"row-issue ${issue.blocking ? 'blocking' : ''}\">${issueText(issue)}</span>`)}\n ${whole.some(issue => issue.code === 'no-source') ? html`<span class=\"row-issue\">${issueText({ code: 'no-source', blocking: false })}</span>` : nothing}\n </td>\n </tr>\n `\n })}\n </tbody>\n </table>\n </div>\n ${this.renderTotals(p.totals ?? [], columns)}\n ${!this.wide && rows.length > SHOWN ? html`<div class=\"more\">${t('more-rows', '{count} more rows are not shown - they are entered too.', { count: rows.length - SHOWN })}</div>` : nothing}\n ${p.checkFailed ? html`<div class=\"check-failed\">${t('check-failed', 'the application could not check these rows; they are checked again when entered.')}</div>` : nothing}\n `\n }\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '@material/web/icon/icon.js';
|
|
2
2
|
import '../components/workspace-view.js';
|
|
3
|
+
import '../components/entry-review.js';
|
|
3
4
|
import { PageView } from '@operato/shell';
|
|
4
5
|
declare const AssistantWorkspacePage_base: (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
|
|
5
6
|
export declare class AssistantWorkspacePage extends AssistantWorkspacePage_base {
|
|
@@ -12,6 +13,9 @@ export declare class AssistantWorkspacePage extends AssistantWorkspacePage_base
|
|
|
12
13
|
private failure;
|
|
13
14
|
/** A version that arrived after the page was drawn - announced, not shown until asked. */
|
|
14
15
|
private newer;
|
|
16
|
+
/** Reviewing a 입력안: its key, what was found, and whether a newer card replaced it. */
|
|
17
|
+
private entryKey;
|
|
18
|
+
private entry?;
|
|
15
19
|
private unsubscribe?;
|
|
16
20
|
get context(): {
|
|
17
21
|
title: string;
|
|
@@ -21,6 +25,10 @@ export declare class AssistantWorkspacePage extends AssistantWorkspacePage_base
|
|
|
21
25
|
disconnectedCallback(): void;
|
|
22
26
|
pageUpdated(_changes: any, lifecycle: any): Promise<void>;
|
|
23
27
|
private load;
|
|
28
|
+
private readMessages;
|
|
29
|
+
/** The 입력안 under review - remembered as shown, so the card enters only this one (§6-1). */
|
|
30
|
+
private loadEntry;
|
|
31
|
+
private renderEntry;
|
|
24
32
|
private go;
|
|
25
33
|
render(): import("lit-html").TemplateResult<1>;
|
|
26
34
|
}
|
|
@@ -2,13 +2,15 @@ import { __decorate, __metadata } from "tslib";
|
|
|
2
2
|
/*
|
|
3
3
|
* The AI 작업판 page (operato-application/design/ai/workspace.md).
|
|
4
4
|
*
|
|
5
|
-
* `assistant-workspace?session=<id>&name=<name>[&version=<n>]
|
|
5
|
+
* `assistant-workspace?session=<id>&name=<name>[&version=<n>]`, or `?session=<id>&entry=<proposal key>` to review a
|
|
6
|
+
* 입력안 wide (§6-1) - read only; the card in the dock is where it is entered. It reads the conversation through its own
|
|
6
7
|
* door (`chatMessages`), so a private conversation shows nothing to someone outside it and a version behind a
|
|
7
8
|
* door the reader cannot pass is not among the versions (ADR-0073). A new version arriving while the page is
|
|
8
9
|
* open is announced, never swapped in under the reader.
|
|
9
10
|
*/
|
|
10
11
|
import '@material/web/icon/icon.js';
|
|
11
12
|
import '../components/workspace-view.js';
|
|
13
|
+
import '../components/entry-review.js';
|
|
12
14
|
import gql from 'graphql-tag';
|
|
13
15
|
import { css, html, nothing } from 'lit';
|
|
14
16
|
import { customElement, state } from 'lit/decorators.js';
|
|
@@ -18,6 +20,8 @@ import { navigate, PageView } from '@operato/shell';
|
|
|
18
20
|
import { ScrollbarStyles } from '@operato/styles';
|
|
19
21
|
import { startSessionActivityFeed, subscribeSessionActivity } from '../utils/assistant-activity.js';
|
|
20
22
|
import { workspaceAddress, workspaceVersions } from '../utils/workspace.js';
|
|
23
|
+
import { entryForReview, rememberReviewed } from '../utils/entry-workspace.js';
|
|
24
|
+
import { entryTitle } from '../utils/entry-proposal.js';
|
|
21
25
|
const MESSAGES = gql `
|
|
22
26
|
query ($sessionId: String!, $limit: Int, $offset: Int) {
|
|
23
27
|
chatMessages(sessionId: $sessionId, limit: $limit, offset: $offset) {
|
|
@@ -41,6 +45,8 @@ let AssistantWorkspacePage = class AssistantWorkspacePage extends localize(i18ne
|
|
|
41
45
|
this.failure = '';
|
|
42
46
|
/** A version that arrived after the page was drawn - announced, not shown until asked. */
|
|
43
47
|
this.newer = 0;
|
|
48
|
+
/** Reviewing a 입력안: its key, what was found, and whether a newer card replaced it. */
|
|
49
|
+
this.entryKey = '';
|
|
44
50
|
}
|
|
45
51
|
static { this.styles = [
|
|
46
52
|
ScrollbarStyles,
|
|
@@ -58,6 +64,11 @@ let AssistantWorkspacePage = class AssistantWorkspacePage extends localize(i18ne
|
|
|
58
64
|
margin: 0 auto;
|
|
59
65
|
}
|
|
60
66
|
|
|
67
|
+
/* A 입력안 is as wide as its columns - the reason it left the dock. */
|
|
68
|
+
.page.entry {
|
|
69
|
+
max-width: none;
|
|
70
|
+
}
|
|
71
|
+
|
|
61
72
|
header {
|
|
62
73
|
display: flex;
|
|
63
74
|
align-items: flex-start;
|
|
@@ -119,6 +130,8 @@ let AssistantWorkspacePage = class AssistantWorkspacePage extends localize(i18ne
|
|
|
119
130
|
`
|
|
120
131
|
]; }
|
|
121
132
|
get context() {
|
|
133
|
+
if (this.entryKey)
|
|
134
|
+
return { title: this.entry?.proposal ? entryTitle(this.entry.proposal, (key, options) => String(i18next.t(key, options))) : t('title', 'AI workspace') };
|
|
122
135
|
const shown = this.shown;
|
|
123
136
|
return { title: shown?.workspace.title || t('title', 'AI workspace') };
|
|
124
137
|
}
|
|
@@ -132,7 +145,7 @@ let AssistantWorkspacePage = class AssistantWorkspacePage extends localize(i18ne
|
|
|
132
145
|
startSessionActivityFeed();
|
|
133
146
|
this.unsubscribe = subscribeSessionActivity(activity => {
|
|
134
147
|
if (activity.sessionId === this.sessionId && activity.kind === 'message')
|
|
135
|
-
void this.load(true);
|
|
148
|
+
void (this.entryKey ? this.loadEntry() : this.load(true));
|
|
136
149
|
});
|
|
137
150
|
}
|
|
138
151
|
disconnectedCallback() {
|
|
@@ -144,6 +157,17 @@ let AssistantWorkspacePage = class AssistantWorkspacePage extends localize(i18ne
|
|
|
144
157
|
const sessionId = String(params.session || '');
|
|
145
158
|
const name = String(params.name || '');
|
|
146
159
|
const wanted = Number(params.version) || 0;
|
|
160
|
+
const entryKey = String(params.entry || '');
|
|
161
|
+
if (entryKey) {
|
|
162
|
+
const changedEntry = sessionId !== this.sessionId || entryKey !== this.entryKey;
|
|
163
|
+
this.sessionId = sessionId;
|
|
164
|
+
this.entryKey = entryKey;
|
|
165
|
+
this.name = '';
|
|
166
|
+
if (changedEntry)
|
|
167
|
+
await this.loadEntry();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
this.entryKey = '';
|
|
147
171
|
const changed = sessionId !== this.sessionId || name !== this.name;
|
|
148
172
|
this.sessionId = sessionId;
|
|
149
173
|
this.name = name;
|
|
@@ -183,11 +207,75 @@ let AssistantWorkspacePage = class AssistantWorkspacePage extends localize(i18ne
|
|
|
183
207
|
this.loading = false;
|
|
184
208
|
}
|
|
185
209
|
}
|
|
210
|
+
async readMessages() {
|
|
211
|
+
const messages = [];
|
|
212
|
+
for (let offset = 0; offset < MOST; offset += PAGE) {
|
|
213
|
+
const result = await client.query({ query: MESSAGES, variables: { sessionId: this.sessionId, limit: PAGE, offset }, fetchPolicy: 'no-cache' });
|
|
214
|
+
if (result.errors?.length)
|
|
215
|
+
throw new Error(result.errors[0].message);
|
|
216
|
+
const page = result.data?.chatMessages ?? [];
|
|
217
|
+
messages.push(...page);
|
|
218
|
+
if (page.length < PAGE)
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
return messages;
|
|
222
|
+
}
|
|
223
|
+
/** The 입력안 under review - remembered as shown, so the card enters only this one (§6-1). */
|
|
224
|
+
async loadEntry() {
|
|
225
|
+
if (!this.sessionId || !this.entryKey)
|
|
226
|
+
return;
|
|
227
|
+
this.loading = !this.entry;
|
|
228
|
+
this.failure = '';
|
|
229
|
+
try {
|
|
230
|
+
const found = entryForReview(await this.readMessages(), this.entryKey);
|
|
231
|
+
this.entry = found;
|
|
232
|
+
if (found.proposal && !found.superseded)
|
|
233
|
+
rememberReviewed(found.proposal);
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
this.failure = error?.message || String(error);
|
|
237
|
+
}
|
|
238
|
+
finally {
|
|
239
|
+
this.loading = false;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
renderEntry() {
|
|
243
|
+
const found = this.entry;
|
|
244
|
+
if (this.loading && !found)
|
|
245
|
+
return html `<div class="empty">${t('loading', 'loading the workspace…')}</div>`;
|
|
246
|
+
if (this.failure)
|
|
247
|
+
return html `<div class="empty">${t('unreadable-page', 'could not read this workspace: {reason}', { reason: this.failure })}</div>`;
|
|
248
|
+
if (!found?.proposal)
|
|
249
|
+
return html `<div class="empty">${t('entry-not-found', 'there is no proposal here that you can see.')}</div>`;
|
|
250
|
+
const p = found.proposal;
|
|
251
|
+
return html `<div class="page entry">
|
|
252
|
+
${found.superseded
|
|
253
|
+
? html `<div class="notice" role="status">
|
|
254
|
+
<md-icon>update</md-icon>
|
|
255
|
+
<span>${t('entry-superseded', 'a newer card replaced this one in the conversation - review that one.')}</span>
|
|
256
|
+
</div>`
|
|
257
|
+
: html `<div class="notice" role="note">
|
|
258
|
+
<md-icon>touch_app</md-icon>
|
|
259
|
+
<span>${t('entry-press-in-dock', 'this is a review. Enter the rows with the button on the card in the AI dock.')}</span>
|
|
260
|
+
</div>`}
|
|
261
|
+
<header>
|
|
262
|
+
<div class="what">
|
|
263
|
+
<h1>${entryTitle(p, (key, options) => String(i18next.t(key, options)))}</h1>
|
|
264
|
+
${p.reason || found.createdAt
|
|
265
|
+
? html `<div class="summary">${[p.reason, found.createdAt ? new Date(found.createdAt).toLocaleString(i18next.language || undefined) : ''].filter(Boolean).join(' · ')}</div>`
|
|
266
|
+
: nothing}
|
|
267
|
+
</div>
|
|
268
|
+
</header>
|
|
269
|
+
<ox-assistant-entry-review wide .proposal=${p}></ox-assistant-entry-review>
|
|
270
|
+
</div>`;
|
|
271
|
+
}
|
|
186
272
|
go(version) {
|
|
187
273
|
this.newer = 0;
|
|
188
274
|
navigate(workspaceAddress(this.sessionId, this.name, version));
|
|
189
275
|
}
|
|
190
276
|
render() {
|
|
277
|
+
if (this.entryKey)
|
|
278
|
+
return this.renderEntry();
|
|
191
279
|
const shown = this.shown;
|
|
192
280
|
if (this.loading && !shown)
|
|
193
281
|
return html `<div class="empty">${t('loading', 'loading the workspace…')}</div>`;
|
|
@@ -256,6 +344,14 @@ __decorate([
|
|
|
256
344
|
state(),
|
|
257
345
|
__metadata("design:type", Object)
|
|
258
346
|
], AssistantWorkspacePage.prototype, "newer", void 0);
|
|
347
|
+
__decorate([
|
|
348
|
+
state(),
|
|
349
|
+
__metadata("design:type", Object)
|
|
350
|
+
], AssistantWorkspacePage.prototype, "entryKey", void 0);
|
|
351
|
+
__decorate([
|
|
352
|
+
state(),
|
|
353
|
+
__metadata("design:type", Object)
|
|
354
|
+
], AssistantWorkspacePage.prototype, "entry", void 0);
|
|
259
355
|
AssistantWorkspacePage = __decorate([
|
|
260
356
|
customElement('assistant-workspace-page')
|
|
261
357
|
], AssistantWorkspacePage);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-workspace-page.js","sourceRoot":"","sources":["../../client/pages/assistant-workspace-page.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The AI 작업판 page (operato-application/design/ai/workspace.md).\n *\n * `assistant-workspace?session=<id>&name=<name>[&version=<n>]`. It reads the conversation through its own\n * door (`chatMessages`), so a private conversation shows nothing to someone outside it and a version behind a\n * door the reader cannot pass is not among the versions (ADR-0073). A new version arriving while the page is\n * open is announced, never swapped in under the reader.\n */\nimport '@material/web/icon/icon.js'\nimport '../components/workspace-view.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { startSessionActivityFeed, subscribeSessionActivity } from '../utils/assistant-activity.js'\nimport { workspaceAddress, workspaceVersions, type WorkspaceVersion } from '../utils/workspace.js'\n\nconst MESSAGES = gql`\n query ($sessionId: String!, $limit: Int, $offset: Int) {\n chatMessages(sessionId: $sessionId, limit: $limit, offset: $offset) {\n id\n createdAt\n proposalsJson\n }\n }\n`\n\nconst PAGE = 200\nconst MOST = 5000\n\nconst t = (key: string, defaultValue: string, options: Record<string, unknown> = {}) =>\n String(i18next.t(`ai-assistant.workspace.${key}`, { defaultValue, ...options }))\n\n@customElement('assistant-workspace-page')\nexport class AssistantWorkspacePage extends localize(i18next)(PageView) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n overflow: auto;\n padding: 20px 24px 40px;\n box-sizing: border-box;\n background: var(--md-sys-color-surface);\n }\n\n .page {\n max-width: 1100px;\n margin: 0 auto;\n }\n\n header {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n margin-bottom: 16px;\n }\n\n header .what {\n flex: 1;\n min-width: 0;\n }\n\n header h1 {\n margin: 0;\n font-size: 24px;\n line-height: 1.3;\n }\n\n header .summary {\n margin-top: 4px;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n header select {\n padding: 4px 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n background: var(--md-sys-color-surface-container-lowest);\n color: inherit;\n font: inherit;\n }\n\n .notice {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 14px;\n padding: 8px 12px;\n border-radius: 8px;\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n\n .notice button {\n padding: 3px 10px;\n border: 1px solid currentColor;\n border-radius: 6px;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n\n .empty {\n padding: 40px 0;\n color: var(--md-sys-color-on-surface-variant);\n text-align: center;\n }\n `\n ]\n\n @state() private sessionId = ''\n @state() private name = ''\n @state() private wanted = 0\n @state() private versions: WorkspaceVersion[] = []\n @state() private loading = false\n @state() private failure = ''\n /** A version that arrived after the page was drawn - announced, not shown until asked. */\n @state() private newer = 0\n\n private unsubscribe?: () => void\n\n get context() {\n const shown = this.shown\n return { title: shown?.workspace.title || t('title', 'AI workspace') }\n }\n\n private get shown(): WorkspaceVersion | undefined {\n if (!this.versions.length) return undefined\n return this.versions.find(one => one.version === this.wanted) ?? this.versions[this.versions.length - 1]\n }\n\n connectedCallback() {\n super.connectedCallback()\n startSessionActivityFeed()\n this.unsubscribe = subscribeSessionActivity(activity => {\n if (activity.sessionId === this.sessionId && activity.kind === 'message') void this.load(true)\n })\n }\n\n disconnectedCallback() {\n this.unsubscribe?.()\n super.disconnectedCallback()\n }\n\n async pageUpdated(_changes: any, lifecycle: any) {\n const params = lifecycle?.params ?? {}\n const sessionId = String(params.session || '')\n const name = String(params.name || '')\n const wanted = Number(params.version) || 0\n const changed = sessionId !== this.sessionId || name !== this.name\n this.sessionId = sessionId\n this.name = name\n this.wanted = wanted\n if (changed) {\n this.newer = 0\n await this.load(false)\n }\n }\n\n private async load(arriving: boolean) {\n if (!this.sessionId || !this.name) return\n const before = this.versions.length\n if (!arriving) this.loading = true\n this.failure = ''\n try {\n const messages: any[] = []\n for (let offset = 0; offset < MOST; offset += PAGE) {\n const result = await client.query({ query: MESSAGES, variables: { sessionId: this.sessionId, limit: PAGE, offset }, fetchPolicy: 'no-cache' })\n if (result.errors?.length) throw new Error(result.errors[0].message)\n const page = result.data?.chatMessages ?? []\n messages.push(...page)\n if (page.length < PAGE) break\n }\n const versions = workspaceVersions(messages, this.name)\n this.versions = versions\n if (arriving && versions.length > before && before > 0) this.newer = versions[versions.length - 1].version\n } catch (error: any) {\n this.failure = error?.message || String(error)\n } finally {\n this.loading = false\n }\n }\n\n private go(version?: number) {\n this.newer = 0\n navigate(workspaceAddress(this.sessionId, this.name, version))\n }\n\n render() {\n const shown = this.shown\n if (this.loading && !shown) return html`<div class=\"empty\">${t('loading', 'loading the workspace…')}</div>`\n if (this.failure) return html`<div class=\"empty\">${t('unreadable-page', 'could not read this workspace: {reason}', { reason: this.failure })}</div>`\n /*\n * Nothing to show says only what is true: this reader sees no such workspace. Whether it never existed, is in\n * a private conversation or sits behind a door is not said - saying which would itself tell.\n */\n if (!shown) return html`<div class=\"empty\">${t('not-found', 'there is no workspace here that you can see.')}</div>`\n\n const latest = this.versions[this.versions.length - 1].version\n return html`<div class=\"page\">\n ${this.newer && this.newer !== shown.version\n ? html`<div class=\"notice\" role=\"status\">\n <md-icon>update</md-icon>\n <span>${t('newer', 'a newer version ({version}) is ready.', { version: this.newer })}</span>\n <button @click=${() => this.go(this.newer)}>${t('show-newer', 'show it')}</button>\n </div>`\n : nothing}\n <header>\n <div class=\"what\">\n <h1>${shown.workspace.title}</h1>\n ${shown.workspace.summary ? html`<div class=\"summary\">${shown.workspace.summary}</div>` : nothing}\n </div>\n ${this.versions.length > 1\n ? html`<select aria-label=${t('versions', 'versions')} @change=${(e: Event) => this.go(Number((e.target as HTMLSelectElement).value))}>\n ${this.versions\n .slice()\n .reverse()\n .map(\n one => html`<option value=${one.version} ?selected=${one.version === shown.version}>\n ${t('version', 'version {version} of {of}', { version: one.version, of: latest })}${one.createdAt ? ` · ${new Date(one.createdAt).toLocaleString(i18next.language || undefined)}` : ''}\n </option>`\n )}\n </select>`\n : nothing}\n </header>\n <ox-assistant-workspace-view .workspace=${shown.workspace}></ox-assistant-workspace-view>\n </div>`\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"assistant-workspace-page.js","sourceRoot":"","sources":["../../client/pages/assistant-workspace-page.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The AI 작업판 page (operato-application/design/ai/workspace.md).\n *\n * `assistant-workspace?session=<id>&name=<name>[&version=<n>]`, or `?session=<id>&entry=<proposal key>` to review a\n * 입력안 wide (§6-1) - read only; the card in the dock is where it is entered. It reads the conversation through its own\n * door (`chatMessages`), so a private conversation shows nothing to someone outside it and a version behind a\n * door the reader cannot pass is not among the versions (ADR-0073). A new version arriving while the page is\n * open is announced, never swapped in under the reader.\n */\nimport '@material/web/icon/icon.js'\nimport '../components/workspace-view.js'\nimport '../components/entry-review.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { startSessionActivityFeed, subscribeSessionActivity } from '../utils/assistant-activity.js'\nimport { workspaceAddress, workspaceVersions, type WorkspaceVersion } from '../utils/workspace.js'\nimport { entryForReview, rememberReviewed } from '../utils/entry-workspace.js'\nimport { entryTitle } from '../utils/entry-proposal.js'\n\nconst MESSAGES = gql`\n query ($sessionId: String!, $limit: Int, $offset: Int) {\n chatMessages(sessionId: $sessionId, limit: $limit, offset: $offset) {\n id\n createdAt\n proposalsJson\n }\n }\n`\n\nconst PAGE = 200\nconst MOST = 5000\n\nconst t = (key: string, defaultValue: string, options: Record<string, unknown> = {}) =>\n String(i18next.t(`ai-assistant.workspace.${key}`, { defaultValue, ...options }))\n\n@customElement('assistant-workspace-page')\nexport class AssistantWorkspacePage extends localize(i18next)(PageView) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n overflow: auto;\n padding: 20px 24px 40px;\n box-sizing: border-box;\n background: var(--md-sys-color-surface);\n }\n\n .page {\n max-width: 1100px;\n margin: 0 auto;\n }\n\n /* A 입력안 is as wide as its columns - the reason it left the dock. */\n .page.entry {\n max-width: none;\n }\n\n header {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n margin-bottom: 16px;\n }\n\n header .what {\n flex: 1;\n min-width: 0;\n }\n\n header h1 {\n margin: 0;\n font-size: 24px;\n line-height: 1.3;\n }\n\n header .summary {\n margin-top: 4px;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n header select {\n padding: 4px 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n background: var(--md-sys-color-surface-container-lowest);\n color: inherit;\n font: inherit;\n }\n\n .notice {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 14px;\n padding: 8px 12px;\n border-radius: 8px;\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n\n .notice button {\n padding: 3px 10px;\n border: 1px solid currentColor;\n border-radius: 6px;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n\n .empty {\n padding: 40px 0;\n color: var(--md-sys-color-on-surface-variant);\n text-align: center;\n }\n `\n ]\n\n @state() private sessionId = ''\n @state() private name = ''\n @state() private wanted = 0\n @state() private versions: WorkspaceVersion[] = []\n @state() private loading = false\n @state() private failure = ''\n /** A version that arrived after the page was drawn - announced, not shown until asked. */\n @state() private newer = 0\n /** Reviewing a 입력안: its key, what was found, and whether a newer card replaced it. */\n @state() private entryKey = ''\n @state() private entry?: { proposal?: any; createdAt?: string; superseded: boolean }\n\n private unsubscribe?: () => void\n\n get context() {\n if (this.entryKey) return { title: this.entry?.proposal ? entryTitle(this.entry.proposal, (key, options) => String(i18next.t(key, options))) : t('title', 'AI workspace') }\n const shown = this.shown\n return { title: shown?.workspace.title || t('title', 'AI workspace') }\n }\n\n private get shown(): WorkspaceVersion | undefined {\n if (!this.versions.length) return undefined\n return this.versions.find(one => one.version === this.wanted) ?? this.versions[this.versions.length - 1]\n }\n\n connectedCallback() {\n super.connectedCallback()\n startSessionActivityFeed()\n this.unsubscribe = subscribeSessionActivity(activity => {\n if (activity.sessionId === this.sessionId && activity.kind === 'message') void (this.entryKey ? this.loadEntry() : this.load(true))\n })\n }\n\n disconnectedCallback() {\n this.unsubscribe?.()\n super.disconnectedCallback()\n }\n\n async pageUpdated(_changes: any, lifecycle: any) {\n const params = lifecycle?.params ?? {}\n const sessionId = String(params.session || '')\n const name = String(params.name || '')\n const wanted = Number(params.version) || 0\n const entryKey = String(params.entry || '')\n if (entryKey) {\n const changedEntry = sessionId !== this.sessionId || entryKey !== this.entryKey\n this.sessionId = sessionId\n this.entryKey = entryKey\n this.name = ''\n if (changedEntry) await this.loadEntry()\n return\n }\n this.entryKey = ''\n const changed = sessionId !== this.sessionId || name !== this.name\n this.sessionId = sessionId\n this.name = name\n this.wanted = wanted\n if (changed) {\n this.newer = 0\n await this.load(false)\n }\n }\n\n private async load(arriving: boolean) {\n if (!this.sessionId || !this.name) return\n const before = this.versions.length\n if (!arriving) this.loading = true\n this.failure = ''\n try {\n const messages: any[] = []\n for (let offset = 0; offset < MOST; offset += PAGE) {\n const result = await client.query({ query: MESSAGES, variables: { sessionId: this.sessionId, limit: PAGE, offset }, fetchPolicy: 'no-cache' })\n if (result.errors?.length) throw new Error(result.errors[0].message)\n const page = result.data?.chatMessages ?? []\n messages.push(...page)\n if (page.length < PAGE) break\n }\n const versions = workspaceVersions(messages, this.name)\n this.versions = versions\n if (arriving && versions.length > before && before > 0) this.newer = versions[versions.length - 1].version\n } catch (error: any) {\n this.failure = error?.message || String(error)\n } finally {\n this.loading = false\n }\n }\n\n private async readMessages(): Promise<any[]> {\n const messages: any[] = []\n for (let offset = 0; offset < MOST; offset += PAGE) {\n const result = await client.query({ query: MESSAGES, variables: { sessionId: this.sessionId, limit: PAGE, offset }, fetchPolicy: 'no-cache' })\n if (result.errors?.length) throw new Error(result.errors[0].message)\n const page = result.data?.chatMessages ?? []\n messages.push(...page)\n if (page.length < PAGE) break\n }\n return messages\n }\n\n /** The 입력안 under review - remembered as shown, so the card enters only this one (§6-1). */\n private async loadEntry() {\n if (!this.sessionId || !this.entryKey) return\n this.loading = !this.entry\n this.failure = ''\n try {\n const found = entryForReview(await this.readMessages(), this.entryKey)\n this.entry = found\n if (found.proposal && !found.superseded) rememberReviewed(found.proposal)\n } catch (error: any) {\n this.failure = error?.message || String(error)\n } finally {\n this.loading = false\n }\n }\n\n private renderEntry() {\n const found = this.entry\n if (this.loading && !found) return html`<div class=\"empty\">${t('loading', 'loading the workspace…')}</div>`\n if (this.failure) return html`<div class=\"empty\">${t('unreadable-page', 'could not read this workspace: {reason}', { reason: this.failure })}</div>`\n if (!found?.proposal) return html`<div class=\"empty\">${t('entry-not-found', 'there is no proposal here that you can see.')}</div>`\n const p = found.proposal\n return html`<div class=\"page entry\">\n ${found.superseded\n ? html`<div class=\"notice\" role=\"status\">\n <md-icon>update</md-icon>\n <span>${t('entry-superseded', 'a newer card replaced this one in the conversation - review that one.')}</span>\n </div>`\n : html`<div class=\"notice\" role=\"note\">\n <md-icon>touch_app</md-icon>\n <span>${t('entry-press-in-dock', 'this is a review. Enter the rows with the button on the card in the AI dock.')}</span>\n </div>`}\n <header>\n <div class=\"what\">\n <h1>${entryTitle(p, (key, options) => String(i18next.t(key, options)))}</h1>\n ${p.reason || found.createdAt\n ? html`<div class=\"summary\">${[p.reason, found.createdAt ? new Date(found.createdAt).toLocaleString(i18next.language || undefined) : ''].filter(Boolean).join(' · ')}</div>`\n : nothing}\n </div>\n </header>\n <ox-assistant-entry-review wide .proposal=${p}></ox-assistant-entry-review>\n </div>`\n }\n\n private go(version?: number) {\n this.newer = 0\n navigate(workspaceAddress(this.sessionId, this.name, version))\n }\n\n render() {\n if (this.entryKey) return this.renderEntry()\n const shown = this.shown\n if (this.loading && !shown) return html`<div class=\"empty\">${t('loading', 'loading the workspace…')}</div>`\n if (this.failure) return html`<div class=\"empty\">${t('unreadable-page', 'could not read this workspace: {reason}', { reason: this.failure })}</div>`\n /*\n * Nothing to show says only what is true: this reader sees no such workspace. Whether it never existed, is in\n * a private conversation or sits behind a door is not said - saying which would itself tell.\n */\n if (!shown) return html`<div class=\"empty\">${t('not-found', 'there is no workspace here that you can see.')}</div>`\n\n const latest = this.versions[this.versions.length - 1].version\n return html`<div class=\"page\">\n ${this.newer && this.newer !== shown.version\n ? html`<div class=\"notice\" role=\"status\">\n <md-icon>update</md-icon>\n <span>${t('newer', 'a newer version ({version}) is ready.', { version: this.newer })}</span>\n <button @click=${() => this.go(this.newer)}>${t('show-newer', 'show it')}</button>\n </div>`\n : nothing}\n <header>\n <div class=\"what\">\n <h1>${shown.workspace.title}</h1>\n ${shown.workspace.summary ? html`<div class=\"summary\">${shown.workspace.summary}</div>` : nothing}\n </div>\n ${this.versions.length > 1\n ? html`<select aria-label=${t('versions', 'versions')} @change=${(e: Event) => this.go(Number((e.target as HTMLSelectElement).value))}>\n ${this.versions\n .slice()\n .reverse()\n .map(\n one => html`<option value=${one.version} ?selected=${one.version === shown.version}>\n ${t('version', 'version {version} of {of}', { version: one.version, of: latest })}${one.createdAt ? ` · ${new Date(one.createdAt).toLocaleString(i18next.language || undefined)}` : ''}\n </option>`\n )}\n </select>`\n : nothing}\n </header>\n <ox-assistant-workspace-view .workspace=${shown.workspace}></ox-assistant-workspace-view>\n </div>`\n }\n}\n"]}
|