pith-ui 0.1.1 → 0.2.0-app.1

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 (140) hide show
  1. package/AI.md +33 -8
  2. package/API.md +424 -268
  3. package/APP-API.md +2019 -0
  4. package/APP.md +137 -0
  5. package/README.md +37 -4
  6. package/dist/app/files.d.ts +68 -0
  7. package/dist/app/files.d.ts.map +1 -0
  8. package/dist/app/files.js +177 -0
  9. package/dist/app/files.js.map +1 -0
  10. package/dist/app/index.d.ts +57 -0
  11. package/dist/app/index.d.ts.map +1 -0
  12. package/dist/app/index.js +300 -0
  13. package/dist/app/index.js.map +1 -0
  14. package/dist/app/internal.d.ts +31 -0
  15. package/dist/app/internal.d.ts.map +1 -0
  16. package/dist/app/internal.js +2 -0
  17. package/dist/app/internal.js.map +1 -0
  18. package/dist/app/resources.d.ts +89 -0
  19. package/dist/app/resources.d.ts.map +1 -0
  20. package/dist/app/resources.js +190 -0
  21. package/dist/app/resources.js.map +1 -0
  22. package/dist/app/session.d.ts +14 -0
  23. package/dist/app/session.d.ts.map +1 -0
  24. package/dist/app/session.js +12 -0
  25. package/dist/app/session.js.map +1 -0
  26. package/dist/app/settings.d.ts +109 -0
  27. package/dist/app/settings.d.ts.map +1 -0
  28. package/dist/app/settings.js +279 -0
  29. package/dist/app/settings.js.map +1 -0
  30. package/dist/app/workspace.d.ts +228 -0
  31. package/dist/app/workspace.d.ts.map +1 -0
  32. package/dist/app/workspace.js +402 -0
  33. package/dist/app/workspace.js.map +1 -0
  34. package/dist/composer.d.ts.map +1 -1
  35. package/dist/composer.js +37 -27
  36. package/dist/composer.js.map +1 -1
  37. package/dist/content/conversation-reader.d.ts.map +1 -1
  38. package/dist/content/conversation-reader.js +8 -1
  39. package/dist/content/conversation-reader.js.map +1 -1
  40. package/dist/content/conversation-view.d.ts.map +1 -1
  41. package/dist/content/conversation-view.js +34 -8
  42. package/dist/content/conversation-view.js.map +1 -1
  43. package/dist/content/image-viewer.d.ts.map +1 -1
  44. package/dist/content/image-viewer.js +11 -3
  45. package/dist/content/image-viewer.js.map +1 -1
  46. package/dist/content/paged-preview.d.ts +1 -1
  47. package/dist/content/paged-preview.d.ts.map +1 -1
  48. package/dist/content/paged-preview.js +4 -2
  49. package/dist/content/paged-preview.js.map +1 -1
  50. package/dist/content/views.d.ts +3 -0
  51. package/dist/content/views.d.ts.map +1 -1
  52. package/dist/content/views.js +110 -41
  53. package/dist/content/views.js.map +1 -1
  54. package/dist/content/welcome.d.ts.map +1 -1
  55. package/dist/content/welcome.js +5 -2
  56. package/dist/content/welcome.js.map +1 -1
  57. package/dist/dom.js +1 -1
  58. package/dist/dom.js.map +1 -1
  59. package/dist/files/panels.d.ts +2 -0
  60. package/dist/files/panels.d.ts.map +1 -1
  61. package/dist/files/panels.js +202 -128
  62. package/dist/files/panels.js.map +1 -1
  63. package/dist/files/systems.d.ts.map +1 -1
  64. package/dist/files/systems.js +37 -64
  65. package/dist/files/systems.js.map +1 -1
  66. package/dist/forms/actions.d.ts +24 -2
  67. package/dist/forms/actions.d.ts.map +1 -1
  68. package/dist/forms/actions.js +54 -25
  69. package/dist/forms/actions.js.map +1 -1
  70. package/dist/forms/custom-connection.d.ts.map +1 -1
  71. package/dist/forms/custom-connection.js +3 -2
  72. package/dist/forms/custom-connection.js.map +1 -1
  73. package/dist/forms/history.d.ts +1 -1
  74. package/dist/forms/history.d.ts.map +1 -1
  75. package/dist/forms/history.js +78 -15
  76. package/dist/forms/history.js.map +1 -1
  77. package/dist/forms/identity.d.ts.map +1 -1
  78. package/dist/forms/identity.js +9 -25
  79. package/dist/forms/identity.js.map +1 -1
  80. package/dist/forms/model-editor.js +3 -3
  81. package/dist/forms/model-editor.js.map +1 -1
  82. package/dist/forms/panels.d.ts +9 -2
  83. package/dist/forms/panels.d.ts.map +1 -1
  84. package/dist/forms/panels.js +79 -88
  85. package/dist/forms/panels.js.map +1 -1
  86. package/dist/forms/provider-login.d.ts.map +1 -1
  87. package/dist/forms/provider-login.js +20 -36
  88. package/dist/forms/provider-login.js.map +1 -1
  89. package/dist/forms/resource-editor.js +5 -4
  90. package/dist/forms/resource-editor.js.map +1 -1
  91. package/dist/foundations.d.ts +1 -1
  92. package/dist/foundations.d.ts.map +1 -1
  93. package/dist/foundations.js +22 -38
  94. package/dist/foundations.js.map +1 -1
  95. package/dist/navigation/context-menu.d.ts +7 -1
  96. package/dist/navigation/context-menu.d.ts.map +1 -1
  97. package/dist/navigation/context-menu.js +60 -57
  98. package/dist/navigation/context-menu.js.map +1 -1
  99. package/dist/navigation/navigation.d.ts +13 -0
  100. package/dist/navigation/navigation.d.ts.map +1 -1
  101. package/dist/navigation/navigation.js +96 -130
  102. package/dist/navigation/navigation.js.map +1 -1
  103. package/dist/operation.d.ts +12 -0
  104. package/dist/operation.d.ts.map +1 -0
  105. package/dist/operation.js +49 -0
  106. package/dist/operation.js.map +1 -0
  107. package/dist/primitives.d.ts +8 -1
  108. package/dist/primitives.d.ts.map +1 -1
  109. package/dist/primitives.js +114 -143
  110. package/dist/primitives.js.map +1 -1
  111. package/dist/reconcile.d.ts +11 -0
  112. package/dist/reconcile.d.ts.map +1 -0
  113. package/dist/reconcile.js +36 -0
  114. package/dist/reconcile.js.map +1 -0
  115. package/dist/select.d.ts +14 -0
  116. package/dist/select.d.ts.map +1 -0
  117. package/dist/select.js +304 -0
  118. package/dist/select.js.map +1 -0
  119. package/dist/styles.css +439 -370
  120. package/dist/surface.d.ts +31 -0
  121. package/dist/surface.d.ts.map +1 -1
  122. package/dist/surface.js +193 -3
  123. package/dist/surface.js.map +1 -1
  124. package/dist/tasks/approval.d.ts.map +1 -1
  125. package/dist/tasks/approval.js +83 -45
  126. package/dist/tasks/approval.js.map +1 -1
  127. package/dist/tasks/permission-element.d.ts +3 -0
  128. package/dist/tasks/permission-element.d.ts.map +1 -0
  129. package/dist/tasks/permission-element.js +10 -0
  130. package/dist/tasks/permission-element.js.map +1 -0
  131. package/dist/tasks/permission.d.ts.map +1 -1
  132. package/dist/tasks/permission.js +37 -18
  133. package/dist/tasks/permission.js.map +1 -1
  134. package/dist/tasks/runtime.d.ts.map +1 -1
  135. package/dist/tasks/runtime.js +32 -15
  136. package/dist/tasks/runtime.js.map +1 -1
  137. package/dist/workspace.d.ts.map +1 -1
  138. package/dist/workspace.js +93 -40
  139. package/dist/workspace.js.map +1 -1
  140. package/package.json +42 -8
@@ -1 +1 @@
1
- {"version":3,"file":"model-editor.js","sourceRoot":"","sources":["../../src/forms/model-editor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAC,iBAAiB,EAAC,sBAAsB,IAAI,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAgC1F,MAAM,UAAU,aAAa,CAAC,KAAa,IAAY,OAAO,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC3J,MAAM,UAAU,iBAAiB,CAAC,MAAc,IAAY,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,uCAAuC,MAAM,qEAAqE,MAAM,yHAAyH,MAAM,oCAAoC,MAAM,wHAAwH,MAAM,2CAA2C,MAAM,6EAA6E,MAAM,mGAAmG,MAAM,yBAAyB,MAAM,iDAAiD,MAAM,2DAA2D,MAAM,6MAA6M,CAAC,CAAC,CAAC;AAC/kC,MAAM,UAAU,iBAAiB,CAAC,OAAyB,EAAE,UAIzD,EAAE;IACF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,CAAC,SAAS,GAAG,kBAAkB,CAAC;QACvC,OAAO,CAAC,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,KAAK,GAAG,CAAsC,EAAU,EAAE,EAAE;QAAG,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAc,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC;QAAC,IAAI,CAAC,MAAM;YAClM,MAAM,IAAI,KAAK,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;QAAC,OAAO,MAAW,CAAC;IAAC,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,KAAK,CAAoB,UAAU,CAAC,EAAE,KAAK,GAAG,KAAK,CAAoB,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAmB,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAoB,UAAU,CAAC,CAAC;IAC5L,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,EAAE,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IACxE,IAAI,SAAS,GAAG,KAAK,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,GAAG,EAAE,EAAE,QAAQ,GAAG,EAAE,CAAC;IAC1E,IAAI,KAAK,GAA+B,OAAO,CAAC;IAChD,MAAM,IAAI,GAAG,GAAmB,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC/K,MAAM,QAAQ,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAC,QAAQ,EAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnW,MAAM,YAAY,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE,EAAE;QAC9C,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;QACvB,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,IAAI,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC7G,MAAM,MAAM,GAAG,KAAK,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9E,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1F,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC5I,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAClC,KAAK,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC/C,KAAK,CAAC,cAAc,CAAC,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,qBAAqB,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC,CAAC,qBAAqB,CAAC;QACrR,QAAQ,EAAE,CAAC;IACf,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE,EAAE;QAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChL,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QACtG,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC;QAC7F,YAAY,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC,CAAC;IACF,MAAM,cAAc,GAAG,CAAC,SAA0B,EAAE,EAAE;QAClD,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC1E,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC;QAClB,QAAQ,GAAG,SAAS,IAAI,SAAS,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC;QACrG,YAAY,CAAC,SAAS,IAAI,SAAS,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,EAAE,aAAa,IAAI,MAAM,CAAC,CAAC;IAChI,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,SAAyB,EAAE,EAAE;QAAG,IAAI,SAAS;YACxD,OAAO;QAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAAC,CAAC,CAAC;IAC/L,MAAM,MAAM,GAAG,CAAC,IAAgC,EAAE,EAAE;QAChD,IAAI,SAAS;YACT,OAAO;QACX,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;QACrB,KAAK,GAAG,IAAI,CAAC;QACb,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACpE,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAC9B,SAAS,GAAG,aAAa,CAAC;YAC1B,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACtG,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAC/B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;iBACrB,CAAC;gBACF,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC;gBAC/H,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;gBACvB,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YACtC,CAAC;YACD,WAAW,GAAG,IAAI,CAAC;QACvB,CAAC;QACD,QAAQ,EAAE,CAAC;IACf,CAAC,CAAC;IACF,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,cAAc,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACtF,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACjF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACjF,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/F,MAAM,CAAC,OAAO,CAAC,CAAC;IAChB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO;YAAK,IAAI,SAAS;gBACpG,OAAO;YAAC,SAAS,GAAG,IAAI,CAAC;YAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAAC,IAAI,CAAC,OAAO,CAAC,OAAO;gBAC9E,OAAO,CAAC,MAAM,EAAE,CAAC;QAAC,CAAC,EAAE,CAAC;AAClC,CAAC","sourcesContent":["import type { UIBlock } from '../core.js';\nimport { escape, uniqueId } from '../dom.js';\nimport {adoptProductParts,reconcileSelectOptions as optionsInto} from '../foundations.js';\nexport interface ModelProviderOption {\n id: string;\n name: string;\n model?: string;\n thinkingLevel?: string;\n}\nexport interface ModelOption {\n id: string;\n name: string;\n provider: string;\n thinkingLevels?: readonly string[] | null;\n supportsImages: boolean;\n contextWindow: number;\n maxTokens: number;\n}\nexport interface ModelEditorState {\n providers: readonly ModelProviderOption[] | null;\n models: readonly ModelOption[] | null;\n selection: ModelSelection;\n disabled?: boolean;\n}\nexport interface ModelSelection {\n provider: string;\n model: string;\n thinkingLevel: string;\n}\nexport interface ModelEditorBlock extends UIBlock<ModelEditorState> {\n read(): ModelSelection;\n reset(selection: ModelSelection): void;\n focus(): void;\n}\nexport function thinkingLabel(level: string): string { return level === 'off' ? 'Thinking off' : `Thinking: ${level === 'xhigh' ? 'extra high' : level}`; }\nexport function modelEditorMarkup(prefix: string): string { prefix = escape(prefix); return `<label class=\"pui-field-label\" for=\"${prefix}-provider\">Provider</label><select class=\"pui-feature-select\" id=\"${prefix}-provider\" required disabled><option value=\"\">Loading providers…</option></select><label class=\"pui-field-label\" for=\"${prefix}-search\">Model</label><input id=\"${prefix}-search\" type=\"search\" placeholder=\"Search by model name or ID\" autocomplete=\"off\" /><label class=\"pui-sr-only\" for=\"${prefix}-model\">Choose model</label><select id=\"${prefix}-model\" class=\"pui-model-list\" size=\"6\" required disabled></select><p id=\"${prefix}-capabilities\" class=\"pui-field-hint\" aria-live=\"polite\"></p><label class=\"pui-field-label\" id=\"${prefix}-thinking-label\" for=\"${prefix}-thinking\">Thinking effort</label><select id=\"${prefix}-thinking\" class=\"pui-feature-select\" aria-describedby=\"${prefix}-capabilities\" required></select><p class=\"pui-field-hint\">Built-in models come from the Pith SDK catalog. Custom models use your saved definitions. Availability depends on your endpoint and account.</p>`; }\nexport function createModelEditor(initial: ModelEditorState, options: {\n prefix?: string;\n element?: HTMLElement;\n onChange?: (selection: ModelSelection) => void;\n} = {}): ModelEditorBlock {\n const prefix = options.prefix || uniqueId('pui-model');\n const element = options.element || document.createElement('div');\n if (!options.element) {\n element.className = 'pui-model-editor';\n element.innerHTML = modelEditorMarkup(prefix);\n }\n const field = <T extends HTMLElement = HTMLElement>(id: string) => { const result = Array.from(element.querySelectorAll<HTMLElement>('[id]')).find(node => node.id === prefix + '-' + id); if (!result)\n throw new Error(`Unknown model field: ${id}`); return result as T; };\n const provider = field<HTMLSelectElement>('provider'), model = field<HTMLSelectElement>('model'), search = field<HTMLInputElement>('search'), effort = field<HTMLSelectElement>('thinking');\n const parts = adoptProductParts(element), abort = new AbortController();\n let destroyed = false, initialized = false, signature = '', selected = '';\n let state: Readonly<ModelEditorState> = initial;\n const read = (): ModelSelection => ({ provider: parts.control(provider).getValue(), model: parts.control(model).getValue(), thinkingLevel: parts.control(effort).getValue() });\n const disabled = () => { parts.control(provider).update({ disabled: !!state.disabled || !state.providers?.length }); parts.control(model).update({ disabled: !!state.disabled || !model.options.length }); parts.control(effort).update({ disabled: !!state.disabled || effort.options.length < 2 }); parts.control(search).update({disabled:!!state.disabled}); };\n const capabilities = (preferred = effort.value) => {\n selected = model.value;\n const entry = (state.models || []).find(entry => entry.provider === provider.value && entry.id === selected);\n const levels = entry?.thinkingLevels?.length ? entry.thinkingLevels : ['off'];\n optionsInto(effort, levels.map(level => ({ value: level, label: thinkingLabel(level) })));\n effort.value = levels.includes(preferred) ? preferred : levels.includes('high') ? 'high' : levels.includes('medium') ? 'medium' : levels[0];\n effort.hidden = levels.length < 2;\n field('thinking-label').hidden = effort.hidden;\n field('capabilities').textContent = entry ? `${entry.supportsImages ? 'Text + images' : 'Text only'} · ${new Intl.NumberFormat('en').format(entry.contextWindow)} context tokens · ${new Intl.NumberFormat('en').format(entry.maxTokens)} max output tokens` : 'No matching models.';\n disabled();\n };\n const renderModels = (preferred = effort.value) => {\n const query = search.value.trim().toLowerCase();\n const entries = (state.models || []).filter(entry => entry.provider === provider.value && (entry.id === selected || `${entry.name} ${entry.id}`.toLowerCase().includes(query)));\n optionsInto(model, entries.map(entry => ({ value: entry.id, label: `${entry.name} — ${entry.id}` })));\n model.value = entries.some(entry => entry.id === selected) ? selected : entries[0]?.id || '';\n capabilities(preferred);\n };\n const chooseProvider = (selection?: ModelSelection) => {\n const entry = state.providers?.find(entry => entry.id === provider.value);\n search.value = '';\n selected = selection && selection.provider === provider.value ? selection.model : entry?.model || '';\n renderModels(selection && selection.provider === provider.value ? selection.thinkingLevel : entry?.thinkingLevel || 'high');\n };\n const reset = (selection: ModelSelection) => { if (destroyed)\n return; parts.control(provider).reset(state.providers?.some(entry => entry.id === selection.provider) ? selection.provider : state.providers?.[0]?.id || ''); chooseProvider(selection); };\n const update = (next: Readonly<ModelEditorState>) => {\n if (destroyed)\n return;\n const draft = read();\n state = next;\n const nextSignature = JSON.stringify([next.providers, next.models]);\n if (nextSignature !== signature) {\n signature = nextSignature;\n optionsInto(provider, (state.providers || []).map(entry => ({ value: entry.id, label: entry.name })));\n if (!initialized || !draft.provider)\n reset(next.selection);\n else {\n provider.value = state.providers?.some(entry => entry.id === draft.provider) ? draft.provider : state.providers?.[0]?.id || '';\n selected = draft.model;\n renderModels(draft.thinkingLevel);\n }\n initialized = true;\n }\n disabled();\n };\n provider.addEventListener('change', () => chooseProvider(), { signal: abort.signal });\n model.addEventListener('change', () => capabilities(), { signal: abort.signal });\n search.addEventListener('input', () => renderModels(), { signal: abort.signal });\n element.addEventListener('change', () => options.onChange?.(read()), { signal: abort.signal });\n update(initial);\n return { element, update, read, reset, focus() { parts.control(search).focus(); }, destroy() { if (destroyed)\n return; destroyed = true; abort.abort(); parts.destroy(); if (!options.element)\n element.remove(); } };\n}\n"]}
1
+ {"version":3,"file":"model-editor.js","sourceRoot":"","sources":["../../src/forms/model-editor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAC,iBAAiB,EAAC,sBAAsB,IAAI,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAgC1F,MAAM,UAAU,aAAa,CAAC,KAAa,IAAY,OAAO,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC3J,MAAM,UAAU,iBAAiB,CAAC,MAAc,IAAY,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,uCAAuC,MAAM,qEAAqE,MAAM,yHAAyH,MAAM,oCAAoC,MAAM,wHAAwH,MAAM,2CAA2C,MAAM,6EAA6E,MAAM,mGAAmG,MAAM,yBAAyB,MAAM,iDAAiD,MAAM,2DAA2D,MAAM,6MAA6M,CAAC,CAAC,CAAC;AAC/kC,MAAM,UAAU,iBAAiB,CAAC,OAAyB,EAAE,UAIzD,EAAE;IACF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,CAAC,SAAS,GAAG,kBAAkB,CAAC;QACvC,OAAO,CAAC,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,KAAK,GAAG,CAAsC,EAAU,EAAE,EAAE;QAAG,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAc,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC;QAAC,IAAI,CAAC,MAAM;YAClM,MAAM,IAAI,KAAK,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;QAAC,OAAO,MAAW,CAAC;IAAC,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,KAAK,CAAoB,UAAU,CAAC,EAAE,KAAK,GAAG,KAAK,CAAoB,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAmB,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAoB,UAAU,CAAC,CAAC;IAC5L,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,EAAE,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IACxE,IAAI,SAAS,GAAG,KAAK,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,GAAG,EAAE,EAAE,QAAQ,GAAG,EAAE,CAAC;IAC1E,IAAI,KAAK,GAA+B,OAAO,CAAC;IAChD,MAAM,IAAI,GAAG,GAAmB,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC/K,MAAM,QAAQ,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAC,QAAQ,EAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnW,MAAM,YAAY,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE,EAAE;QAC9C,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;QACvB,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,IAAI,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC7G,MAAM,MAAM,GAAG,KAAK,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9E,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1F,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1J,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAClC,KAAK,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC/C,KAAK,CAAC,cAAc,CAAC,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,qBAAqB,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC,CAAC,qBAAqB,CAAC;QACrR,QAAQ,EAAE,CAAC;IACf,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE,EAAE;QAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChL,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QACtG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3G,YAAY,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC,CAAC;IACF,MAAM,cAAc,GAAG,CAAC,SAA0B,EAAE,EAAE;QAClD,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC1E,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC;QAClB,QAAQ,GAAG,SAAS,IAAI,SAAS,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC;QACrG,YAAY,CAAC,SAAS,IAAI,SAAS,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,EAAE,aAAa,IAAI,MAAM,CAAC,CAAC;IAChI,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,SAAyB,EAAE,EAAE;QAAG,IAAI,SAAS;YACxD,OAAO;QAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAAC,CAAC,CAAC;IAC/L,MAAM,MAAM,GAAG,CAAC,IAAgC,EAAE,EAAE;QAChD,IAAI,SAAS;YACT,OAAO;QACX,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;QACrB,KAAK,GAAG,IAAI,CAAC;QACb,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACpE,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAC9B,SAAS,GAAG,aAAa,CAAC;YAC1B,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACtG,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAC/B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;iBACrB,CAAC;gBACF,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC7I,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;gBACvB,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YACtC,CAAC;YACD,WAAW,GAAG,IAAI,CAAC;QACvB,CAAC;QACD,QAAQ,EAAE,CAAC;IACf,CAAC,CAAC;IACF,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,cAAc,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACtF,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACjF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACjF,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/F,MAAM,CAAC,OAAO,CAAC,CAAC;IAChB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO;YAAK,IAAI,SAAS;gBACpG,OAAO;YAAC,SAAS,GAAG,IAAI,CAAC;YAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAAC,IAAI,CAAC,OAAO,CAAC,OAAO;gBAC9E,OAAO,CAAC,MAAM,EAAE,CAAC;QAAC,CAAC,EAAE,CAAC;AAClC,CAAC","sourcesContent":["import type { UIBlock } from '../core.js';\nimport { escape, uniqueId } from '../dom.js';\nimport {adoptProductParts,reconcileSelectOptions as optionsInto} from '../foundations.js';\nexport interface ModelProviderOption {\n id: string;\n name: string;\n model?: string;\n thinkingLevel?: string;\n}\nexport interface ModelOption {\n id: string;\n name: string;\n provider: string;\n thinkingLevels?: readonly string[] | null;\n supportsImages: boolean;\n contextWindow: number;\n maxTokens: number;\n}\nexport interface ModelEditorState {\n providers: readonly ModelProviderOption[] | null;\n models: readonly ModelOption[] | null;\n selection: ModelSelection;\n disabled?: boolean;\n}\nexport interface ModelSelection {\n provider: string;\n model: string;\n thinkingLevel: string;\n}\nexport interface ModelEditorBlock extends UIBlock<ModelEditorState> {\n read(): ModelSelection;\n reset(selection: ModelSelection): void;\n focus(): void;\n}\nexport function thinkingLabel(level: string): string { return level === 'off' ? 'Thinking off' : `Thinking: ${level === 'xhigh' ? 'extra high' : level}`; }\nexport function modelEditorMarkup(prefix: string): string { prefix = escape(prefix); return `<label class=\"pui-field-label\" for=\"${prefix}-provider\">Provider</label><select class=\"pui-feature-select\" id=\"${prefix}-provider\" required disabled><option value=\"\">Loading providers…</option></select><label class=\"pui-field-label\" for=\"${prefix}-search\">Model</label><input id=\"${prefix}-search\" type=\"search\" placeholder=\"Search by model name or ID\" autocomplete=\"off\" /><label class=\"pui-sr-only\" for=\"${prefix}-model\">Choose model</label><select id=\"${prefix}-model\" class=\"pui-model-list\" size=\"6\" required disabled></select><p id=\"${prefix}-capabilities\" class=\"pui-field-hint\" aria-live=\"polite\"></p><label class=\"pui-field-label\" id=\"${prefix}-thinking-label\" for=\"${prefix}-thinking\">Thinking effort</label><select id=\"${prefix}-thinking\" class=\"pui-feature-select\" aria-describedby=\"${prefix}-capabilities\" required></select><p class=\"pui-field-hint\">Built-in models come from the Pith SDK catalog. Custom models use your saved definitions. Availability depends on your endpoint and account.</p>`; }\nexport function createModelEditor(initial: ModelEditorState, options: {\n prefix?: string;\n element?: HTMLElement;\n onChange?: (selection: ModelSelection) => void;\n} = {}): ModelEditorBlock {\n const prefix = options.prefix || uniqueId('pui-model');\n const element = options.element || document.createElement('div');\n if (!options.element) {\n element.className = 'pui-model-editor';\n element.innerHTML = modelEditorMarkup(prefix);\n }\n const field = <T extends HTMLElement = HTMLElement>(id: string) => { const result = Array.from(element.querySelectorAll<HTMLElement>('[id]')).find(node => node.id === prefix + '-' + id); if (!result)\n throw new Error(`Unknown model field: ${id}`); return result as T; };\n const provider = field<HTMLSelectElement>('provider'), model = field<HTMLSelectElement>('model'), search = field<HTMLInputElement>('search'), effort = field<HTMLSelectElement>('thinking');\n const parts = adoptProductParts(element), abort = new AbortController();\n let destroyed = false, initialized = false, signature = '', selected = '';\n let state: Readonly<ModelEditorState> = initial;\n const read = (): ModelSelection => ({ provider: parts.control(provider).getValue(), model: parts.control(model).getValue(), thinkingLevel: parts.control(effort).getValue() });\n const disabled = () => { parts.control(provider).update({ disabled: !!state.disabled || !state.providers?.length }); parts.control(model).update({ disabled: !!state.disabled || !model.options.length }); parts.control(effort).update({ disabled: !!state.disabled || effort.options.length < 2 }); parts.control(search).update({disabled:!!state.disabled}); };\n const capabilities = (preferred = effort.value) => {\n selected = model.value;\n const entry = (state.models || []).find(entry => entry.provider === provider.value && entry.id === selected);\n const levels = entry?.thinkingLevels?.length ? entry.thinkingLevels : ['off'];\n optionsInto(effort, levels.map(level => ({ value: level, label: thinkingLabel(level) })));\n parts.control(effort).reset(levels.includes(preferred) ? preferred : levels.includes('high') ? 'high' : levels.includes('medium') ? 'medium' : levels[0]);\n effort.hidden = levels.length < 2;\n field('thinking-label').hidden = effort.hidden;\n field('capabilities').textContent = entry ? `${entry.supportsImages ? 'Text + images' : 'Text only'} · ${new Intl.NumberFormat('en').format(entry.contextWindow)} context tokens · ${new Intl.NumberFormat('en').format(entry.maxTokens)} max output tokens` : 'No matching models.';\n disabled();\n };\n const renderModels = (preferred = effort.value) => {\n const query = search.value.trim().toLowerCase();\n const entries = (state.models || []).filter(entry => entry.provider === provider.value && (entry.id === selected || `${entry.name} ${entry.id}`.toLowerCase().includes(query)));\n optionsInto(model, entries.map(entry => ({ value: entry.id, label: `${entry.name} — ${entry.id}` })));\n parts.control(model).reset(entries.some(entry => entry.id === selected) ? selected : entries[0]?.id || '');\n capabilities(preferred);\n };\n const chooseProvider = (selection?: ModelSelection) => {\n const entry = state.providers?.find(entry => entry.id === provider.value);\n search.value = '';\n selected = selection && selection.provider === provider.value ? selection.model : entry?.model || '';\n renderModels(selection && selection.provider === provider.value ? selection.thinkingLevel : entry?.thinkingLevel || 'high');\n };\n const reset = (selection: ModelSelection) => { if (destroyed)\n return; parts.control(provider).reset(state.providers?.some(entry => entry.id === selection.provider) ? selection.provider : state.providers?.[0]?.id || ''); chooseProvider(selection); };\n const update = (next: Readonly<ModelEditorState>) => {\n if (destroyed)\n return;\n const draft = read();\n state = next;\n const nextSignature = JSON.stringify([next.providers, next.models]);\n if (nextSignature !== signature) {\n signature = nextSignature;\n optionsInto(provider, (state.providers || []).map(entry => ({ value: entry.id, label: entry.name })));\n if (!initialized || !draft.provider)\n reset(next.selection);\n else {\n parts.control(provider).reset(state.providers?.some(entry => entry.id === draft.provider) ? draft.provider : state.providers?.[0]?.id || '');\n selected = draft.model;\n renderModels(draft.thinkingLevel);\n }\n initialized = true;\n }\n disabled();\n };\n provider.addEventListener('change', () => chooseProvider(), { signal: abort.signal });\n model.addEventListener('change', () => capabilities(), { signal: abort.signal });\n search.addEventListener('input', () => renderModels(), { signal: abort.signal });\n element.addEventListener('change', () => options.onChange?.(read()), { signal: abort.signal });\n update(initial);\n return { element, update, read, reset, focus() { parts.control(search).focus(); }, destroy() { if (destroyed)\n return; destroyed = true; abort.abort(); parts.destroy(); if (!options.element)\n element.remove(); } };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type ActionResult, type UIBlock } from '../core.js';
1
+ import { type ActionResult, type UIBlock, type UIAction } from '../core.js';
2
2
  import { type ModelEditorState, type ModelSelection } from './model-editor.js';
3
3
  export { modelEditorMarkup } from './model-editor.js';
4
4
  export interface FormFeedback {
@@ -142,5 +142,12 @@ export interface MCPConnectionItem {
142
142
  export interface MCPConnectionListState extends FormFeedback {
143
143
  entries: readonly MCPConnectionItem[];
144
144
  }
145
- export declare function createMCPConnectionList(initial: MCPConnectionListState): UIBlock<MCPConnectionListState>;
145
+ export type MCPConnectionAction = 'mcp-login' | 'mcp-logout' | 'mcp-edit' | 'mcp-toggle' | 'mcp-remove';
146
+ export interface MCPConnectionTarget {
147
+ readonly name: string;
148
+ }
149
+ export interface MCPConnectionListOptions {
150
+ onAction?: (action: MCPConnectionAction, target: MCPConnectionTarget) => ReturnType<UIAction>;
151
+ }
152
+ export declare function createMCPConnectionList(initial: MCPConnectionListState, options?: MCPConnectionListOptions): UIBlock<MCPConnectionListState>;
146
153
  //# sourceMappingURL=panels.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../src/forms/panels.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../src/forms/panels.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,10 @@
1
- import { Generation } from '../core.js';
1
+ import {} from '../core.js';
2
2
  import { scopeIds, bindFormSubmission } from './identity.js';
3
3
  import { dialogHeading, escape, icon, uniqueId, setText } from '../dom.js';
4
4
  import { createModelEditor, modelEditorMarkup } from './model-editor.js';
5
- import { adoptProductParts, reconcileSelectOptions } from '../foundations.js';
5
+ import { adoptAction, adoptProductParts, reconcileSelectOptions } from '../foundations.js';
6
+ import { createOperation } from '../operation.js';
7
+ import { reconcileKeyed } from '../reconcile.js';
6
8
  export { modelEditorMarkup } from './model-editor.js';
7
9
  function formBlock(markup, className, initial, prefix = '') {
8
10
  const element = document.createElement('div');
@@ -88,10 +90,14 @@ export function createSettingsPanel(state, options = {}) {
88
90
  <p class="pui-field-hint">Version, usage and failure category only; no conversation, file contents, paths or credentials.</p>
89
91
  <div class="pui-settings-actions"><button type="button" class="pui-secondary-button" data-action="diagnostics">Save diagnostics</button></div>
90
92
  </section>
91
- <div class="pui-modal-footer"><button class="pui-secondary-button" type="button" data-close="settings-dialog">Cancel</button><button class="pui-primary-button" id="save-settings" data-control-pending="true" disabled data-global-idle type="submit">Save settings</button></div>
93
+ <div class="pui-modal-footer"><button class="pui-secondary-button" type="button" data-pui-close data-close="settings-dialog">Cancel</button><button class="pui-primary-button" id="save-settings" data-control-pending="true" disabled data-global-idle type="submit">Save settings</button></div>
92
94
  </form>`, 'pui-settings-panel', state, options.idPrefix ?? uniqueId('pui-form') + '-');
93
- const $ = block.field, abort = new AbortController(), generation = new Generation();
94
- let current = state, pending = false, removing = false, destroyed = false;
95
+ const $ = block.field, abort = new AbortController();
96
+ let current = state, pending = false, removing = false, destroyed = false, operationKind = 'submit';
97
+ // These controls also exist before providers or appearance state have loaded.
98
+ // Adopt them eagerly so the first rendered frame uses the shared selector.
99
+ block.parts.control($('appearance-mode'));
100
+ block.parts.control($('settings-provider'));
95
101
  const form = $('settings-form'), submit = $('save-settings'), test = $('test-connection'), remove = $('remove-key');
96
102
  const read = () => { const key = $('api-key'); return { provider: block.parts.control($('settings-provider')).getValue(), baseUrl: block.parts.control($('base-url')).getValue().trim(), apiKey: key.disabled ? '' : block.parts.control(key).getValue().trim() }; };
97
103
  const update = (next) => {
@@ -99,9 +105,9 @@ export function createSettingsPanel(state, options = {}) {
99
105
  return;
100
106
  current = next;
101
107
  block.update(next);
102
- block.parts.action(submit).update({ disabled: next.disabled, pending: pending || !!next.testing || next.ready !== true });
103
- block.parts.action(test).update({ label: next.testing ? 'Cancel test' : 'Test connection', disabled: !!next.disabled || pending, pending: next.ready !== true });
104
- block.parts.action(remove).update({ disabled: !!next.disabled || pending, pending: removing });
108
+ block.parts.action(submit).update({ disabled: next.disabled, pending: pending || removing || !!next.testing || next.ready !== true });
109
+ block.parts.action(test).update({ label: next.testing ? 'Cancel test' : 'Test connection', disabled: !!next.disabled || pending || removing, pending: next.ready !== true });
110
+ block.parts.action(remove).update({ disabled: !!next.disabled || pending || !!next.testing || next.ready !== true, pending: removing });
105
111
  if (next.appearance) {
106
112
  const appearance = block.parts.control($('appearance-mode'));
107
113
  appearance.reset(next.appearance.mode);
@@ -114,31 +120,17 @@ export function createSettingsPanel(state, options = {}) {
114
120
  result.className = next.testResult.ok === undefined ? '' : next.testResult.ok ? 'pui-test-success' : 'pui-form-error';
115
121
  }
116
122
  };
117
- const run = async (action, kind) => {
118
- if (!action || pending || removing || current.disabled || current.testing || current.ready !== true)
123
+ const operation = createOperation({ unavailable: () => !!current.disabled || !!current.testing || current.ready !== true,
124
+ onPending(value) { pending = value && operationKind === 'submit'; removing = value && operationKind === 'remove'; update(current); },
125
+ onError(error) { update({ ...current, error }); } });
126
+ const run = (action, kind) => {
127
+ if (!action || operation.pending || current.disabled || current.testing || current.ready !== true)
119
128
  return;
120
- const seq = generation.next();
121
- if (kind === 'submit')
122
- pending = true;
123
- else
124
- removing = true;
125
- update({ ...current, error: '' });
126
- try {
127
- const result = await action(read());
128
- if (generation.current(seq) && !result.ok)
129
- update({ ...current, error: result.error });
130
- }
131
- catch (error) {
132
- if (generation.current(seq))
133
- update({ ...current, error: error instanceof Error ? error.message : String(error) });
134
- }
135
- finally {
136
- if (generation.current(seq)) {
137
- pending = false;
138
- removing = false;
139
- update(current);
140
- }
141
- }
129
+ if (kind === 'submit' && !form.reportValidity())
130
+ return;
131
+ operationKind = kind;
132
+ operation.run(() => { update({ ...current, error: '' }); return action(read()); }, result => { if (!result.ok)
133
+ update({ ...current, error: result.error }); });
142
134
  };
143
135
  form.addEventListener('submit', event => { if (options.onSubmit) {
144
136
  event.preventDefault();
@@ -156,7 +148,7 @@ export function createSettingsPanel(state, options = {}) {
156
148
  setProviders(providers, selected) { if (destroyed)
157
149
  return; const select = $('settings-provider'), previous = selected ?? select.value; reconcileSelectOptions(select, providers.map(provider => ({ value: provider.id, label: `${provider.name}${provider.signedIn ? ' · Signed in' : provider.configured ? ' · Configured' : ''}` })), providers.some(provider => provider.id === previous) ? previous : providers[0]?.id || ''); block.parts.control(select).update({ disabled: !providers.length }); },
158
150
  resetProvider(value) { if (destroyed)
159
- return; generation.invalidate(); pending = false; removing = false; update({ ...current, error: '' }); block.parts.control($('settings-provider')).reset(value.provider); block.parts.control($('base-url')).reset(value.baseUrl); if (value.clearKey)
151
+ return; operation.invalidate(); update({ ...current, error: '' }); block.parts.control($('settings-provider')).reset(value.provider); block.parts.control($('base-url')).reset(value.baseUrl); if (value.clearKey)
160
152
  block.parts.control($('api-key')).reset(''); if (value.collapseAdvanced)
161
153
  $('provider-advanced').open = false; },
162
154
  setCredential(view) { if (destroyed)
@@ -166,11 +158,11 @@ export function createSettingsPanel(state, options = {}) {
166
158
  actions.replaceChildren(); block.parts.update(); },
167
159
  clearSecrets() { block.parts.control($('api-key')).reset(''); },
168
160
  destroy() { if (destroyed)
169
- return; destroyed = true; generation.destroy(); abort.abort(); $('api-key').value = ''; block.destroy(); }
161
+ return; destroyed = true; operation.destroy(); abort.abort(); $('api-key').value = ''; block.destroy(); }
170
162
  };
171
163
  }
172
164
  export function createMCPConnectionsPanel(state = {}, options = {}) {
173
- const block = formBlock(`${dialogHeading('Connections', 'connections-title', 'connections-dialog', 'EXTERNAL TOOLS')}<p class="pui-modal-description">Add an MCP server to give Pith access to its tools. Enabled connections connect automatically when a task starts. Disable a connection to stop using it in tasks. External tools require approval unless this conversation has full access.</p><div class="pui-feature-toolbar"><button class="pui-secondary-button" data-action="refresh-mcp">Refresh</button></div><div id="mcp-list"><p class="pui-feature-hint">Loading connections…</p></div><div id="mcp-error" data-dialog-error class="pui-form-error" role="alert"></div><section class="pui-connection-editor"><div class="pui-section-heading"><span id="mcp-form-title">Add connection</span><button type="button" class="pui-secondary-button" data-action="new-mcp">New connection</button></div><form id="mcp-form"><label class="pui-field-label" for="mcp-name">Name</label><input id="mcp-name" name="name" required autocomplete="off" placeholder="my-tools" /><label class="pui-field-label" for="mcp-type">Connection type</label><select id="mcp-type" name="type" class="pui-feature-select"><option value="http">HTTP</option><option value="stdio">Local command (stdio)</option></select><div id="mcp-http-fields"><label class="pui-field-label" for="mcp-url">Server URL</label><input id="mcp-url" name="url" type="url" placeholder="https://example.com/mcp" autocomplete="off" /><label class="pui-checkbox-field"><input id="mcp-oauth" type="checkbox" />Sign in with OAuth</label><details class="pui-provider-advanced"><summary>OAuth settings (optional)</summary><label class="pui-field-label">Registered client ID<input id="mcp-oauth-client" /></label><label class="pui-field-label">Scopes<input id="mcp-oauth-scope" /></label><p class="pui-field-hint">Uses the server’s OAuth discovery and PKCE. The temporary callback listens on 127.0.0.1:54819.</p></details><label class="pui-field-label" for="mcp-token">Bearer token (optional)</label><input id="mcp-token" name="bearerToken" type="password" autocomplete="new-password" placeholder="Optional token" /><label class="pui-checkbox-field" id="mcp-clear-token-row" hidden><input id="mcp-clear-token" type="checkbox" />Remove saved bearer token</label><p class="pui-field-hint">Saved tokens are never returned to this page. Leave this field blank to keep an existing token.</p></div><div id="mcp-stdio-fields" hidden><label class="pui-field-label" for="mcp-command">Installed executable</label><input id="mcp-command" name="command" placeholder="/path/to/mcp-server" autocomplete="off" /><label class="pui-field-label" for="mcp-args">Arguments (JSON array)</label><textarea id="mcp-args" name="args" rows="3" spellcheck="false">[]</textarea><p class="pui-field-hint">The executable and any runtime it needs must already be installed on your computer. Pith Desk does not bundle external runtimes or a marketplace.</p><div class="pui-secret-label"><label class="pui-field-label" for="mcp-env">Environment overrides (JSON object, optional)</label><button class="pui-secondary-button" type="button" id="mcp-env-visibility" data-action="toggle-env" aria-controls="mcp-env" aria-pressed="false">Show</button></div><textarea id="mcp-env" class="pui-secret-field" name="env" rows="3" spellcheck="false" autocomplete="off" aria-describedby="mcp-env-hint" placeholder='{"API_KEY":"…"}'></textarea><p id="mcp-env-hint" class="pui-field-hint">Values stay private. Leave blank to keep saved overrides. Add a JSON object of string keys and values to set or replace individual overrides.</p><p id="mcp-env-keys" class="pui-field-hint" hidden></p><label class="pui-checkbox-field" id="mcp-clear-env-row" hidden><input id="mcp-clear-env" type="checkbox" />Clear saved environment overrides</label></div><label class="pui-checkbox-field"><input id="mcp-enabled" name="enabled" type="checkbox" checked />Enable this connection</label><div id="mcp-form-error" class="pui-form-error" role="alert"></div><div class="pui-modal-footer"><button class="pui-secondary-button" type="button" data-close="connections-dialog">Close</button><button class="pui-primary-button" type="submit" data-idle-action data-global-idle>Save connection</button></div></form></section>`, 'pui-mcp-connections', state, options.idPrefix ?? uniqueId('pui-form') + '-');
165
+ const block = formBlock(`${dialogHeading('Connections', 'connections-title', 'connections-dialog', 'EXTERNAL TOOLS')}<p class="pui-modal-description">Add an MCP server to give Pith access to its tools. Enabled connections connect automatically when a task starts. Disable a connection to stop using it in tasks. External tools require approval unless this conversation has full access.</p><div class="pui-feature-toolbar"><button type="button" class="pui-secondary-button" data-action="refresh-mcp">Refresh</button></div><div id="mcp-list"><p class="pui-feature-hint">Loading connections…</p></div><div id="mcp-error" data-dialog-error class="pui-form-error" role="alert"></div><section class="pui-connection-editor"><div class="pui-section-heading"><span id="mcp-form-title">Add connection</span><button type="button" class="pui-secondary-button" data-action="new-mcp">New connection</button></div><form id="mcp-form"><label class="pui-field-label" for="mcp-name">Name</label><input id="mcp-name" name="name" required autocomplete="off" placeholder="my-tools" /><label class="pui-field-label" for="mcp-type">Connection type</label><select id="mcp-type" name="type" class="pui-feature-select"><option value="http">HTTP</option><option value="stdio">Local command (stdio)</option></select><div id="mcp-http-fields"><label class="pui-field-label" for="mcp-url">Server URL</label><input id="mcp-url" name="url" type="url" placeholder="https://example.com/mcp" autocomplete="off" /><label class="pui-checkbox-field"><input id="mcp-oauth" type="checkbox" />Sign in with OAuth</label><details class="pui-provider-advanced"><summary>OAuth settings (optional)</summary><label class="pui-field-label">Registered client ID<input id="mcp-oauth-client" /></label><label class="pui-field-label">Scopes<input id="mcp-oauth-scope" /></label><p class="pui-field-hint">Uses the server’s OAuth discovery and PKCE. The temporary callback listens on 127.0.0.1:54819.</p></details><label class="pui-field-label" for="mcp-token">Bearer token (optional)</label><input id="mcp-token" name="bearerToken" type="password" autocomplete="new-password" placeholder="Optional token" /><label class="pui-checkbox-field" id="mcp-clear-token-row" hidden><input id="mcp-clear-token" type="checkbox" />Remove saved bearer token</label><p class="pui-field-hint">Saved tokens are never returned to this page. Leave this field blank to keep an existing token.</p></div><div id="mcp-stdio-fields" hidden><label class="pui-field-label" for="mcp-command">Installed executable</label><input id="mcp-command" name="command" placeholder="/path/to/mcp-server" autocomplete="off" /><label class="pui-field-label" for="mcp-args">Arguments (JSON array)</label><textarea id="mcp-args" name="args" rows="3" spellcheck="false">[]</textarea><p class="pui-field-hint">The executable and any runtime it needs must already be installed on your computer. Pith Desk does not bundle external runtimes or a marketplace.</p><div class="pui-secret-label"><label class="pui-field-label" for="mcp-env">Environment overrides (JSON object, optional)</label><button class="pui-secondary-button" type="button" id="mcp-env-visibility" data-action="toggle-env" aria-controls="mcp-env" aria-pressed="false">Show</button></div><textarea id="mcp-env" class="pui-secret-field" name="env" rows="3" spellcheck="false" autocomplete="off" aria-describedby="mcp-env-hint" placeholder='{"API_KEY":"…"}'></textarea><p id="mcp-env-hint" class="pui-field-hint">Values stay private. Leave blank to keep saved overrides. Add a JSON object of string keys and values to set or replace individual overrides.</p><p id="mcp-env-keys" class="pui-field-hint" hidden></p><label class="pui-checkbox-field" id="mcp-clear-env-row" hidden><input id="mcp-clear-env" type="checkbox" />Clear saved environment overrides</label></div><label class="pui-checkbox-field"><input id="mcp-enabled" name="enabled" type="checkbox" checked />Enable this connection</label><div id="mcp-form-error" class="pui-form-error" role="alert"></div><div class="pui-modal-footer"><button class="pui-secondary-button" type="button" data-pui-close data-close="connections-dialog">Close</button><button class="pui-primary-button" type="submit" data-idle-action data-global-idle>Save connection</button></div></form></section>`, 'pui-mcp-connections', state, options.idPrefix ?? uniqueId('pui-form') + '-');
174
166
  const $ = block.field;
175
167
  const abort = new AbortController();
176
168
  let disposed = false, pending = false, current = state;
@@ -181,7 +173,12 @@ export function createMCPConnectionsPanel(state = {}, options = {}) {
181
173
  return; current = next; block.update(next); if (next.formError !== undefined)
182
174
  block.parts.feedback($('mcp-form-error')).update({ message: next.formError, tone: 'error' }); block.parts.action(submit).update({ disabled: next.disabled, pending }); };
183
175
  const renderType = () => { if (disposed)
184
- return; const http = control('mcp-type').getValue() === 'http'; $('mcp-http-fields').hidden = !http; $('mcp-stdio-fields').hidden = http; control('mcp-url').update({ required: http }); control('mcp-command').update({ required: !http }); };
176
+ return; const http = control('mcp-type').getValue() === 'http'; for (const [id, active] of [['mcp-http-fields', http], ['mcp-stdio-fields', !http]]) {
177
+ const group = $(id);
178
+ group.hidden = !active;
179
+ for (const field of group.querySelectorAll('input,textarea'))
180
+ block.parts.control(field).update({ disabled: !active });
181
+ } control('mcp-url').update({ required: http }); control('mcp-command').update({ required: !http }); };
185
182
  const edit = (entry) => {
186
183
  if (disposed)
187
184
  return;
@@ -227,7 +224,7 @@ export function createMCPConnectionsPanel(state = {}, options = {}) {
227
224
  }
228
225
  export function createModelPicker(state = {}, options = {}) {
229
226
  const prefix = options.idPrefix ?? uniqueId('pui-form') + '-';
230
- const block = formBlock(`${dialogHeading('Choose a model', 'model-title', 'model-dialog', 'PITH MODEL CATALOG')}<form id="model-form">${modelEditorMarkup('picker')}<div id="model-error" class="pui-form-error" role="alert"></div><div class="pui-modal-footer"><button type="button" class="pui-secondary-button" data-close="model-dialog">Cancel</button><button type="submit" class="pui-primary-button" id="choose-model" data-global-idle data-control-pending="true" disabled>Use model</button></div></form>`, 'pui-model-picker', state, prefix);
227
+ const block = formBlock(`${dialogHeading('Choose a model', 'model-title', 'model-dialog', 'PITH MODEL CATALOG')}<form id="model-form">${modelEditorMarkup('picker')}<div id="model-error" class="pui-form-error" role="alert"></div><div class="pui-modal-footer"><button type="button" class="pui-secondary-button" data-pui-close data-close="model-dialog">Cancel</button><button type="submit" class="pui-primary-button" id="choose-model" data-global-idle data-control-pending="true" disabled>Use model</button></div></form>`, 'pui-model-picker', state, prefix);
231
228
  let editor;
232
229
  let destroyed = false, pending = false, current = state;
233
230
  const form = block.field('model-form'), submit = block.field('choose-model');
@@ -244,7 +241,7 @@ export function createModelPicker(state = {}, options = {}) {
244
241
  return { ...block, update, read, reset(selection) { submission.invalidate(); editor?.reset(selection); }, focus() { editor?.focus(); }, destroy() { if (destroyed)
245
242
  return; destroyed = true; submission.destroy(); editor?.destroy(); block.destroy(); } };
246
243
  }
247
- export function createMCPConnectionList(initial) {
244
+ export function createMCPConnectionList(initial, options = {}) {
248
245
  const element = document.createElement('div');
249
246
  element.className = 'pui-mcp-connection-list';
250
247
  const parts = adoptProductParts(element);
@@ -253,7 +250,7 @@ export function createMCPConnectionList(initial) {
253
250
  const empty = document.createElement('p');
254
251
  empty.className = 'pui-feature-hint';
255
252
  empty.textContent = 'No connections yet. Add an HTTP server or an installed local MCP command below. Tools are discovered on demand using tool search and Codemode.';
256
- function createEntry() {
253
+ function createEntry(item) {
257
254
  const root = document.createElement('article');
258
255
  root.className = 'pui-connection-card';
259
256
  root.innerHTML = '<div class="pui-connection-card-heading"><strong></strong></div><p class="pui-file-path"></p><p class="pui-feature-hint"></p><p class="pui-connection-status" role="status"></p><p class="pui-feature-hint" hidden></p><p class="pui-form-error"></p><div class="pui-file-actions"></div>';
@@ -272,58 +269,51 @@ export function createMCPConnectionList(initial) {
272
269
  node.dataset.idleAction = '';
273
270
  }
274
271
  actions.append(edit, toggle, remove);
275
- return { element: root, name: root.querySelector('strong'), address: paragraphs[0], enabled: paragraphs[1], status: paragraphs[2], env: paragraphs[3], error: paragraphs[4], actions, signIn, signOut, edit, toggle, remove };
272
+ const entry = { element: root, name: root.querySelector('strong'), address: paragraphs[0], enabled: paragraphs[1], status: paragraphs[2], env: paragraphs[3], error: paragraphs[4], actions, signIn, signOut, edit, toggle, remove, handles: new Map(), abort: new AbortController(), localError: '' };
273
+ const target = Object.freeze({ name: item.name });
274
+ for (const [node, action] of [[signIn, 'mcp-login'], [signOut, 'mcp-logout'], [edit, 'mcp-edit'], [toggle, 'mcp-toggle'], [remove, 'mcp-remove']]) {
275
+ if (options.onAction)
276
+ node.addEventListener('click', event => event.stopPropagation(), { signal: entry.abort.signal });
277
+ entry.handles.set(node, adoptAction(node, { onAction: options.onAction ? () => { entry.localError = ''; parts.feedback(entry.error).update({ message: '', tone: 'error' }); return options.onAction(action, target); } : undefined, onError(message) { entry.localError = message; parts.feedback(entry.error).update({ message, tone: 'error' }); } }));
278
+ }
279
+ return entry;
276
280
  }
281
+ const release = (entry) => { entry.abort.abort(); for (const handle of entry.handles.values())
282
+ handle.destroy(); };
277
283
  const update = (state) => {
278
284
  if (destroyed)
279
285
  return;
280
- const current = new Set();
281
- let cursor = element.firstElementChild;
282
- for (const item of state.entries) {
283
- current.add(item.name);
284
- let entry = entries.get(item.name);
285
- if (!entry) {
286
- entry = createEntry();
287
- entries.set(item.name, entry);
288
- }
289
- setText(entry.name, item.name);
290
- entry.element.dataset.connectionKey = item.name;
291
- setText(entry.address, item.type === 'http' ? item.url || '' : [item.command, ...(item.args || [])].join(' '));
292
- setText(entry.enabled, `${item.enabled ? 'Enabled' : 'Disabled'}${item.hasBearerToken ? ' · Token configured' : ''}`);
293
- setText(entry.status, item.statusLabel);
294
- entry.status.classList.toggle('pui-is-error', item.enabled && item.status === 'error');
295
- entry.env.hidden = !item.envKeys?.length;
296
- setText(entry.env, item.envKeys?.length ? 'Saved environment keys: ' + item.envKeys.join(', ') : '');
297
- parts.feedback(entry.error).update({ message: item.error || '', tone: 'error' });
298
- setText(entry.signIn, item.signedIn ? 'Sign in again' : 'Sign in');
299
- entry.signIn.dataset.id = entry.signOut.dataset.id = item.name;
300
- entry.edit.dataset.mcpEdit = item.name;
301
- entry.toggle.dataset.mcpToggle = item.name;
302
- entry.remove.dataset.mcpRemove = item.name;
303
- setText(entry.toggle, item.enabled ? 'Disable' : 'Enable');
304
- if (item.oauth) {
305
- if (entry.signIn.parentElement !== entry.actions)
306
- entry.actions.insertBefore(entry.signIn, entry.edit);
307
- }
308
- else
309
- entry.signIn.remove();
310
- if (item.oauth && item.signedIn) {
311
- if (entry.signOut.parentElement !== entry.actions)
312
- entry.actions.insertBefore(entry.signOut, entry.edit);
313
- }
314
- else
315
- entry.signOut.remove();
316
- for (const button of [entry.signIn, entry.signOut, entry.edit, entry.toggle, entry.remove])
317
- parts.action(button).update({ disabled: !!state.disabled });
318
- if (entry.element !== cursor)
319
- element.insertBefore(entry.element, cursor);
320
- cursor = entry.element.nextElementSibling;
321
- }
322
- for (const [key, entry] of entries)
323
- if (!current.has(key)) {
324
- entry.element.remove();
325
- entries.delete(key);
326
- }
286
+ reconcileKeyed(element, entries, state.entries, { key: item => item.name, element: entry => entry.element, create: createEntry, update(entry, item) {
287
+ setText(entry.name, item.name);
288
+ entry.element.dataset.connectionKey = item.name;
289
+ setText(entry.address, item.type === 'http' ? item.url || '' : [item.command, ...(item.args || [])].join(' '));
290
+ setText(entry.enabled, `${item.enabled ? 'Enabled' : 'Disabled'}${item.hasBearerToken ? ' · Token configured' : ''}`);
291
+ setText(entry.status, item.statusLabel);
292
+ entry.status.classList.toggle('pui-is-error', item.enabled && item.status === 'error');
293
+ entry.env.hidden = !item.envKeys?.length;
294
+ setText(entry.env, item.envKeys?.length ? 'Saved environment keys: ' + item.envKeys.join(', ') : '');
295
+ parts.feedback(entry.error).update({ message: item.error || entry.localError, tone: 'error' });
296
+ setText(entry.signIn, item.signedIn ? 'Sign in again' : 'Sign in');
297
+ entry.signIn.dataset.id = entry.signOut.dataset.id = item.name;
298
+ entry.edit.dataset.mcpEdit = item.name;
299
+ entry.toggle.dataset.mcpToggle = item.name;
300
+ entry.remove.dataset.mcpRemove = item.name;
301
+ setText(entry.toggle, item.enabled ? 'Disable' : 'Enable');
302
+ if (item.oauth) {
303
+ if (entry.signIn.parentElement !== entry.actions)
304
+ entry.actions.insertBefore(entry.signIn, entry.edit);
305
+ }
306
+ else
307
+ entry.signIn.remove();
308
+ if (item.oauth && item.signedIn) {
309
+ if (entry.signOut.parentElement !== entry.actions)
310
+ entry.actions.insertBefore(entry.signOut, entry.edit);
311
+ }
312
+ else
313
+ entry.signOut.remove();
314
+ for (const [button, handle] of entry.handles)
315
+ handle.update({ disabled: !!state.disabled || (button === entry.signIn && !item.oauth) || (button === entry.signOut && (!item.oauth || !item.signedIn)) });
316
+ }, destroy: release });
327
317
  if (!state.entries.length) {
328
318
  if (empty.parentElement !== element)
329
319
  element.append(empty);
@@ -334,6 +324,7 @@ export function createMCPConnectionList(initial) {
334
324
  };
335
325
  update(initial);
336
326
  return { element, update, destroy() { if (destroyed)
337
- return; destroyed = true; parts.destroy(); entries.clear(); element.remove(); } };
327
+ return; destroyed = true; for (const entry of entries.values())
328
+ release(entry); parts.destroy(); entries.clear(); element.remove(); } };
338
329
  }
339
330
  //# sourceMappingURL=panels.js.map