@agent-native/core 0.7.71 → 0.7.73

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 (51) hide show
  1. package/dist/a2a/artifact-response.d.ts.map +1 -1
  2. package/dist/a2a/artifact-response.js +140 -9
  3. package/dist/a2a/artifact-response.js.map +1 -1
  4. package/dist/a2a/handlers.d.ts.map +1 -1
  5. package/dist/a2a/handlers.js +9 -1
  6. package/dist/a2a/handlers.js.map +1 -1
  7. package/dist/a2a/task-store.d.ts +1 -0
  8. package/dist/a2a/task-store.d.ts.map +1 -1
  9. package/dist/a2a/task-store.js +22 -4
  10. package/dist/a2a/task-store.js.map +1 -1
  11. package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
  12. package/dist/client/NewWorkspaceAppFlow.js +18 -56
  13. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  14. package/dist/client/composer/ComposerPlusMenu.d.ts +9 -1
  15. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  16. package/dist/client/composer/ComposerPlusMenu.js +10 -1
  17. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  18. package/dist/client/composer/PromptComposer.d.ts +40 -0
  19. package/dist/client/composer/PromptComposer.d.ts.map +1 -0
  20. package/dist/client/composer/PromptComposer.js +124 -0
  21. package/dist/client/composer/PromptComposer.js.map +1 -0
  22. package/dist/client/composer/TiptapComposer.d.ts +14 -3
  23. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  24. package/dist/client/composer/TiptapComposer.js +8 -4
  25. package/dist/client/composer/TiptapComposer.js.map +1 -1
  26. package/dist/client/composer/index.d.ts +1 -0
  27. package/dist/client/composer/index.d.ts.map +1 -1
  28. package/dist/client/composer/index.js +1 -0
  29. package/dist/client/composer/index.js.map +1 -1
  30. package/dist/client/index.d.ts +1 -0
  31. package/dist/client/index.d.ts.map +1 -1
  32. package/dist/client/index.js +1 -0
  33. package/dist/client/index.js.map +1 -1
  34. package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
  35. package/dist/client/settings/AutomationsSection.js +7 -14
  36. package/dist/client/settings/AutomationsSection.js.map +1 -1
  37. package/dist/client/tools/EmbeddedTool.d.ts.map +1 -1
  38. package/dist/client/tools/EmbeddedTool.js +50 -5
  39. package/dist/client/tools/EmbeddedTool.js.map +1 -1
  40. package/dist/client/tools/ToolViewer.d.ts.map +1 -1
  41. package/dist/client/tools/ToolViewer.js +58 -17
  42. package/dist/client/tools/ToolViewer.js.map +1 -1
  43. package/dist/client/tools/ToolsListPage.d.ts.map +1 -1
  44. package/dist/client/tools/ToolsListPage.js +17 -39
  45. package/dist/client/tools/ToolsListPage.js.map +1 -1
  46. package/dist/client/tools/ToolsSidebarSection.d.ts.map +1 -1
  47. package/dist/client/tools/ToolsSidebarSection.js +6 -14
  48. package/dist/client/tools/ToolsSidebarSection.js.map +1 -1
  49. package/dist/deploy/workspace-deploy.js +7 -1
  50. package/dist/deploy/workspace-deploy.js.map +1 -1
  51. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"NewWorkspaceAppFlow.js","sourceRoot":"","sources":["../../src/client/NewWorkspaceAppFlow.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,eAAe,EACf,QAAQ,EACR,OAAO,EACP,WAAW,EACX,QAAQ,GACT,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gCAAgC,EAAE,MAAM,+BAA+B,CAAC;AAgBjF,MAAM,gBAAgB,GAAG;IACvB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;IACtC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;IAC1C,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;IACxC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;IACtC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACpC,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;IACxC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;IAClC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAChC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACpC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACpC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;CAC1B,CAAC;AAEX,SAAS,OAAO,CAAC,KAAa;IAC5B,OAAO,KAAK;SACT,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,eAAe,CAAC,MAAc;IACrC,MAAM,OAAO,GAAG,MAAM;SACnB,OAAO,CAAC,sDAAsD,EAAE,GAAG,CAAC;SACpE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;IACV,OAAO,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC,IAAI,SAAS,CAAC;AACpD,CAAC;AAED,SAAS,SAAS,CAAC,QAAuB,EAAE,MAAc;IACxD,MAAM,IAAI,GAAG,0BAA0B,MAAM,EAAE,CAAC;IAChD,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAChD,OAAO,GAAG,UAAU,GAAG,IAAI,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,uBAAuB,CAAC,SAAkB;IACjD,IAAI,SAAS,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,IAAkB;IACtD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,OAAO,IAAI,kBAAkB,GAAG,CAAC,MAAM,EAAE,CAC/D,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,0BAA0B,CAAC,KAKnC;IACC,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,OAAO;QAC1B,CAAC,CAAC,qDAAqD,OAAO,EAAE;QAChE,CAAC,CAAC,wDAAwD,CAAC;IAE7D,OAAO;QACL,kDAAkD;QAClD,EAAE;QACF,aAAa,KAAK,CAAC,KAAK,EAAE;QAC1B,2BAA2B,KAAK,CAAC,QAAQ,EAAE;QAC3C,gBAAgB,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE;QACrC,YAAY;QACZ,EAAE;QACF,sDAAsD,KAAK,CAAC,KAAK,kBAAkB,KAAK,CAAC,KAAK,4IAA4I;QAC1O,OAAO;YACL,CAAC,CAAC,0EAA0E,KAAK,CAAC,KAAK,gIAAgI;YACvN,CAAC,CAAC,kEAAkE;QACtE,EAAE;QACF,gDAAgD;QAChD,qDAAqD,KAAK,CAAC,KAAK,6HAA6H,KAAK,CAAC,KAAK,sBAAsB;QAC9N,4JAA4J;QAC5J,wHAAwH;QACxH,sHAAsH;QACtH,wFAAwF,KAAK,CAAC,KAAK,GAAG;KACvG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,EAClC,SAAS,GAAG,SAAS,EACrB,SAAS,GAAG,EAAE,EACd,gBAAgB,GACS;IACzB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAC3B,QAAQ,CAA6C,SAAS,CAAC,CAAC;IAClE,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAW,EAAE,CAAC,CAAC;IACzE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAsB,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAChE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE,CAAC;IAEnC,MAAM,yBAAyB,GAC7B,gBAAgB,KAAK,SAAS;QAC5B,CAAC,CAAC,uBAAuB,CAAC,SAAS,CAAC;QACpC,CAAC,CAAC,gBAAgB,CAAC;IAEvB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,MAAM,GAAG,GAAG,SAAS,CACnB,yBAAyB,EACzB,2BAA2B,CAC5B,CAAC;QACF,SAAS,CAAC,GAAG,CAAC;aACX,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACb,IAAI,SAAS;gBAAE,OAAO;YACtB,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5C,eAAe,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,IAAI,SAAS;gBAAE,OAAO;YACtB,UAAU,CAAC,EAAE,CAAC,CAAC;YACf,eAAe,CAAC,GAAG,EAAE,OAAO,IAAI,8BAA8B,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,CAAC;IAEhC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,OAAO;QACtC,UAAU,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;IACtC,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEtB,MAAM,eAAe,GAAG,OAAO,CAC7B,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EACvE,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAC7B,CAAC;IACF,MAAM,mBAAmB,GACvB,iBAAiB,CAAC,MAAM,KAAK,CAAC;QAC5B,CAAC,CAAC,kBAAkB;QACpB,CAAC,CAAC,GAAG,iBAAiB,CAAC,MAAM,OAAO,iBAAiB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC;IAC7F,MAAM,mBAAmB,GACvB,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,mBAAmB;QACtC,CAAC,CAAC,gCAAgC,CAAC,WAAW,CAAC;QAC/C,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,SAAS,GACb,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC;IACtE,MAAM,cAAc,GAClB,OAAO,SAAS,KAAK,WAAW;QAChC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;QACzC,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,MAAM,CAAC;IAEb,SAAS,YAAY;QACnB,OAAO,0BAA0B,CAAC;YAChC,KAAK,EAAE,WAAW;YAClB,MAAM;YACN,QAAQ;YACR,YAAY,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;SAC1D,CAAC,CAAC;IACL,CAAC;IAED,KAAK,UAAU,MAAM;QACnB,IAAI,CAAC,SAAS,IAAI,YAAY;YAAE,OAAO;QACvC,MAAM,eAAe,GAAG,gCAAgC,CAAC,WAAW,CAAC,CAAC;QACtE,IAAI,eAAe,EAAE,CAAC;YACpB,gBAAgB,CAAC,eAAe,CAAC,CAAC;YAClC,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;QAC/B,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,YAAY,CAAC,IAAI,CAAC,CAAC;QAEnB,IAAI,CAAC;YACH,IAAI,gBAAgB,EAAE,EAAE,CAAC;gBACvB,eAAe,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBACzD,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;YAC5C,CAAC;iBAAM,IAAI,SAAS,EAAE,CAAC;gBACrB,eAAe,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvE,gBAAgB,CAAC,0BAA0B,CAAC,CAAC;YAC/C,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,GAAG,MAAM,SAAS,CAC5B,SAAS,CAAC,yBAAyB,EAAE,8BAA8B,CAAC,EACpE;oBACE,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;oBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;wBACrB,KAAK,EAAE,WAAW;wBAClB,QAAQ;wBACR,SAAS,EAAE,iBAAiB;qBAC7B,CAAC;iBACH,CACF,CAAC;gBACF,IAAI,MAAM,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;oBAC/B,YAAY,CAAC,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC;oBAClC,gBAAgB,CAAC,yBAAyB,CAAC,CAAC;gBAC9C,CAAC;qBAAM,CAAC;oBACN,gBAAgB,CACd,MAAM,EAAE,OAAO;wBACb,6GAA6G,CAChH,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,gBAAgB,CAAC,GAAG,EAAE,OAAO,IAAI,mCAAmC,CAAC,CAAC;QACxE,CAAC;gBAAS,CAAC;YACT,eAAe,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,SAAS,YAAY,CAAC,EAAU;QAC9B,oBAAoB,CAAC,CAAC,OAAO,EAAE,EAAE,CAC/B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,EAAE,CAAC;YAC/C,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,EAAE,CAAC,CACrB,CAAC;IACJ,CAAC;IAED,OAAO,CACL,kBACE,SAAS,EAAE,0DAA0D,SAAS,EAAE,YAEhF,eAAK,SAAS,EAAC,+CAA+C,aAC5D,eAAK,SAAS,EAAC,yCAAyC,aACtD,cAAK,SAAS,EAAC,kCAAkC,YAC/C,eAAK,SAAS,EAAC,6CAA6C,aAC1D,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,eAE5B,GACF,EACN,eAAK,SAAS,EAAC,eAAe,aAC5B,iBAAO,SAAS,EAAC,iBAAiB,aAChC,eAAM,SAAS,EAAC,2CAA2C,uBAEpD,EACP,mBACE,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC1C,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;gDACf,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;oDAClD,CAAC,CAAC,cAAc,EAAE,CAAC;oDACnB,MAAM,EAAE,CAAC;gDACX,CAAC;4CACH,CAAC,EACD,WAAW,EAAC,yDAAyD,EACrE,IAAI,EAAE,CAAC,EACP,SAAS,EAAC,2HAA2H,GACrI,IACI,EAER,eAAK,SAAS,EAAC,2BAA2B,aACxC,iBAAO,SAAS,EAAC,iBAAiB,aAChC,eAAM,SAAS,EAAC,2CAA2C,yBAEpD,EACP,gBACE,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EACpD,WAAW,EAAC,iBAAiB,EAC7B,SAAS,EAAE,2FACT,YAAY,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,cACxC,EAAE,GACF,EACD,YAAY,CAAC,CAAC,CAAC,CACd,eAAM,SAAS,EAAC,gCAAgC,YAC7C,YAAY,GACR,CACR,CAAC,CAAC,CAAC,IAAI,IACF,EACR,iBAAO,SAAS,EAAC,iBAAiB,aAChC,eAAM,SAAS,EAAC,2CAA2C,iCAEpD,EACP,iBACE,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CACd,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,KAAwB,CAAC,EAEhD,SAAS,EAAC,sGAAsG,YAE/G,gBAAgB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAChC,iBAA2B,KAAK,EAAE,MAAM,CAAC,KAAK,YAC3C,MAAM,CAAC,KAAK,IADF,MAAM,CAAC,KAAK,CAEhB,CACV,CAAC,GACK,IACH,IACJ,EAEN,eAAK,SAAS,EAAC,qCAAqC,aAClD,gBAAM,SAAS,EAAC,sCAAsC,aACnD,cAAc,wBACV,EACP,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,SAAS,IAAI,YAAY,EACpC,SAAS,EAAC,uJAAuJ,aAEhK,YAAY,CAAC,CAAC,CAAC,CACd,KAAC,WAAW,IAAC,SAAS,EAAC,sBAAsB,GAAG,CACjD,CAAC,CAAC,CAAC,CACF,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,CACjC,kBAEM,IACL,EAEL,aAAa,CAAC,CAAC,CAAC,CACf,eAAK,SAAS,EAAC,qFAAqF,aACjG,aAAa,EACb,SAAS,CAAC,CAAC,CAAC,CACX,aACE,IAAI,EAAE,SAAS,EACf,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAChB,SAAS,EAAC,2EAA2E,6BAEzE,KAAC,gBAAgB,IAAC,SAAS,EAAC,SAAS,GAAG,IAClD,CACL,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC,CAAC,CAAC,IAAI,IACJ,IACF,EAEN,iBAAO,SAAS,EAAC,yCAAyC,aACxD,cAAK,SAAS,EAAC,kCAAkC,YAC/C,eAAK,SAAS,EAAC,yCAAyC,aACtD,eAAK,SAAS,EAAC,6CAA6C,aAC1D,KAAC,OAAO,IAAC,SAAS,EAAC,SAAS,GAAG,qBAE3B,EACN,eAAM,SAAS,EAAC,sGAAsG,YACnH,mBAAmB,GACf,IACH,GACF,EACN,cAAK,SAAS,EAAC,6CAA6C,YACzD,YAAY,CAAC,CAAC,CAAC,CACd,YAAG,SAAS,EAAC,uFAAuF,YACjG,YAAY,GACX,CACL,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACzB,YAAG,SAAS,EAAC,uFAAuF,kDAEhG,CACL,CAAC,CAAC,CAAC,CACF,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;gCACrB,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gCACvD,OAAO,CACL,eAEE,SAAS,EAAE,8CACT,QAAQ;wCACN,CAAC,CAAC,kGAAkG;wCACpG,CAAC,CAAC,oGACN,EAAE,aAEF,kBACE,IAAI,EAAC,QAAQ,kBACC,QAAQ,EACtB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,EACtC,SAAS,EAAC,yIAAyI,aAEnJ,eACE,SAAS,EAAE,sFACT,QAAQ;wDACN,CAAC,CAAC,8CAA8C;wDAChD,CAAC,CAAC,oFACN,EAAE,YAED,QAAQ,CAAC,CAAC,CAAC,KAAC,SAAS,IAAC,SAAS,EAAC,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,GAC/C,EACP,gBAAM,SAAS,EAAC,gBAAgB,aAC9B,eAAM,SAAS,EAAC,4BAA4B,YACzC,MAAM,CAAC,aAAa,GAChB,EACP,eAAM,SAAS,EAAC,iDAAiD,YAC9D,QAAQ;gEACP,CAAC,CAAC,gCAAgC;gEAClC,CAAC,CAAC,kBAAkB,GACjB,IACF,IACA,EACT,mBAAS,SAAS,EAAC,4GAA4G,aAC7H,mBAAS,SAAS,EAAC,+HAA+H,aAChJ,KAAC,eAAe,IAAC,SAAS,EAAC,4DAA4D,GAAG,eAElF,EACV,eAAK,SAAS,EAAC,8BAA8B,aAC3C,eAAK,SAAS,EAAC,UAAU,2BACZ,MAAM,CAAC,QAAQ,IAAI,eAAe,IACzC,EACN,eAAK,SAAS,EAAC,UAAU,uBAAQ,MAAM,CAAC,IAAI,IAAO,IAC/C,IACE,KA5CL,MAAM,CAAC,EAAE,CA6CV,CACP,CAAC;4BACJ,CAAC,CAAC,CACH,GACG,IACA,IACJ,GACE,CACX,CAAC;AACJ,CAAC","sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport {\n IconArrowUpRight,\n IconCheck,\n IconChevronDown,\n IconCode,\n IconKey,\n IconLoader2,\n IconPlus,\n} from \"@tabler/icons-react\";\nimport { agentNativePath, appBasePath } from \"./api-path.js\";\nimport { sendToAgentChat } from \"./agent-chat.js\";\nimport { isInBuilderFrame } from \"./builder-frame.js\";\nimport { useDevMode } from \"./use-dev-mode.js\";\nimport { getWorkspaceAppIdValidationError } from \"../shared/workspace-app-id.js\";\n\nexport interface VaultSecretOption {\n id: string;\n name: string;\n credentialKey: string;\n provider?: string | null;\n description?: string | null;\n}\n\nexport interface NewWorkspaceAppFlowProps {\n sourceApp?: string;\n className?: string;\n dispatchBasePath?: string | null;\n}\n\nconst TEMPLATE_OPTIONS = [\n { value: \"starter\", label: \"Starter\" },\n { value: \"analytics\", label: \"Analytics\" },\n { value: \"calendar\", label: \"Calendar\" },\n { value: \"content\", label: \"Content\" },\n { value: \"design\", label: \"Design\" },\n { value: \"dispatch\", label: \"Dispatch\" },\n { value: \"forms\", label: \"Forms\" },\n { value: \"mail\", label: \"Mail\" },\n { value: \"slides\", label: \"Slides\" },\n { value: \"videos\", label: \"Videos\" },\n { value: \"clips\", label: \"Clips\" },\n] as const;\n\nfunction slugify(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/^[^a-z]+/, \"\")\n .slice(0, 48);\n}\n\nfunction titleFromPrompt(prompt: string): string {\n const cleaned = prompt\n .replace(/\\b(build|create|make|an?|the|app|tool|dashboard)\\b/gi, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n return slugify(cleaned || \"new-app\") || \"new-app\";\n}\n\nfunction actionUrl(basePath: string | null, action: string): string {\n const path = `/_agent-native/actions/${action}`;\n if (basePath === null) return agentNativePath(path);\n const normalized = basePath.replace(/\\/+$/, \"\");\n return `${normalized}${path}`;\n}\n\nfunction defaultDispatchBasePath(sourceApp?: string): string | null {\n if (sourceApp === \"dispatch\") return null;\n const base = appBasePath();\n if (base === \"/dispatch\") return null;\n return \"/dispatch\";\n}\n\nasync function fetchJson(url: string, init?: RequestInit): Promise<any> {\n const res = await fetch(url, init);\n const data = await res.json().catch(() => null);\n if (!res.ok) {\n throw new Error(\n data?.error || data?.message || `Request failed ${res.status}`,\n );\n }\n return data;\n}\n\nfunction buildNewWorkspaceAppPrompt(input: {\n appId: string;\n prompt: string;\n template: string;\n selectedKeys: string[];\n}): string {\n const keyList = input.selectedKeys.join(\", \");\n const grantRequest = keyList\n ? `Requested Dispatch vault key grants for this app: ${keyList}`\n : `Requested Dispatch vault key grants for this app: none`;\n\n return [\n `Create a new agent-native app in this workspace.`,\n ``,\n `App name: ${input.appId}`,\n `Template to start from: ${input.template}`,\n `User prompt: ${input.prompt.trim()}`,\n grantRequest,\n ``,\n `Use the workspace app layout: create it under apps/${input.appId}, mount it at /${input.appId}, keep it on the shared workspace database/hosting model, and avoid table-name collisions by namespacing any new domain tables to the app.`,\n keyList\n ? `After the app exists, grant the selected Dispatch vault keys to appId \"${input.appId}\" and sync them once the app server is available. Treat these as requested grants, not active grants before creation succeeds.`\n : `Do not grant any Dispatch vault keys unless the user asks later.`,\n ``,\n `App readiness requirements before handing off:`,\n `- Update the workspace app registry metadata for \"${input.appId}\" (workspace-apps.json or .agent-native/workspace-apps.json, whichever this workspace uses) so Dispatch lists the app at /${input.appId} after merge/deploy.`,\n `- Update the app manifest/package/deploy metadata needed by the existing workspace deployment model; do not leave the app relying only on local discovery.`,\n `- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment.`,\n `- Include a final verification note covering the registry entry, manifest/deploy metadata, and agent-card readiness.`,\n `When it is ready, start or update the workspace dev server and navigate the user to /${input.appId}.`,\n ].join(\"\\n\");\n}\n\nexport function NewWorkspaceAppFlow({\n sourceApp = \"starter\",\n className = \"\",\n dispatchBasePath,\n}: NewWorkspaceAppFlowProps) {\n const [prompt, setPrompt] = useState(\"\");\n const [appName, setAppName] = useState(\"\");\n const [template, setTemplate] =\n useState<(typeof TEMPLATE_OPTIONS)[number][\"value\"]>(\"starter\");\n const [selectedSecretIds, setSelectedSecretIds] = useState<string[]>([]);\n const [secrets, setSecrets] = useState<VaultSecretOption[]>([]);\n const [secretsError, setSecretsError] = useState<string | null>(null);\n const [statusMessage, setStatusMessage] = useState<string | null>(null);\n const [branchUrl, setBranchUrl] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const { isDevMode } = useDevMode();\n\n const effectiveDispatchBasePath =\n dispatchBasePath === undefined\n ? defaultDispatchBasePath(sourceApp)\n : dispatchBasePath;\n\n useEffect(() => {\n let cancelled = false;\n const url = actionUrl(\n effectiveDispatchBasePath,\n \"list-vault-secret-options\",\n );\n fetchJson(url)\n .then((data) => {\n if (cancelled) return;\n setSecrets(Array.isArray(data) ? data : []);\n setSecretsError(null);\n })\n .catch((err) => {\n if (cancelled) return;\n setSecrets([]);\n setSecretsError(err?.message || \"Could not load Dispatch keys\");\n });\n return () => {\n cancelled = true;\n };\n }, [effectiveDispatchBasePath]);\n\n useEffect(() => {\n if (appName || !prompt.trim()) return;\n setAppName(titleFromPrompt(prompt));\n }, [prompt, appName]);\n\n const selectedSecrets = useMemo(\n () => secrets.filter((secret) => selectedSecretIds.includes(secret.id)),\n [secrets, selectedSecretIds],\n );\n const selectedSecretLabel =\n selectedSecretIds.length === 0\n ? \"No keys selected\"\n : `${selectedSecretIds.length} key${selectedSecretIds.length === 1 ? \"\" : \"s\"} selected`;\n const hasAppNameCandidate =\n appName.trim().length > 0 || prompt.trim().length > 0;\n const safeAppName = slugify(appName) || titleFromPrompt(prompt);\n const appNameError = hasAppNameCandidate\n ? getWorkspaceAppIdValidationError(safeAppName)\n : null;\n\n const canSubmit =\n prompt.trim().length > 0 && safeAppName.length > 0 && !appNameError;\n const submitShortcut =\n typeof navigator !== \"undefined\" &&\n /Mac|iPhone|iPad/.test(navigator.userAgent)\n ? \"⌘\"\n : \"Ctrl\";\n\n function buildMessage(): string {\n return buildNewWorkspaceAppPrompt({\n appId: safeAppName,\n prompt,\n template,\n selectedKeys: selectedSecrets.map((s) => s.credentialKey),\n });\n }\n\n async function submit() {\n if (!canSubmit || isSubmitting) return;\n const validationError = getWorkspaceAppIdValidationError(safeAppName);\n if (validationError) {\n setStatusMessage(validationError);\n return;\n }\n const message = buildMessage();\n setIsSubmitting(true);\n setStatusMessage(null);\n setBranchUrl(null);\n\n try {\n if (isInBuilderFrame()) {\n sendToAgentChat({ message, submit: true, type: \"code\" });\n setStatusMessage(\"Sent to Builder chat.\");\n } else if (isDevMode) {\n sendToAgentChat({ message, submit: true, type: \"code\", newTab: true });\n setStatusMessage(\"Sent to the local agent.\");\n } else {\n const result = await fetchJson(\n actionUrl(effectiveDispatchBasePath, \"start-workspace-app-creation\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n prompt: prompt.trim(),\n appId: safeAppName,\n template,\n secretIds: selectedSecretIds,\n }),\n },\n );\n if (result?.mode === \"builder\") {\n setBranchUrl(result?.url || null);\n setStatusMessage(\"Builder branch created.\");\n } else {\n setStatusMessage(\n result?.message ||\n \"Builder app creation is coming soon here. Open this workspace in Builder to create an app from this prompt.\",\n );\n }\n }\n } catch (err: any) {\n setStatusMessage(err?.message || \"Could not start the new app flow.\");\n } finally {\n setIsSubmitting(false);\n }\n }\n\n function toggleSecret(id: string) {\n setSelectedSecretIds((current) =>\n current.includes(id)\n ? current.filter((existing) => existing !== id)\n : [...current, id],\n );\n }\n\n return (\n <section\n className={`mx-auto flex w-full max-w-5xl flex-col gap-5 px-4 py-6 ${className}`}\n >\n <div className=\"grid gap-5 lg:grid-cols-[minmax(0,1fr)_320px]\">\n <div className=\"rounded-lg border border-border bg-card\">\n <div className=\"border-b border-border px-4 py-3\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <IconPlus className=\"h-4 w-4\" />\n New app\n </div>\n </div>\n <div className=\"space-y-4 p-4\">\n <label className=\"block space-y-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Prompt\n </span>\n <textarea\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n submit();\n }\n }}\n placeholder=\"Describe the app your teammate should be able to use...\"\n rows={6}\n className=\"min-h-36 w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus:border-ring\"\n />\n </label>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <label className=\"block space-y-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n App path\n </span>\n <input\n value={appName}\n onChange={(e) => setAppName(slugify(e.target.value))}\n placeholder=\"customer-health\"\n className={`h-10 w-full rounded-md border bg-background px-3 text-sm outline-none focus:border-ring ${\n appNameError ? \"border-destructive\" : \"border-input\"\n }`}\n />\n {appNameError ? (\n <span className=\"block text-xs text-destructive\">\n {appNameError}\n </span>\n ) : null}\n </label>\n <label className=\"block space-y-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Starter template\n </span>\n <select\n value={template}\n onChange={(e) =>\n setTemplate(e.target.value as typeof template)\n }\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring\"\n >\n {TEMPLATE_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n </div>\n\n <div className=\"flex items-center justify-end gap-3\">\n <span className=\"text-[11px] text-muted-foreground/75\">\n {submitShortcut}+Enter to submit\n </span>\n <button\n type=\"button\"\n onClick={submit}\n disabled={!canSubmit || isSubmitting}\n className=\"inline-flex h-10 items-center gap-2 rounded-md bg-foreground px-4 text-sm font-medium text-background disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {isSubmitting ? (\n <IconLoader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <IconCode className=\"h-4 w-4\" />\n )}\n Create app\n </button>\n </div>\n\n {statusMessage ? (\n <div className=\"rounded-md border border-border bg-muted/40 px-3 py-2 text-sm text-muted-foreground\">\n {statusMessage}\n {branchUrl ? (\n <a\n href={branchUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"ml-2 inline-flex items-center gap-1 font-medium text-foreground underline\"\n >\n Open branch <IconArrowUpRight className=\"h-3 w-3\" />\n </a>\n ) : null}\n </div>\n ) : null}\n </div>\n </div>\n\n <aside className=\"rounded-lg border border-border bg-card\">\n <div className=\"border-b border-border px-4 py-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <IconKey className=\"h-4 w-4\" />\n Dispatch keys\n </div>\n <span className=\"shrink-0 rounded border border-border bg-background/40 px-2 py-0.5 text-[11px] text-muted-foreground\">\n {selectedSecretLabel}\n </span>\n </div>\n </div>\n <div className=\"max-h-[440px] space-y-2 overflow-y-auto p-3\">\n {secretsError ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n {secretsError}\n </p>\n ) : secrets.length === 0 ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n No Dispatch vault keys found yet.\n </p>\n ) : (\n secrets.map((secret) => {\n const selected = selectedSecretIds.includes(secret.id);\n return (\n <div\n key={secret.id}\n className={`group rounded-md border text-sm transition ${\n selected\n ? \"border-primary/45 bg-primary/5 text-foreground shadow-[inset_0_0_0_1px_hsl(var(--primary)/0.08)]\"\n : \"border-border bg-background/25 text-foreground hover:border-muted-foreground/40 hover:bg-accent/35\"\n }`}\n >\n <button\n type=\"button\"\n aria-pressed={selected}\n onClick={() => toggleSecret(secret.id)}\n className=\"flex w-full items-start gap-3 rounded-md px-3 py-2 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30\"\n >\n <span\n className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition ${\n selected\n ? \"border-primary/60 bg-primary/10 text-primary\"\n : \"border-muted-foreground/35 text-transparent group-hover:border-muted-foreground/60\"\n }`}\n >\n {selected ? <IconCheck className=\"h-3 w-3\" /> : null}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium\">\n {secret.credentialKey}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground/70\">\n {selected\n ? \"Will be requested for this app\"\n : \"Click to request\"}\n </span>\n </span>\n </button>\n <details className=\"group/details border-t border-border/60 px-3 py-1.5 text-xs text-muted-foreground/75 open:bg-background/10\">\n <summary className=\"flex cursor-pointer list-none items-center gap-1.5 text-[11px] hover:text-muted-foreground [&::-webkit-details-marker]:hidden\">\n <IconChevronDown className=\"h-3 w-3 transition-transform group-open/details:rotate-180\" />\n Details\n </summary>\n <div className=\"mt-1.5 space-y-1 pb-0.5 pl-4\">\n <div className=\"truncate\">\n Provider: {secret.provider || \"Not specified\"}\n </div>\n <div className=\"truncate\">Name: {secret.name}</div>\n </div>\n </details>\n </div>\n );\n })\n )}\n </div>\n </aside>\n </div>\n </section>\n );\n}\n"]}
1
+ {"version":3,"file":"NewWorkspaceAppFlow.js","sourceRoot":"","sources":["../../src/client/NewWorkspaceAppFlow.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport {\n IconArrowUpRight,\n IconCheck,\n IconChevronDown,\n IconKey,\n} from \"@tabler/icons-react\";\nimport { agentNativePath, appBasePath } from \"./api-path.js\";\nimport { sendToAgentChat } from \"./agent-chat.js\";\nimport { isInBuilderFrame } from \"./builder-frame.js\";\nimport { useDevMode } from \"./use-dev-mode.js\";\nimport { getWorkspaceAppIdValidationError } from \"../shared/workspace-app-id.js\";\nimport { PromptComposer } from \"./composer/PromptComposer.js\";\n\nexport interface VaultSecretOption {\n id: string;\n name: string;\n credentialKey: string;\n provider?: string | null;\n description?: string | null;\n}\n\nexport interface NewWorkspaceAppFlowProps {\n sourceApp?: string;\n className?: string;\n dispatchBasePath?: string | null;\n}\n\nfunction slugify(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/^[^a-z]+/, \"\")\n .slice(0, 48);\n}\n\nfunction titleFromPrompt(prompt: string): string {\n const cleaned = prompt\n .replace(/\\b(build|create|make|an?|the|app|tool|dashboard)\\b/gi, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n return slugify(cleaned || \"new-app\") || \"new-app\";\n}\n\nfunction actionUrl(basePath: string | null, action: string): string {\n const path = `/_agent-native/actions/${action}`;\n if (basePath === null) return agentNativePath(path);\n const normalized = basePath.replace(/\\/+$/, \"\");\n return `${normalized}${path}`;\n}\n\nfunction defaultDispatchBasePath(sourceApp?: string): string | null {\n if (sourceApp === \"dispatch\") return null;\n const base = appBasePath();\n if (base === \"/dispatch\") return null;\n return \"/dispatch\";\n}\n\nasync function fetchJson(url: string, init?: RequestInit): Promise<any> {\n const res = await fetch(url, init);\n const data = await res.json().catch(() => null);\n if (!res.ok) {\n throw new Error(\n data?.error || data?.message || `Request failed ${res.status}`,\n );\n }\n return data;\n}\n\nfunction buildNewWorkspaceAppPrompt(input: {\n appId: string;\n prompt: string;\n selectedKeys: string[];\n}): string {\n const keyList = input.selectedKeys.join(\", \");\n const grantRequest = keyList\n ? `Requested Dispatch vault key grants for this app: ${keyList}`\n : `Requested Dispatch vault key grants for this app: none`;\n\n return [\n `Create a new agent-native app in this workspace.`,\n ``,\n `Suggested app name: ${input.appId} (you may adjust the slug if it conflicts)`,\n `User prompt: ${input.prompt.trim()}`,\n grantRequest,\n ``,\n `Pick a starter template that fits the user's prompt — analytics, calendar, content, design, dispatch, forms, mail, slides, videos, clips, or starter when none of the others fit.`,\n `Use the workspace app layout: create it under apps/${input.appId}, mount it at /${input.appId}, keep it on the shared workspace database/hosting model, and avoid table-name collisions by namespacing any new domain tables to the app.`,\n keyList\n ? `After the app exists, grant the selected Dispatch vault keys to appId \"${input.appId}\" and sync them once the app server is available. Treat these as requested grants, not active grants before creation succeeds.`\n : `Do not grant any Dispatch vault keys unless the user asks later.`,\n ``,\n `App readiness requirements before handing off:`,\n `- Update the workspace app registry metadata for \"${input.appId}\" (workspace-apps.json or .agent-native/workspace-apps.json, whichever this workspace uses) so Dispatch lists the app at /${input.appId} after merge/deploy.`,\n `- Update the app manifest/package/deploy metadata needed by the existing workspace deployment model; do not leave the app relying only on local discovery.`,\n `- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment.`,\n `- Include a final verification note covering the registry entry, manifest/deploy metadata, and agent-card readiness.`,\n `When it is ready, start or update the workspace dev server and navigate the user to /${input.appId}.`,\n ].join(\"\\n\");\n}\n\nexport function NewWorkspaceAppFlow({\n sourceApp = \"starter\",\n className = \"\",\n dispatchBasePath,\n}: NewWorkspaceAppFlowProps) {\n const [selectedSecretIds, setSelectedSecretIds] = useState<string[]>([]);\n const [secrets, setSecrets] = useState<VaultSecretOption[]>([]);\n const [secretsError, setSecretsError] = useState<string | null>(null);\n const [statusMessage, setStatusMessage] = useState<string | null>(null);\n const [branchUrl, setBranchUrl] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const { isDevMode } = useDevMode();\n\n const effectiveDispatchBasePath =\n dispatchBasePath === undefined\n ? defaultDispatchBasePath(sourceApp)\n : dispatchBasePath;\n\n useEffect(() => {\n let cancelled = false;\n const url = actionUrl(\n effectiveDispatchBasePath,\n \"list-vault-secret-options\",\n );\n fetchJson(url)\n .then((data) => {\n if (cancelled) return;\n setSecrets(Array.isArray(data) ? data : []);\n setSecretsError(null);\n })\n .catch((err) => {\n if (cancelled) return;\n setSecrets([]);\n setSecretsError(err?.message || \"Could not load Dispatch keys\");\n });\n return () => {\n cancelled = true;\n };\n }, [effectiveDispatchBasePath]);\n\n const selectedSecrets = useMemo(\n () => secrets.filter((secret) => selectedSecretIds.includes(secret.id)),\n [secrets, selectedSecretIds],\n );\n const selectedSecretLabel =\n selectedSecretIds.length === 0\n ? \"No keys selected\"\n : `${selectedSecretIds.length} key${selectedSecretIds.length === 1 ? \"\" : \"s\"} selected`;\n\n async function submit(rawPrompt: string) {\n const prompt = rawPrompt.trim();\n if (!prompt || isSubmitting) return;\n const appId = titleFromPrompt(prompt);\n const validationError = getWorkspaceAppIdValidationError(appId);\n if (validationError) {\n setStatusMessage(validationError);\n return;\n }\n\n const message = buildNewWorkspaceAppPrompt({\n appId,\n prompt,\n selectedKeys: selectedSecrets.map((s) => s.credentialKey),\n });\n setIsSubmitting(true);\n setStatusMessage(null);\n setBranchUrl(null);\n\n try {\n if (isInBuilderFrame()) {\n sendToAgentChat({ message, submit: true, type: \"code\" });\n setStatusMessage(\"Sent to Builder chat.\");\n } else if (isDevMode) {\n sendToAgentChat({ message, submit: true, type: \"code\", newTab: true });\n setStatusMessage(\"Sent to the local agent.\");\n } else {\n const result = await fetchJson(\n actionUrl(effectiveDispatchBasePath, \"start-workspace-app-creation\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n prompt,\n appId,\n secretIds: selectedSecretIds,\n }),\n },\n );\n if (result?.mode === \"builder\") {\n setBranchUrl(result?.url || null);\n setStatusMessage(\"Builder branch created.\");\n } else {\n setStatusMessage(\n result?.message ||\n \"Builder app creation is coming soon here. Open this workspace in Builder to create an app from this prompt.\",\n );\n }\n }\n } catch (err: any) {\n setStatusMessage(err?.message || \"Could not start the new app flow.\");\n } finally {\n setIsSubmitting(false);\n }\n }\n\n function toggleSecret(id: string) {\n setSelectedSecretIds((current) =>\n current.includes(id)\n ? current.filter((existing) => existing !== id)\n : [...current, id],\n );\n }\n\n return (\n <section\n className={`mx-auto flex w-full max-w-5xl flex-col gap-5 px-4 py-6 ${className}`}\n >\n <div className=\"grid gap-5 lg:grid-cols-[minmax(0,1fr)_320px]\">\n <div className=\"flex flex-col gap-3\">\n <PromptComposer\n autoFocus\n disabled={isSubmitting}\n placeholder=\"Describe the app your teammate should be able to use...\"\n draftScope=\"dispatch:new-app\"\n onSubmit={(text) => submit(text)}\n />\n\n {statusMessage ? (\n <div className=\"rounded-md border border-border bg-muted/40 px-3 py-2 text-sm text-muted-foreground\">\n {statusMessage}\n {branchUrl ? (\n <a\n href={branchUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"ml-2 inline-flex items-center gap-1 font-medium text-foreground underline\"\n >\n Open branch <IconArrowUpRight className=\"h-3 w-3\" />\n </a>\n ) : null}\n </div>\n ) : null}\n </div>\n\n <aside className=\"rounded-lg border border-border bg-card\">\n <div className=\"border-b border-border px-4 py-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <IconKey className=\"h-4 w-4\" />\n Dispatch keys\n </div>\n <span className=\"shrink-0 rounded border border-border bg-background/40 px-2 py-0.5 text-[11px] text-muted-foreground\">\n {selectedSecretLabel}\n </span>\n </div>\n </div>\n <div className=\"max-h-[440px] space-y-2 overflow-y-auto p-3\">\n {secretsError ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n {secretsError}\n </p>\n ) : secrets.length === 0 ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n No Dispatch vault keys found yet.\n </p>\n ) : (\n secrets.map((secret) => {\n const selected = selectedSecretIds.includes(secret.id);\n return (\n <div\n key={secret.id}\n className={`group rounded-md border text-sm transition ${\n selected\n ? \"border-primary/45 bg-primary/5 text-foreground shadow-[inset_0_0_0_1px_hsl(var(--primary)/0.08)]\"\n : \"border-border bg-background/25 text-foreground hover:border-muted-foreground/40 hover:bg-accent/35\"\n }`}\n >\n <button\n type=\"button\"\n aria-pressed={selected}\n onClick={() => toggleSecret(secret.id)}\n className=\"flex w-full cursor-pointer items-start gap-3 rounded-md px-3 py-2 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30\"\n >\n <span\n className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition ${\n selected\n ? \"border-primary/60 bg-primary/10 text-primary\"\n : \"border-muted-foreground/35 text-transparent group-hover:border-muted-foreground/60\"\n }`}\n >\n {selected ? <IconCheck className=\"h-3 w-3\" /> : null}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium\">\n {secret.credentialKey}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground/70\">\n {selected\n ? \"Will be requested for this app\"\n : \"Click to request\"}\n </span>\n </span>\n </button>\n <details className=\"group/details border-t border-border/60 px-3 py-1.5 text-xs text-muted-foreground/75 open:bg-background/10\">\n <summary className=\"flex cursor-pointer list-none items-center gap-1.5 text-[11px] hover:text-muted-foreground [&::-webkit-details-marker]:hidden\">\n <IconChevronDown className=\"h-3 w-3 transition-transform group-open/details:rotate-180\" />\n Details\n </summary>\n <div className=\"mt-1.5 space-y-1 pb-0.5 pl-4\">\n <div className=\"truncate\">\n Provider: {secret.provider || \"Not specified\"}\n </div>\n <div className=\"truncate\">Name: {secret.name}</div>\n </div>\n </details>\n </div>\n );\n })\n )}\n </div>\n </aside>\n </div>\n </section>\n );\n}\n"]}
@@ -1,7 +1,15 @@
1
1
  import type { ComposerMode } from "./types.js";
2
2
  interface ComposerPlusMenuProps {
3
3
  onSelectMode?: (mode: ComposerMode) => void;
4
+ /**
5
+ * "full" (default): full + menu with Upload File, Create Skill, Scheduled Task,
6
+ * Automation, Tool, MCP Server. "upload-only": clicking + opens the file
7
+ * picker directly — no popover, no other modes. Use for prompt popovers
8
+ * (create tool, create deck, create dashboard, etc.) where the only thing
9
+ * to attach is a file.
10
+ */
11
+ mode?: "full" | "upload-only";
4
12
  }
5
- export declare function ComposerPlusMenu({ onSelectMode }: ComposerPlusMenuProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function ComposerPlusMenu({ onSelectMode, mode, }: ComposerPlusMenuProps): import("react/jsx-runtime").JSX.Element;
6
14
  export {};
7
15
  //# sourceMappingURL=ComposerPlusMenu.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ComposerPlusMenu.d.ts","sourceRoot":"","sources":["../../../src/client/composer/ComposerPlusMenu.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,UAAU,qBAAqB;IAC7B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;CAC7C;AAID,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE,EAAE,qBAAqB,2CA0WvE"}
1
+ {"version":3,"file":"ComposerPlusMenu.d.ts","sourceRoot":"","sources":["../../../src/client/composer/ComposerPlusMenu.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,UAAU,qBAAqB;IAC7B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAC5C;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;CAC/B;AAmBD,wBAAgB,gBAAgB,CAAC,EAC/B,YAAY,EACZ,IAAa,GACd,EAAE,qBAAqB,2CAKvB"}
@@ -6,7 +6,16 @@ import { cn } from "../utils.js";
6
6
  import { Popover, PopoverTrigger, PopoverContent, } from "../components/ui/popover.js";
7
7
  import { useOrg } from "../org/hooks.js";
8
8
  import { useCreateMcpServer, testMcpServerUrl, } from "../resources/use-mcp-servers.js";
9
- export function ComposerPlusMenu({ onSelectMode }) {
9
+ function UploadOnlyAttachButton() {
10
+ return (_jsx(ComposerPrimitive.AddAttachment, { asChild: true, children: _jsx("button", { type: "button", className: "shrink-0 flex h-7 w-7 cursor-pointer items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50 disabled:opacity-30 disabled:cursor-not-allowed", title: "Upload file", "aria-label": "Upload file", children: _jsx(IconPlus, { className: "h-4 w-4" }) }) }));
11
+ }
12
+ export function ComposerPlusMenu({ onSelectMode, mode = "full", }) {
13
+ if (mode === "upload-only") {
14
+ return _jsx(UploadOnlyAttachButton, {});
15
+ }
16
+ return _jsx(ComposerPlusMenuFull, { onSelectMode: onSelectMode });
17
+ }
18
+ function ComposerPlusMenuFull({ onSelectMode, }) {
10
19
  const [open, setOpen] = useState(false);
11
20
  const [view, setView] = useState("menu");
12
21
  // MCP state
@@ -1 +1 @@
1
- {"version":3,"file":"ComposerPlusMenu.js","sourceRoot":"","sources":["../../../src/client/composer/ComposerPlusMenu.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useRef, useEffect } from \"react\";\nimport {\n IconPlus,\n IconUpload,\n IconBulb,\n IconClock,\n IconBolt,\n IconTool,\n IconPlugConnected,\n IconLoader2,\n IconCheck,\n IconArrowLeft,\n} from \"@tabler/icons-react\";\nimport { ComposerPrimitive } from \"@assistant-ui/react\";\nimport { cn } from \"../utils.js\";\nimport {\n Popover,\n PopoverTrigger,\n PopoverContent,\n} from \"../components/ui/popover.js\";\nimport { useOrg } from \"../org/hooks.js\";\nimport {\n useCreateMcpServer,\n testMcpServerUrl,\n type McpServerScope,\n} from \"../resources/use-mcp-servers.js\";\nimport type { ComposerMode } from \"./types.js\";\n\ninterface ComposerPlusMenuProps {\n onSelectMode?: (mode: ComposerMode) => void;\n}\n\ntype View = \"menu\" | \"mcp-server\";\n\nexport function ComposerPlusMenu({ onSelectMode }: ComposerPlusMenuProps) {\n const [open, setOpen] = useState(false);\n const [view, setView] = useState<View>(\"menu\");\n\n // MCP state\n const { data: org } = useOrg();\n const canCreateOrgMcp =\n !org?.orgId || org.role === \"owner\" || org.role === \"admin\";\n const hasOrg = !!org?.orgId;\n const defaultMcpScope: McpServerScope =\n hasOrg && canCreateOrgMcp ? \"org\" : \"user\";\n const [mcpScope, setMcpScope] = useState<McpServerScope>(defaultMcpScope);\n const [mcpName, setMcpName] = useState(\"\");\n const [mcpUrl, setMcpUrl] = useState(\"\");\n const [mcpDescription, setMcpDescription] = useState(\"\");\n const [mcpHeadersText, setMcpHeadersText] = useState(\"\");\n const [mcpBusy, setMcpBusy] = useState(false);\n const [mcpError, setMcpError] = useState<string | null>(null);\n const [mcpTestResult, setMcpTestResult] = useState<{\n ok: boolean;\n message: string;\n } | null>(null);\n const createMcp = useCreateMcpServer();\n\n const inputRef = useRef<HTMLInputElement>(null);\n const fileUploadRef = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n if (open) {\n setView(\"menu\");\n setMcpScope(defaultMcpScope);\n setMcpName(\"\");\n setMcpUrl(\"\");\n setMcpDescription(\"\");\n setMcpHeadersText(\"\");\n setMcpError(null);\n setMcpTestResult(null);\n setMcpBusy(false);\n }\n }, [open, defaultMcpScope]);\n\n useEffect(() => {\n if (view === \"mcp-server\") {\n const t = setTimeout(() => inputRef.current?.focus(), 50);\n return () => clearTimeout(t);\n }\n }, [view]);\n\n const parseHeaderLines = (\n text: string,\n ): Record<string, string> | undefined => {\n const out: Record<string, string> = {};\n for (const line of text.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n const idx = trimmed.indexOf(\":\");\n if (idx <= 0) continue;\n const key = trimmed.slice(0, idx).trim();\n const val = trimmed.slice(idx + 1).trim();\n if (!key || !val) continue;\n out[key] = val;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n };\n\n const submitMcpServer = async () => {\n const name = mcpName.trim();\n const url = mcpUrl.trim();\n if (!name || !url || mcpBusy) return;\n setMcpError(null);\n setMcpBusy(true);\n try {\n await createMcp.mutateAsync({\n scope: mcpScope,\n name,\n url,\n headers: parseHeaderLines(mcpHeadersText),\n description: mcpDescription.trim() || undefined,\n });\n setOpen(false);\n } catch (err: any) {\n setMcpError(err?.message ?? String(err));\n } finally {\n setMcpBusy(false);\n }\n };\n\n const runMcpTest = async () => {\n const url = mcpUrl.trim();\n if (!url || mcpBusy) return;\n setMcpTestResult(null);\n setMcpError(null);\n setMcpBusy(true);\n try {\n const res = await testMcpServerUrl(url, parseHeaderLines(mcpHeadersText));\n if (res.ok) {\n setMcpTestResult({\n ok: true,\n message: `${res.toolCount ?? 0} tool${res.toolCount === 1 ? \"\" : \"s\"} available`,\n });\n } else {\n setMcpTestResult({ ok: false, message: res.error ?? \"Failed\" });\n }\n } catch (err: any) {\n setMcpTestResult({ ok: false, message: err?.message ?? String(err) });\n } finally {\n setMcpBusy(false);\n }\n };\n\n const menuItems: {\n icon: React.ReactNode;\n label: string;\n desc: string;\n action: () => void;\n }[] = [\n {\n icon: <IconUpload className=\"h-3.5 w-3.5\" />,\n label: \"Upload File\",\n desc: \"Attach a file to this message\",\n action: () => {\n setOpen(false);\n setTimeout(() => fileUploadRef.current?.click(), 0);\n },\n },\n {\n icon: <IconBulb className=\"h-3.5 w-3.5\" />,\n label: \"Create Skill\",\n desc: \"Teach the agent a new ability\",\n action: () => {\n onSelectMode?.(\"skill\");\n setOpen(false);\n },\n },\n {\n icon: <IconClock className=\"h-3.5 w-3.5\" />,\n label: \"Scheduled Task\",\n desc: \"Run something on a schedule\",\n action: () => {\n onSelectMode?.(\"job\");\n setOpen(false);\n },\n },\n {\n icon: <IconBolt className=\"h-3.5 w-3.5\" />,\n label: \"Create Automation\",\n desc: \"Set up a when-X-do-Y rule\",\n action: () => {\n onSelectMode?.(\"automation\");\n setOpen(false);\n },\n },\n {\n icon: <IconTool className=\"h-3.5 w-3.5\" />,\n label: \"Create Tool\",\n desc: \"Build an interactive mini app\",\n action: () => {\n onSelectMode?.(\"tool\");\n setOpen(false);\n },\n },\n {\n icon: <IconPlugConnected className=\"h-3.5 w-3.5\" />,\n label: \"Connect MCP Server\",\n desc: \"Expose external tools to the agent\",\n action: () => setView(\"mcp-server\"),\n },\n ];\n\n const backButton = (\n <button\n type=\"button\"\n onClick={() => setView(\"menu\")}\n className=\"flex items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground mb-1.5\"\n >\n <IconArrowLeft className=\"h-3 w-3\" />\n Back\n </button>\n );\n\n return (\n <>\n {/* Hidden button to trigger the native file upload */}\n <ComposerPrimitive.AddAttachment asChild>\n <button\n ref={fileUploadRef}\n type=\"button\"\n className=\"hidden\"\n tabIndex={-1}\n aria-hidden\n />\n </ComposerPrimitive.AddAttachment>\n\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"shrink-0 flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50 disabled:opacity-30 disabled:cursor-not-allowed\"\n title=\"Add...\"\n >\n <IconPlus className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n side=\"top\"\n align=\"start\"\n sideOffset={8}\n className=\"w-[260px] p-0 rounded-lg\"\n style={{ fontSize: 13, lineHeight: \"normal\" }}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n {view === \"menu\" && (\n <div className=\"py-1\">\n {menuItems.map((item) => (\n <button\n key={item.label}\n onClick={item.action}\n className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left hover:bg-accent/50\"\n >\n <span className=\"text-muted-foreground\">{item.icon}</span>\n <div className=\"min-w-0\">\n <div className=\"text-[12px] font-medium text-foreground\">\n {item.label}\n </div>\n <div className=\"mt-0.5 text-[10px] text-muted-foreground/60\">\n {item.desc}\n </div>\n </div>\n </button>\n ))}\n </div>\n )}\n\n {view === \"mcp-server\" && (\n <div className=\"p-3\">\n {backButton}\n <label className=\"mb-1 block text-[11px] font-semibold text-foreground\">\n Connect MCP Server\n </label>\n <p className=\"mb-2 text-[10px] text-muted-foreground/60 leading-relaxed\">\n Point at any Streamable HTTP MCP server. Its tools become\n available to the agent.\n </p>\n <div className=\"space-y-2\">\n <div className=\"flex gap-1 rounded-md border border-border p-0.5\">\n <button\n type=\"button\"\n onClick={() => setMcpScope(\"user\")}\n className={cn(\n \"flex-1 rounded px-2 py-1 text-[11px] font-medium\",\n mcpScope === \"user\"\n ? \"bg-accent text-foreground\"\n : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n Personal\n </button>\n <button\n type=\"button\"\n onClick={() =>\n hasOrg && canCreateOrgMcp && setMcpScope(\"org\")\n }\n disabled={!hasOrg || !canCreateOrgMcp}\n title={\n !hasOrg\n ? \"Join an organization to share MCP servers\"\n : !canCreateOrgMcp\n ? \"Only owners and admins can add org-scope servers\"\n : undefined\n }\n className={cn(\n \"flex-1 rounded px-2 py-1 text-[11px] font-medium\",\n mcpScope === \"org\"\n ? \"bg-accent text-foreground\"\n : \"text-muted-foreground hover:text-foreground\",\n (!hasOrg || !canCreateOrgMcp) &&\n \"cursor-not-allowed opacity-40 hover:text-muted-foreground\",\n )}\n >\n Organization\n </button>\n </div>\n <input\n ref={inputRef}\n value={mcpName}\n onChange={(e) => setMcpName(e.target.value)}\n className=\"w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent\"\n placeholder=\"Server name (e.g. zapier)\"\n />\n <input\n value={mcpUrl}\n onChange={(e) => setMcpUrl(e.target.value)}\n className=\"w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent\"\n placeholder=\"https://mcp.example.com/\"\n />\n <input\n value={mcpDescription}\n onChange={(e) => setMcpDescription(e.target.value)}\n className=\"w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent\"\n placeholder=\"Description (optional)\"\n />\n <label className=\"block text-[10px] font-medium text-muted-foreground/70\">\n Headers (one per line, e.g. Authorization: Bearer ...)\n </label>\n <textarea\n value={mcpHeadersText}\n onChange={(e) => setMcpHeadersText(e.target.value)}\n rows={2}\n className=\"w-full resize-y rounded-md border border-border bg-background px-2.5 py-1.5 text-[12px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent\"\n style={{\n fontFamily:\n 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n }}\n placeholder=\"Authorization: Bearer sk-...\"\n />\n {mcpTestResult && (\n <div\n className={cn(\n \"flex items-center gap-1 text-[11px]\",\n mcpTestResult.ok\n ? \"text-green-600 dark:text-green-400\"\n : \"text-red-600 dark:text-red-400\",\n )}\n >\n {mcpTestResult.ok && <IconCheck className=\"h-3 w-3\" />}\n {mcpTestResult.message}\n </div>\n )}\n {mcpError && (\n <div className=\"text-[11px] text-red-600 dark:text-red-400\">\n {mcpError}\n </div>\n )}\n </div>\n <div className=\"mt-2.5 flex items-center justify-between gap-2\">\n <button\n type=\"button\"\n onClick={runMcpTest}\n disabled={!mcpUrl.trim() || mcpBusy}\n className=\"rounded-md border border-border bg-background px-2.5 py-1.5 text-[11px] font-medium text-foreground hover:bg-accent disabled:opacity-40 disabled:pointer-events-none\"\n >\n Test\n </button>\n <button\n type=\"button\"\n onClick={submitMcpServer}\n disabled={!mcpName.trim() || !mcpUrl.trim() || mcpBusy}\n className=\"rounded-md bg-accent px-3 py-1.5 text-[12px] font-medium text-foreground hover:bg-accent/80 disabled:opacity-40 disabled:pointer-events-none\"\n >\n {mcpBusy ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : (\n \"Connect\"\n )}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n </>\n );\n}\n"]}
1
+ {"version":3,"file":"ComposerPlusMenu.js","sourceRoot":"","sources":["../../../src/client/composer/ComposerPlusMenu.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,aAAa,GACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EACL,kBAAkB,EAClB,gBAAgB,GAEjB,MAAM,iCAAiC,CAAC;AAiBzC,SAAS,sBAAsB;IAC7B,OAAO,CACL,KAAC,iBAAiB,CAAC,aAAa,IAAC,OAAO,kBACtC,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,4LAA4L,EACtM,KAAK,EAAC,aAAa,gBACR,aAAa,YAExB,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,GACuB,CACnC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAC/B,YAAY,EACZ,IAAI,GAAG,MAAM,GACS;IACtB,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;QAC3B,OAAO,KAAC,sBAAsB,KAAG,CAAC;IACpC,CAAC;IACD,OAAO,KAAC,oBAAoB,IAAC,YAAY,EAAE,YAAY,GAAI,CAAC;AAC9D,CAAC;AAED,SAAS,oBAAoB,CAAC,EAC5B,YAAY,GACgC;IAC5C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAO,MAAM,CAAC,CAAC;IAE/C,YAAY;IACZ,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IAC/B,MAAM,eAAe,GACnB,CAAC,GAAG,EAAE,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC;IAC9D,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC;IAC5B,MAAM,eAAe,GACnB,MAAM,IAAI,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAC7C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAiB,eAAe,CAAC,CAAC;IAC1E,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC9D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAGxC,IAAI,CAAC,CAAC;IAChB,MAAM,SAAS,GAAG,kBAAkB,EAAE,CAAC;IAEvC,MAAM,QAAQ,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAChD,MAAM,aAAa,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAEtD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,CAAC,MAAM,CAAC,CAAC;YAChB,WAAW,CAAC,eAAe,CAAC,CAAC;YAC7B,UAAU,CAAC,EAAE,CAAC,CAAC;YACf,SAAS,CAAC,EAAE,CAAC,CAAC;YACd,iBAAiB,CAAC,EAAE,CAAC,CAAC;YACtB,iBAAiB,CAAC,EAAE,CAAC,CAAC;YACtB,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACvB,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC;IAE5B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1B,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;YAC1D,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,gBAAgB,GAAG,CACvB,IAAY,EACwB,EAAE;QACtC,MAAM,GAAG,GAA2B,EAAE,CAAC;QACvC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACjC,IAAI,GAAG,IAAI,CAAC;gBAAE,SAAS;YACvB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACzC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1C,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG;gBAAE,SAAS;YAC3B,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QACjB,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IACvD,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;QACjC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,IAAI,OAAO;YAAE,OAAO;QACrC,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,WAAW,CAAC;gBAC1B,KAAK,EAAE,QAAQ;gBACf,IAAI;gBACJ,GAAG;gBACH,OAAO,EAAE,gBAAgB,CAAC,cAAc,CAAC;gBACzC,WAAW,EAAE,cAAc,CAAC,IAAI,EAAE,IAAI,SAAS;aAChD,CAAC,CAAC;YACH,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,WAAW,CAAC,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;QAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,GAAG,IAAI,OAAO;YAAE,OAAO;QAC5B,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC,CAAC;YAC1E,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,gBAAgB,CAAC;oBACf,EAAE,EAAE,IAAI;oBACR,OAAO,EAAE,GAAG,GAAG,CAAC,SAAS,IAAI,CAAC,QAAQ,GAAG,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,YAAY;iBACjF,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,gBAAgB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,IAAI,QAAQ,EAAE,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,gBAAgB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,SAAS,GAKT;QACJ;YACE,IAAI,EAAE,KAAC,UAAU,IAAC,SAAS,EAAC,aAAa,GAAG;YAC5C,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,+BAA+B;YACrC,MAAM,EAAE,GAAG,EAAE;gBACX,OAAO,CAAC,KAAK,CAAC,CAAC;gBACf,UAAU,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;YACtD,CAAC;SACF;QACD;YACE,IAAI,EAAE,KAAC,QAAQ,IAAC,SAAS,EAAC,aAAa,GAAG;YAC1C,KAAK,EAAE,cAAc;YACrB,IAAI,EAAE,+BAA+B;YACrC,MAAM,EAAE,GAAG,EAAE;gBACX,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC;gBACxB,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;SACF;QACD;YACE,IAAI,EAAE,KAAC,SAAS,IAAC,SAAS,EAAC,aAAa,GAAG;YAC3C,KAAK,EAAE,gBAAgB;YACvB,IAAI,EAAE,6BAA6B;YACnC,MAAM,EAAE,GAAG,EAAE;gBACX,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;gBACtB,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;SACF;QACD;YACE,IAAI,EAAE,KAAC,QAAQ,IAAC,SAAS,EAAC,aAAa,GAAG;YAC1C,KAAK,EAAE,mBAAmB;YAC1B,IAAI,EAAE,2BAA2B;YACjC,MAAM,EAAE,GAAG,EAAE;gBACX,YAAY,EAAE,CAAC,YAAY,CAAC,CAAC;gBAC7B,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;SACF;QACD;YACE,IAAI,EAAE,KAAC,QAAQ,IAAC,SAAS,EAAC,aAAa,GAAG;YAC1C,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,+BAA+B;YACrC,MAAM,EAAE,GAAG,EAAE;gBACX,YAAY,EAAE,CAAC,MAAM,CAAC,CAAC;gBACvB,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;SACF;QACD;YACE,IAAI,EAAE,KAAC,iBAAiB,IAAC,SAAS,EAAC,aAAa,GAAG;YACnD,KAAK,EAAE,oBAAoB;YAC3B,IAAI,EAAE,oCAAoC;YAC1C,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC;SACpC;KACF,CAAC;IAEF,MAAM,UAAU,GAAG,CACjB,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAC9B,SAAS,EAAC,wFAAwF,aAElG,KAAC,aAAa,IAAC,SAAS,EAAC,SAAS,GAAG,YAE9B,CACV,CAAC;IAEF,OAAO,CACL,8BAEE,KAAC,iBAAiB,CAAC,aAAa,IAAC,OAAO,kBACtC,iBACE,GAAG,EAAE,aAAa,EAClB,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,QAAQ,EAClB,QAAQ,EAAE,CAAC,CAAC,wBAEZ,GAC8B,EAElC,MAAC,OAAO,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,aACxC,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,6KAA6K,EACvL,KAAK,EAAC,QAAQ,YAEd,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,GACM,EACjB,MAAC,cAAc,IACb,IAAI,EAAC,KAAK,EACV,KAAK,EAAC,OAAO,EACb,UAAU,EAAE,CAAC,EACb,SAAS,EAAC,0BAA0B,EACpC,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,EAC7C,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,aAEzC,IAAI,KAAK,MAAM,IAAI,CAClB,cAAK,SAAS,EAAC,MAAM,YAClB,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACvB,kBAEE,OAAO,EAAE,IAAI,CAAC,MAAM,EACpB,SAAS,EAAC,yEAAyE,aAEnF,eAAM,SAAS,EAAC,uBAAuB,YAAE,IAAI,CAAC,IAAI,GAAQ,EAC1D,eAAK,SAAS,EAAC,SAAS,aACtB,cAAK,SAAS,EAAC,yCAAyC,YACrD,IAAI,CAAC,KAAK,GACP,EACN,cAAK,SAAS,EAAC,6CAA6C,YACzD,IAAI,CAAC,IAAI,GACN,IACF,KAZD,IAAI,CAAC,KAAK,CAaR,CACV,CAAC,GACE,CACP,EAEA,IAAI,KAAK,YAAY,IAAI,CACxB,eAAK,SAAS,EAAC,KAAK,aACjB,UAAU,EACX,gBAAO,SAAS,EAAC,sDAAsD,mCAE/D,EACR,YAAG,SAAS,EAAC,2DAA2D,kGAGpE,EACJ,eAAK,SAAS,EAAC,WAAW,aACxB,eAAK,SAAS,EAAC,kDAAkD,aAC/D,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,EAClC,SAAS,EAAE,EAAE,CACX,kDAAkD,EAClD,QAAQ,KAAK,MAAM;4DACjB,CAAC,CAAC,2BAA2B;4DAC7B,CAAC,CAAC,6CAA6C,CAClD,yBAGM,EACT,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CACZ,MAAM,IAAI,eAAe,IAAI,WAAW,CAAC,KAAK,CAAC,EAEjD,QAAQ,EAAE,CAAC,MAAM,IAAI,CAAC,eAAe,EACrC,KAAK,EACH,CAAC,MAAM;4DACL,CAAC,CAAC,2CAA2C;4DAC7C,CAAC,CAAC,CAAC,eAAe;gEAChB,CAAC,CAAC,kDAAkD;gEACpD,CAAC,CAAC,SAAS,EAEjB,SAAS,EAAE,EAAE,CACX,kDAAkD,EAClD,QAAQ,KAAK,KAAK;4DAChB,CAAC,CAAC,2BAA2B;4DAC7B,CAAC,CAAC,6CAA6C,EACjD,CAAC,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC;4DAC3B,2DAA2D,CAC9D,6BAGM,IACL,EACN,gBACE,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC3C,SAAS,EAAC,iLAAiL,EAC3L,WAAW,EAAC,2BAA2B,GACvC,EACF,gBACE,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC1C,SAAS,EAAC,iLAAiL,EAC3L,WAAW,EAAC,0BAA0B,GACtC,EACF,gBACE,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAClD,SAAS,EAAC,iLAAiL,EAC3L,WAAW,EAAC,wBAAwB,GACpC,EACF,gBAAO,SAAS,EAAC,wDAAwD,uEAEjE,EACR,mBACE,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAClD,IAAI,EAAE,CAAC,EACP,SAAS,EAAC,0LAA0L,EACpM,KAAK,EAAE;oDACL,UAAU,EACR,qEAAqE;iDACxE,EACD,WAAW,EAAC,8BAA8B,GAC1C,EACD,aAAa,IAAI,CAChB,eACE,SAAS,EAAE,EAAE,CACX,qCAAqC,EACrC,aAAa,CAAC,EAAE;oDACd,CAAC,CAAC,oCAAoC;oDACtC,CAAC,CAAC,gCAAgC,CACrC,aAEA,aAAa,CAAC,EAAE,IAAI,KAAC,SAAS,IAAC,SAAS,EAAC,SAAS,GAAG,EACrD,aAAa,CAAC,OAAO,IAClB,CACP,EACA,QAAQ,IAAI,CACX,cAAK,SAAS,EAAC,4CAA4C,YACxD,QAAQ,GACL,CACP,IACG,EACN,eAAK,SAAS,EAAC,gDAAgD,aAC7D,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,OAAO,EACnC,SAAS,EAAC,sKAAsK,qBAGzK,EACT,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,OAAO,EACtD,SAAS,EAAC,8IAA8I,YAEvJ,OAAO,CAAC,CAAC,CAAC,CACT,KAAC,WAAW,IAAC,SAAS,EAAC,sBAAsB,GAAG,CACjD,CAAC,CAAC,CAAC,CACF,SAAS,CACV,GACM,IACL,IACF,CACP,IACc,IACT,IACT,CACJ,CAAC;AACJ,CAAC","sourcesContent":["import React, { useState, useRef, useEffect } from \"react\";\nimport {\n IconPlus,\n IconUpload,\n IconBulb,\n IconClock,\n IconBolt,\n IconTool,\n IconPlugConnected,\n IconLoader2,\n IconCheck,\n IconArrowLeft,\n} from \"@tabler/icons-react\";\nimport { ComposerPrimitive } from \"@assistant-ui/react\";\nimport { cn } from \"../utils.js\";\nimport {\n Popover,\n PopoverTrigger,\n PopoverContent,\n} from \"../components/ui/popover.js\";\nimport { useOrg } from \"../org/hooks.js\";\nimport {\n useCreateMcpServer,\n testMcpServerUrl,\n type McpServerScope,\n} from \"../resources/use-mcp-servers.js\";\nimport type { ComposerMode } from \"./types.js\";\n\ninterface ComposerPlusMenuProps {\n onSelectMode?: (mode: ComposerMode) => void;\n /**\n * \"full\" (default): full + menu with Upload File, Create Skill, Scheduled Task,\n * Automation, Tool, MCP Server. \"upload-only\": clicking + opens the file\n * picker directly — no popover, no other modes. Use for prompt popovers\n * (create tool, create deck, create dashboard, etc.) where the only thing\n * to attach is a file.\n */\n mode?: \"full\" | \"upload-only\";\n}\n\ntype View = \"menu\" | \"mcp-server\";\n\nfunction UploadOnlyAttachButton() {\n return (\n <ComposerPrimitive.AddAttachment asChild>\n <button\n type=\"button\"\n className=\"shrink-0 flex h-7 w-7 cursor-pointer items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50 disabled:opacity-30 disabled:cursor-not-allowed\"\n title=\"Upload file\"\n aria-label=\"Upload file\"\n >\n <IconPlus className=\"h-4 w-4\" />\n </button>\n </ComposerPrimitive.AddAttachment>\n );\n}\n\nexport function ComposerPlusMenu({\n onSelectMode,\n mode = \"full\",\n}: ComposerPlusMenuProps) {\n if (mode === \"upload-only\") {\n return <UploadOnlyAttachButton />;\n }\n return <ComposerPlusMenuFull onSelectMode={onSelectMode} />;\n}\n\nfunction ComposerPlusMenuFull({\n onSelectMode,\n}: Pick<ComposerPlusMenuProps, \"onSelectMode\">) {\n const [open, setOpen] = useState(false);\n const [view, setView] = useState<View>(\"menu\");\n\n // MCP state\n const { data: org } = useOrg();\n const canCreateOrgMcp =\n !org?.orgId || org.role === \"owner\" || org.role === \"admin\";\n const hasOrg = !!org?.orgId;\n const defaultMcpScope: McpServerScope =\n hasOrg && canCreateOrgMcp ? \"org\" : \"user\";\n const [mcpScope, setMcpScope] = useState<McpServerScope>(defaultMcpScope);\n const [mcpName, setMcpName] = useState(\"\");\n const [mcpUrl, setMcpUrl] = useState(\"\");\n const [mcpDescription, setMcpDescription] = useState(\"\");\n const [mcpHeadersText, setMcpHeadersText] = useState(\"\");\n const [mcpBusy, setMcpBusy] = useState(false);\n const [mcpError, setMcpError] = useState<string | null>(null);\n const [mcpTestResult, setMcpTestResult] = useState<{\n ok: boolean;\n message: string;\n } | null>(null);\n const createMcp = useCreateMcpServer();\n\n const inputRef = useRef<HTMLInputElement>(null);\n const fileUploadRef = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n if (open) {\n setView(\"menu\");\n setMcpScope(defaultMcpScope);\n setMcpName(\"\");\n setMcpUrl(\"\");\n setMcpDescription(\"\");\n setMcpHeadersText(\"\");\n setMcpError(null);\n setMcpTestResult(null);\n setMcpBusy(false);\n }\n }, [open, defaultMcpScope]);\n\n useEffect(() => {\n if (view === \"mcp-server\") {\n const t = setTimeout(() => inputRef.current?.focus(), 50);\n return () => clearTimeout(t);\n }\n }, [view]);\n\n const parseHeaderLines = (\n text: string,\n ): Record<string, string> | undefined => {\n const out: Record<string, string> = {};\n for (const line of text.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n const idx = trimmed.indexOf(\":\");\n if (idx <= 0) continue;\n const key = trimmed.slice(0, idx).trim();\n const val = trimmed.slice(idx + 1).trim();\n if (!key || !val) continue;\n out[key] = val;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n };\n\n const submitMcpServer = async () => {\n const name = mcpName.trim();\n const url = mcpUrl.trim();\n if (!name || !url || mcpBusy) return;\n setMcpError(null);\n setMcpBusy(true);\n try {\n await createMcp.mutateAsync({\n scope: mcpScope,\n name,\n url,\n headers: parseHeaderLines(mcpHeadersText),\n description: mcpDescription.trim() || undefined,\n });\n setOpen(false);\n } catch (err: any) {\n setMcpError(err?.message ?? String(err));\n } finally {\n setMcpBusy(false);\n }\n };\n\n const runMcpTest = async () => {\n const url = mcpUrl.trim();\n if (!url || mcpBusy) return;\n setMcpTestResult(null);\n setMcpError(null);\n setMcpBusy(true);\n try {\n const res = await testMcpServerUrl(url, parseHeaderLines(mcpHeadersText));\n if (res.ok) {\n setMcpTestResult({\n ok: true,\n message: `${res.toolCount ?? 0} tool${res.toolCount === 1 ? \"\" : \"s\"} available`,\n });\n } else {\n setMcpTestResult({ ok: false, message: res.error ?? \"Failed\" });\n }\n } catch (err: any) {\n setMcpTestResult({ ok: false, message: err?.message ?? String(err) });\n } finally {\n setMcpBusy(false);\n }\n };\n\n const menuItems: {\n icon: React.ReactNode;\n label: string;\n desc: string;\n action: () => void;\n }[] = [\n {\n icon: <IconUpload className=\"h-3.5 w-3.5\" />,\n label: \"Upload File\",\n desc: \"Attach a file to this message\",\n action: () => {\n setOpen(false);\n setTimeout(() => fileUploadRef.current?.click(), 0);\n },\n },\n {\n icon: <IconBulb className=\"h-3.5 w-3.5\" />,\n label: \"Create Skill\",\n desc: \"Teach the agent a new ability\",\n action: () => {\n onSelectMode?.(\"skill\");\n setOpen(false);\n },\n },\n {\n icon: <IconClock className=\"h-3.5 w-3.5\" />,\n label: \"Scheduled Task\",\n desc: \"Run something on a schedule\",\n action: () => {\n onSelectMode?.(\"job\");\n setOpen(false);\n },\n },\n {\n icon: <IconBolt className=\"h-3.5 w-3.5\" />,\n label: \"Create Automation\",\n desc: \"Set up a when-X-do-Y rule\",\n action: () => {\n onSelectMode?.(\"automation\");\n setOpen(false);\n },\n },\n {\n icon: <IconTool className=\"h-3.5 w-3.5\" />,\n label: \"Create Tool\",\n desc: \"Build an interactive mini app\",\n action: () => {\n onSelectMode?.(\"tool\");\n setOpen(false);\n },\n },\n {\n icon: <IconPlugConnected className=\"h-3.5 w-3.5\" />,\n label: \"Connect MCP Server\",\n desc: \"Expose external tools to the agent\",\n action: () => setView(\"mcp-server\"),\n },\n ];\n\n const backButton = (\n <button\n type=\"button\"\n onClick={() => setView(\"menu\")}\n className=\"flex items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground mb-1.5\"\n >\n <IconArrowLeft className=\"h-3 w-3\" />\n Back\n </button>\n );\n\n return (\n <>\n {/* Hidden button to trigger the native file upload */}\n <ComposerPrimitive.AddAttachment asChild>\n <button\n ref={fileUploadRef}\n type=\"button\"\n className=\"hidden\"\n tabIndex={-1}\n aria-hidden\n />\n </ComposerPrimitive.AddAttachment>\n\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"shrink-0 flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50 disabled:opacity-30 disabled:cursor-not-allowed\"\n title=\"Add...\"\n >\n <IconPlus className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n side=\"top\"\n align=\"start\"\n sideOffset={8}\n className=\"w-[260px] p-0 rounded-lg\"\n style={{ fontSize: 13, lineHeight: \"normal\" }}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n {view === \"menu\" && (\n <div className=\"py-1\">\n {menuItems.map((item) => (\n <button\n key={item.label}\n onClick={item.action}\n className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left hover:bg-accent/50\"\n >\n <span className=\"text-muted-foreground\">{item.icon}</span>\n <div className=\"min-w-0\">\n <div className=\"text-[12px] font-medium text-foreground\">\n {item.label}\n </div>\n <div className=\"mt-0.5 text-[10px] text-muted-foreground/60\">\n {item.desc}\n </div>\n </div>\n </button>\n ))}\n </div>\n )}\n\n {view === \"mcp-server\" && (\n <div className=\"p-3\">\n {backButton}\n <label className=\"mb-1 block text-[11px] font-semibold text-foreground\">\n Connect MCP Server\n </label>\n <p className=\"mb-2 text-[10px] text-muted-foreground/60 leading-relaxed\">\n Point at any Streamable HTTP MCP server. Its tools become\n available to the agent.\n </p>\n <div className=\"space-y-2\">\n <div className=\"flex gap-1 rounded-md border border-border p-0.5\">\n <button\n type=\"button\"\n onClick={() => setMcpScope(\"user\")}\n className={cn(\n \"flex-1 rounded px-2 py-1 text-[11px] font-medium\",\n mcpScope === \"user\"\n ? \"bg-accent text-foreground\"\n : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n Personal\n </button>\n <button\n type=\"button\"\n onClick={() =>\n hasOrg && canCreateOrgMcp && setMcpScope(\"org\")\n }\n disabled={!hasOrg || !canCreateOrgMcp}\n title={\n !hasOrg\n ? \"Join an organization to share MCP servers\"\n : !canCreateOrgMcp\n ? \"Only owners and admins can add org-scope servers\"\n : undefined\n }\n className={cn(\n \"flex-1 rounded px-2 py-1 text-[11px] font-medium\",\n mcpScope === \"org\"\n ? \"bg-accent text-foreground\"\n : \"text-muted-foreground hover:text-foreground\",\n (!hasOrg || !canCreateOrgMcp) &&\n \"cursor-not-allowed opacity-40 hover:text-muted-foreground\",\n )}\n >\n Organization\n </button>\n </div>\n <input\n ref={inputRef}\n value={mcpName}\n onChange={(e) => setMcpName(e.target.value)}\n className=\"w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent\"\n placeholder=\"Server name (e.g. zapier)\"\n />\n <input\n value={mcpUrl}\n onChange={(e) => setMcpUrl(e.target.value)}\n className=\"w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent\"\n placeholder=\"https://mcp.example.com/\"\n />\n <input\n value={mcpDescription}\n onChange={(e) => setMcpDescription(e.target.value)}\n className=\"w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent\"\n placeholder=\"Description (optional)\"\n />\n <label className=\"block text-[10px] font-medium text-muted-foreground/70\">\n Headers (one per line, e.g. Authorization: Bearer ...)\n </label>\n <textarea\n value={mcpHeadersText}\n onChange={(e) => setMcpHeadersText(e.target.value)}\n rows={2}\n className=\"w-full resize-y rounded-md border border-border bg-background px-2.5 py-1.5 text-[12px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent\"\n style={{\n fontFamily:\n 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n }}\n placeholder=\"Authorization: Bearer sk-...\"\n />\n {mcpTestResult && (\n <div\n className={cn(\n \"flex items-center gap-1 text-[11px]\",\n mcpTestResult.ok\n ? \"text-green-600 dark:text-green-400\"\n : \"text-red-600 dark:text-red-400\",\n )}\n >\n {mcpTestResult.ok && <IconCheck className=\"h-3 w-3\" />}\n {mcpTestResult.message}\n </div>\n )}\n {mcpError && (\n <div className=\"text-[11px] text-red-600 dark:text-red-400\">\n {mcpError}\n </div>\n )}\n </div>\n <div className=\"mt-2.5 flex items-center justify-between gap-2\">\n <button\n type=\"button\"\n onClick={runMcpTest}\n disabled={!mcpUrl.trim() || mcpBusy}\n className=\"rounded-md border border-border bg-background px-2.5 py-1.5 text-[11px] font-medium text-foreground hover:bg-accent disabled:opacity-40 disabled:pointer-events-none\"\n >\n Test\n </button>\n <button\n type=\"button\"\n onClick={submitMcpServer}\n disabled={!mcpName.trim() || !mcpUrl.trim() || mcpBusy}\n className=\"rounded-md bg-accent px-3 py-1.5 text-[12px] font-medium text-foreground hover:bg-accent/80 disabled:opacity-40 disabled:pointer-events-none\"\n >\n {mcpBusy ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : (\n \"Connect\"\n )}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n </>\n );\n}\n"]}
@@ -0,0 +1,40 @@
1
+ import { type Ref } from "react";
2
+ import { type TiptapComposerHandle } from "./TiptapComposer.js";
3
+ import type { Reference } from "./types.js";
4
+ /**
5
+ * Files the user attached via the "+" button in PromptComposer. The host owns
6
+ * what to do with them — typically POST to a per-app upload endpoint and pass
7
+ * the resulting URLs/paths into the prompt that gets sent to the agent.
8
+ */
9
+ export type PromptComposerFile = File;
10
+ export interface PromptComposerProps {
11
+ /** Called when the user submits the composer. */
12
+ onSubmit: (text: string, files: PromptComposerFile[], references: Reference[]) => void;
13
+ placeholder?: string;
14
+ disabled?: boolean;
15
+ autoFocus?: boolean;
16
+ className?: string;
17
+ /** Forwarded to TiptapComposer for draft persistence. */
18
+ draftScope?: string;
19
+ /** Show the model selector (default: false). */
20
+ showModelSelector?: boolean;
21
+ /** Show the voice dictation button (default: true). */
22
+ voiceEnabled?: boolean;
23
+ /** Show file upload controls and pass submitted files to onSubmit. */
24
+ attachmentsEnabled?: boolean;
25
+ /** Imperative handle for focusing the composer. */
26
+ composerRef?: Ref<TiptapComposerHandle>;
27
+ }
28
+ /**
29
+ * Standalone composer that mirrors the agent sidebar's input experience —
30
+ * voice dictation, file upload, model selector, submit-on-Enter — for use in
31
+ * popovers and inline prompt forms (create tool, create deck, create dashboard,
32
+ * the Dispatch new-app flow, etc.).
33
+ *
34
+ * The host owns submission: when the user presses Enter or clicks submit,
35
+ * `onSubmit(text, files, references)` is called. PromptComposer runs its own
36
+ * minimal assistant-ui runtime so it can be dropped into any subtree without
37
+ * needing the outer chat to be mounted.
38
+ */
39
+ export declare function PromptComposer(props: PromptComposerProps): import("react/jsx-runtime").JSX.Element;
40
+ //# sourceMappingURL=PromptComposer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PromptComposer.d.ts","sourceRoot":"","sources":["../../../src/client/composer/PromptComposer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAuB1E,OAAO,EAAkB,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEtC,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,kBAAkB,EAAE,EAC3B,UAAU,EAAE,SAAS,EAAE,KACpB,IAAI,CAAC;IACV,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,mDAAmD;IACnD,WAAW,CAAC,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC;CACzC;AAiND;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,2CAqBxD"}
@@ -0,0 +1,124 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useRef } from "react";
3
+ import { AssistantRuntimeProvider, ComposerPrimitive, ThreadPrimitive, useAui, useComposer, useLocalRuntime, } from "@assistant-ui/react";
4
+ import { CompositeAttachmentAdapter, SimpleImageAttachmentAdapter, SimpleTextAttachmentAdapter, } from "@assistant-ui/react";
5
+ import { IconX } from "@tabler/icons-react";
6
+ import { cn } from "../utils.js";
7
+ import { TiptapComposer } from "./TiptapComposer.js";
8
+ import { useChatModels } from "../use-chat-models.js";
9
+ // Minimal pass-through adapter. PromptComposer always submits through
10
+ // onSubmitOverride, so the runtime never actually calls this — but
11
+ // `useLocalRuntime` needs *something* shaped like a ChatModelAdapter.
12
+ const NOOP_ADAPTER = {
13
+ async *run() {
14
+ return;
15
+ },
16
+ };
17
+ /**
18
+ * Local clone of AssistantChat's BinaryDocumentAttachmentAdapter so PDFs and
19
+ * PPTX files can be attached without dragging the whole assistant chat module
20
+ * into bundles that just want a prompt popover.
21
+ */
22
+ class BinaryDocumentAttachmentAdapter {
23
+ accept = "application/pdf,application/vnd.openxmlformats-officedocument.presentationml.presentation,.pdf,.pptx";
24
+ async add(state) {
25
+ return {
26
+ id: state.file.name,
27
+ type: "document",
28
+ name: state.file.name,
29
+ contentType: state.file.type || "application/octet-stream",
30
+ file: state.file,
31
+ status: { type: "requires-action", reason: "composer-send" },
32
+ };
33
+ }
34
+ async send(attachment) {
35
+ return {
36
+ ...attachment,
37
+ status: { type: "complete" },
38
+ content: [],
39
+ };
40
+ }
41
+ async remove() {
42
+ /* noop */
43
+ }
44
+ }
45
+ function getImageSrc(attachment) {
46
+ if (attachment.type !== "image")
47
+ return null;
48
+ if ("file" in attachment && attachment.file) {
49
+ return URL.createObjectURL(attachment.file);
50
+ }
51
+ const imagePart = attachment.content?.find((part) => part.type === "image");
52
+ return imagePart && "image" in imagePart ? imagePart.image : null;
53
+ }
54
+ function AttachmentChip({ attachment, onRemove, }) {
55
+ const src = useMemo(() => getImageSrc(attachment), [attachment]);
56
+ useEffect(() => () => {
57
+ if (src?.startsWith("blob:"))
58
+ URL.revokeObjectURL(src);
59
+ }, [src]);
60
+ if (src) {
61
+ return (_jsxs("div", { className: "group relative h-16 w-16 overflow-hidden rounded-lg border border-border/70 bg-muted/50", children: [_jsx("img", { src: src, alt: attachment.name, className: "h-full w-full object-cover" }), _jsx("button", { type: "button", onClick: () => onRemove(attachment.id), "aria-label": `Remove ${attachment.name}`, className: "absolute right-1 top-1 flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-border/60 bg-background/90 text-muted-foreground hover:text-foreground", children: _jsx(IconX, { className: "h-3 w-3" }) })] }));
62
+ }
63
+ return (_jsxs("div", { className: "group relative inline-flex max-w-[200px] items-center gap-2 rounded-md border border-border/70 bg-muted/50 px-2 py-1.5 text-xs", children: [_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded bg-background text-[9px] font-semibold uppercase text-muted-foreground", children: attachment.name.split(".").pop() || "file" }), _jsx("span", { className: "min-w-0 truncate font-medium", children: attachment.name }), _jsx("button", { type: "button", onClick: () => onRemove(attachment.id), "aria-label": `Remove ${attachment.name}`, className: "flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded text-muted-foreground hover:text-foreground", children: _jsx(IconX, { className: "h-3 w-3" }) })] }));
64
+ }
65
+ function PromptAttachmentStrip() {
66
+ const attachments = useComposer((state) => state.attachments);
67
+ const aui = useAui();
68
+ const handleRemove = useCallback((id) => {
69
+ void aui.composer().attachment({ id }).remove();
70
+ }, [aui]);
71
+ if (attachments.length === 0)
72
+ return null;
73
+ return (_jsx("div", { className: "flex flex-wrap gap-2 px-2 pt-2", children: attachments.map((attachment) => (_jsx(AttachmentChip, { attachment: attachment, onRemove: handleRemove }, attachment.id))) }));
74
+ }
75
+ function PromptComposerInner({ onSubmit, placeholder, disabled, autoFocus, className, draftScope, showModelSelector, voiceEnabled = true, attachmentsEnabled = false, composerRef, }) {
76
+ const localRef = useRef(null);
77
+ const handleRef = composerRef ?? localRef;
78
+ const models = useChatModels();
79
+ useEffect(() => {
80
+ if (!autoFocus)
81
+ return;
82
+ const id = window.setTimeout(() => {
83
+ const target = typeof handleRef === "object" && handleRef && "current" in handleRef
84
+ ? handleRef.current
85
+ : null;
86
+ target?.focus();
87
+ }, 50);
88
+ return () => window.clearTimeout(id);
89
+ }, [autoFocus, handleRef]);
90
+ const handleSubmit = useCallback((text, references, attachments) => {
91
+ const files = [];
92
+ for (const att of attachments ?? []) {
93
+ const a = att;
94
+ if ("file" in a && a.file instanceof File) {
95
+ files.push(a.file);
96
+ }
97
+ }
98
+ onSubmit(text, files, references);
99
+ }, [onSubmit]);
100
+ return (_jsx("div", { className: cn("agent-composer-area flex flex-col rounded-lg border border-input bg-background focus-within:ring-1 focus-within:ring-ring", className), children: _jsxs(ComposerPrimitive.Root, { className: "flex flex-col", children: [_jsx(PromptAttachmentStrip, {}), _jsx(TiptapComposer, { focusRef: handleRef, disabled: disabled, placeholder: placeholder, onSubmit: handleSubmit, plusMenuMode: attachmentsEnabled ? "upload-only" : "hidden", voiceEnabled: voiceEnabled, draftScope: draftScope, selectedModel: showModelSelector ? models.selectedModel : undefined, selectedEffort: showModelSelector ? models.selectedEffort : undefined, availableModels: showModelSelector ? models.availableModels : undefined, onModelChange: showModelSelector ? models.onModelChange : undefined, onEffortChange: showModelSelector ? models.onEffortChange : undefined })] }) }));
101
+ }
102
+ /**
103
+ * Standalone composer that mirrors the agent sidebar's input experience —
104
+ * voice dictation, file upload, model selector, submit-on-Enter — for use in
105
+ * popovers and inline prompt forms (create tool, create deck, create dashboard,
106
+ * the Dispatch new-app flow, etc.).
107
+ *
108
+ * The host owns submission: when the user presses Enter or clicks submit,
109
+ * `onSubmit(text, files, references)` is called. PromptComposer runs its own
110
+ * minimal assistant-ui runtime so it can be dropped into any subtree without
111
+ * needing the outer chat to be mounted.
112
+ */
113
+ export function PromptComposer(props) {
114
+ const attachmentAdapter = useMemo(() => new CompositeAttachmentAdapter([
115
+ new SimpleImageAttachmentAdapter(),
116
+ new BinaryDocumentAttachmentAdapter(),
117
+ new SimpleTextAttachmentAdapter(),
118
+ ]), []);
119
+ const runtime = useLocalRuntime(NOOP_ADAPTER, {
120
+ adapters: { attachments: attachmentAdapter },
121
+ });
122
+ return (_jsx(AssistantRuntimeProvider, { runtime: runtime, children: _jsx(ThreadPrimitive.Root, { className: "contents", children: _jsx(PromptComposerInner, { ...props }) }) }));
123
+ }
124
+ //# sourceMappingURL=PromptComposer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PromptComposer.js","sourceRoot":"","sources":["../../../src/client/composer/PromptComposer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, type Ref } from \"react\";\nimport {\n AssistantRuntimeProvider,\n ComposerPrimitive,\n ThreadPrimitive,\n useAui,\n useComposer,\n useLocalRuntime,\n} from \"@assistant-ui/react\";\nimport type {\n Attachment,\n AttachmentAdapter,\n ChatModelAdapter,\n CompleteAttachment,\n PendingAttachment,\n} from \"@assistant-ui/react\";\nimport {\n CompositeAttachmentAdapter,\n SimpleImageAttachmentAdapter,\n SimpleTextAttachmentAdapter,\n} from \"@assistant-ui/react\";\nimport { IconX } from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { TiptapComposer, type TiptapComposerHandle } from \"./TiptapComposer.js\";\nimport type { Reference } from \"./types.js\";\nimport { useChatModels } from \"../use-chat-models.js\";\n\n/**\n * Files the user attached via the \"+\" button in PromptComposer. The host owns\n * what to do with them — typically POST to a per-app upload endpoint and pass\n * the resulting URLs/paths into the prompt that gets sent to the agent.\n */\nexport type PromptComposerFile = File;\n\nexport interface PromptComposerProps {\n /** Called when the user submits the composer. */\n onSubmit: (\n text: string,\n files: PromptComposerFile[],\n references: Reference[],\n ) => void;\n placeholder?: string;\n disabled?: boolean;\n autoFocus?: boolean;\n className?: string;\n /** Forwarded to TiptapComposer for draft persistence. */\n draftScope?: string;\n /** Show the model selector (default: false). */\n showModelSelector?: boolean;\n /** Show the voice dictation button (default: true). */\n voiceEnabled?: boolean;\n /** Show file upload controls and pass submitted files to onSubmit. */\n attachmentsEnabled?: boolean;\n /** Imperative handle for focusing the composer. */\n composerRef?: Ref<TiptapComposerHandle>;\n}\n\n// Minimal pass-through adapter. PromptComposer always submits through\n// onSubmitOverride, so the runtime never actually calls this — but\n// `useLocalRuntime` needs *something* shaped like a ChatModelAdapter.\nconst NOOP_ADAPTER: ChatModelAdapter = {\n async *run() {\n return;\n },\n};\n\n/**\n * Local clone of AssistantChat's BinaryDocumentAttachmentAdapter so PDFs and\n * PPTX files can be attached without dragging the whole assistant chat module\n * into bundles that just want a prompt popover.\n */\nclass BinaryDocumentAttachmentAdapter implements AttachmentAdapter {\n public accept =\n \"application/pdf,application/vnd.openxmlformats-officedocument.presentationml.presentation,.pdf,.pptx\";\n\n public async add(state: { file: File }): Promise<PendingAttachment> {\n return {\n id: state.file.name,\n type: \"document\",\n name: state.file.name,\n contentType: state.file.type || \"application/octet-stream\",\n file: state.file,\n status: { type: \"requires-action\", reason: \"composer-send\" },\n };\n }\n\n public async send(\n attachment: PendingAttachment,\n ): Promise<CompleteAttachment> {\n return {\n ...attachment,\n status: { type: \"complete\" },\n content: [],\n };\n }\n\n public async remove() {\n /* noop */\n }\n}\n\nfunction getImageSrc(attachment: Attachment): string | null {\n if (attachment.type !== \"image\") return null;\n if (\"file\" in attachment && attachment.file) {\n return URL.createObjectURL(attachment.file);\n }\n const imagePart = attachment.content?.find((part) => part.type === \"image\");\n return imagePart && \"image\" in imagePart ? imagePart.image : null;\n}\n\nfunction AttachmentChip({\n attachment,\n onRemove,\n}: {\n attachment: Attachment;\n onRemove: (id: string) => void;\n}) {\n const src = useMemo(() => getImageSrc(attachment), [attachment]);\n useEffect(\n () => () => {\n if (src?.startsWith(\"blob:\")) URL.revokeObjectURL(src);\n },\n [src],\n );\n\n if (src) {\n return (\n <div className=\"group relative h-16 w-16 overflow-hidden rounded-lg border border-border/70 bg-muted/50\">\n <img\n src={src}\n alt={attachment.name}\n className=\"h-full w-full object-cover\"\n />\n <button\n type=\"button\"\n onClick={() => onRemove(attachment.id)}\n aria-label={`Remove ${attachment.name}`}\n className=\"absolute right-1 top-1 flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-border/60 bg-background/90 text-muted-foreground hover:text-foreground\"\n >\n <IconX className=\"h-3 w-3\" />\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"group relative inline-flex max-w-[200px] items-center gap-2 rounded-md border border-border/70 bg-muted/50 px-2 py-1.5 text-xs\">\n <div className=\"flex h-6 w-6 shrink-0 items-center justify-center rounded bg-background text-[9px] font-semibold uppercase text-muted-foreground\">\n {attachment.name.split(\".\").pop() || \"file\"}\n </div>\n <span className=\"min-w-0 truncate font-medium\">{attachment.name}</span>\n <button\n type=\"button\"\n onClick={() => onRemove(attachment.id)}\n aria-label={`Remove ${attachment.name}`}\n className=\"flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded text-muted-foreground hover:text-foreground\"\n >\n <IconX className=\"h-3 w-3\" />\n </button>\n </div>\n );\n}\n\nfunction PromptAttachmentStrip() {\n const attachments = useComposer((state) => state.attachments);\n const aui = useAui();\n\n const handleRemove = useCallback(\n (id: string) => {\n void aui.composer().attachment({ id }).remove();\n },\n [aui],\n );\n\n if (attachments.length === 0) return null;\n return (\n <div className=\"flex flex-wrap gap-2 px-2 pt-2\">\n {attachments.map((attachment) => (\n <AttachmentChip\n key={attachment.id}\n attachment={attachment}\n onRemove={handleRemove}\n />\n ))}\n </div>\n );\n}\n\nfunction PromptComposerInner({\n onSubmit,\n placeholder,\n disabled,\n autoFocus,\n className,\n draftScope,\n showModelSelector,\n voiceEnabled = true,\n attachmentsEnabled = false,\n composerRef,\n}: PromptComposerProps) {\n const localRef = useRef<TiptapComposerHandle>(null);\n const handleRef = composerRef ?? localRef;\n const models = useChatModels();\n\n useEffect(() => {\n if (!autoFocus) return;\n const id = window.setTimeout(() => {\n const target =\n typeof handleRef === \"object\" && handleRef && \"current\" in handleRef\n ? handleRef.current\n : null;\n target?.focus();\n }, 50);\n return () => window.clearTimeout(id);\n }, [autoFocus, handleRef]);\n\n const handleSubmit = useCallback(\n (\n text: string,\n references: Reference[],\n attachments?: ReadonlyArray<unknown>,\n ) => {\n const files: File[] = [];\n for (const att of attachments ?? []) {\n const a = att as Attachment;\n if (\"file\" in a && a.file instanceof File) {\n files.push(a.file);\n }\n }\n onSubmit(text, files, references);\n },\n [onSubmit],\n );\n\n return (\n <div\n className={cn(\n \"agent-composer-area flex flex-col rounded-lg border border-input bg-background focus-within:ring-1 focus-within:ring-ring\",\n className,\n )}\n >\n <ComposerPrimitive.Root className=\"flex flex-col\">\n <PromptAttachmentStrip />\n <TiptapComposer\n focusRef={handleRef}\n disabled={disabled}\n placeholder={placeholder}\n onSubmit={handleSubmit}\n plusMenuMode={attachmentsEnabled ? \"upload-only\" : \"hidden\"}\n voiceEnabled={voiceEnabled}\n draftScope={draftScope}\n selectedModel={showModelSelector ? models.selectedModel : undefined}\n selectedEffort={showModelSelector ? models.selectedEffort : undefined}\n availableModels={\n showModelSelector ? models.availableModels : undefined\n }\n onModelChange={showModelSelector ? models.onModelChange : undefined}\n onEffortChange={showModelSelector ? models.onEffortChange : undefined}\n />\n </ComposerPrimitive.Root>\n </div>\n );\n}\n\n/**\n * Standalone composer that mirrors the agent sidebar's input experience —\n * voice dictation, file upload, model selector, submit-on-Enter — for use in\n * popovers and inline prompt forms (create tool, create deck, create dashboard,\n * the Dispatch new-app flow, etc.).\n *\n * The host owns submission: when the user presses Enter or clicks submit,\n * `onSubmit(text, files, references)` is called. PromptComposer runs its own\n * minimal assistant-ui runtime so it can be dropped into any subtree without\n * needing the outer chat to be mounted.\n */\nexport function PromptComposer(props: PromptComposerProps) {\n const attachmentAdapter = useMemo(\n () =>\n new CompositeAttachmentAdapter([\n new SimpleImageAttachmentAdapter(),\n new BinaryDocumentAttachmentAdapter(),\n new SimpleTextAttachmentAdapter(),\n ]),\n [],\n );\n const runtime = useLocalRuntime(NOOP_ADAPTER, {\n adapters: { attachments: attachmentAdapter },\n });\n\n return (\n <AssistantRuntimeProvider runtime={runtime}>\n <ThreadPrimitive.Root className=\"contents\">\n <PromptComposerInner {...props} />\n </ThreadPrimitive.Root>\n </AssistantRuntimeProvider>\n );\n}\n"]}
@@ -9,8 +9,12 @@ interface TiptapComposerProps {
9
9
  placeholder?: string;
10
10
  disabled?: boolean;
11
11
  focusRef?: React.Ref<TiptapComposerHandle>;
12
- /** When provided, called instead of composerRuntime.send(). Used for queue mode. */
13
- onSubmit?: (text: string, references: Reference[]) => void;
12
+ /**
13
+ * When provided, called instead of composerRuntime.send(). Used for queue
14
+ * mode and standalone prompt popovers. Receives the live composer
15
+ * attachments so callers (e.g. PromptComposer) can surface uploaded files.
16
+ */
17
+ onSubmit?: (text: string, references: Reference[], attachments?: ReadonlyArray<unknown>) => void;
14
18
  /** Custom action button (e.g. stop button) to render instead of the default send button. */
15
19
  actionButton?: React.ReactNode;
16
20
  /** Extra button to render alongside the default send button (e.g. stop while running). */
@@ -42,7 +46,14 @@ interface TiptapComposerProps {
42
46
  onEffortChange?: (effort: ReasoningEffort) => void;
43
47
  /** Stable scope for persisted drafts, usually the active thread or tab id. */
44
48
  draftScope?: string;
49
+ /**
50
+ * Controls the "+" menu next to the composer. `"full"` (default) shows the
51
+ * normal Upload / Skill / Job / Automation / Tool / MCP picker. `"upload-only"`
52
+ * collapses it to a single button that opens the file picker directly.
53
+ * `"hidden"` hides attachment controls for text-only prompt surfaces.
54
+ */
55
+ plusMenuMode?: "full" | "upload-only" | "hidden";
45
56
  }
46
- export declare function TiptapComposer({ placeholder, disabled, focusRef, onSubmit, actionButton, extraActionButton, attachButton, onSlashCommand, execMode, onExecModeChange, voiceEnabled, selectedModel, selectedEffort, availableModels, onModelChange, onEffortChange, draftScope, }: TiptapComposerProps): import("react/jsx-runtime").JSX.Element;
57
+ export declare function TiptapComposer({ placeholder, disabled, focusRef, onSubmit, actionButton, extraActionButton, attachButton, onSlashCommand, execMode, onExecModeChange, voiceEnabled, selectedModel, selectedEffort, availableModels, onModelChange, onEffortChange, draftScope, plusMenuMode, }: TiptapComposerProps): import("react/jsx-runtime").JSX.Element;
47
58
  export {};
48
59
  //# sourceMappingURL=TiptapComposer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TiptapComposer.d.ts","sourceRoot":"","sources":["../../../src/client/composer/TiptapComposer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAgCf,OAAO,KAAK,EAGV,SAAS,EAGV,MAAM,YAAY,CAAC;AAMpB,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,kCAAkC,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AAwHD,KAAK,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjC,UAAU,mBAAmB;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC3C,oFAAoF;IACpF,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC3D,4FAA4F;IAC5F,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,0FAA0F;IAC1F,iBAAiB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACpC,qFAAqF;IACrF,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC5C,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,2CAA2C;IAC3C,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC,CAAC;IACH,uCAAuC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,kDAAkD;IAClD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA8YD,wBAAgB,cAAc,CAAC,EAC7B,WAAgC,EAChC,QAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,YAAmB,EACnB,aAAa,EACb,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,EACd,UAAU,GACX,EAAE,mBAAmB,2CAw2BrB"}
1
+ {"version":3,"file":"TiptapComposer.d.ts","sourceRoot":"","sources":["../../../src/client/composer/TiptapComposer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAgCf,OAAO,KAAK,EAGV,SAAS,EAGV,MAAM,YAAY,CAAC;AAMpB,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,kCAAkC,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AAwHD,KAAK,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjC,UAAU,mBAAmB;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CACT,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,SAAS,EAAE,EACvB,WAAW,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,KACjC,IAAI,CAAC;IACV,4FAA4F;IAC5F,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,0FAA0F;IAC1F,iBAAiB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACpC,qFAAqF;IACrF,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC5C,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,2CAA2C;IAC3C,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC,CAAC;IACH,uCAAuC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,kDAAkD;IAClD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,CAAC;CAClD;AA8YD,wBAAgB,cAAc,CAAC,EAC7B,WAAgC,EAChC,QAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,YAAmB,EACnB,aAAa,EACb,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,EACd,UAAU,EACV,YAAqB,GACtB,EAAE,mBAAmB,2CAk3BrB"}
@@ -261,7 +261,7 @@ function ModelSelector({ model, effort = "auto", engines, onChange, onEffortChan
261
261
  : "opacity-40 cursor-default"}`, children: [_jsx("span", { className: "flex-1 min-w-0 text-[13px] text-foreground truncate", children: friendlyModelName(m) }), m === model && group.configured && (_jsx(IconCheck, { className: "h-3.5 w-3.5 shrink-0 text-blue-500" }))] }, m)))] }, groupKey));
262
262
  }), effortOptions.length > 0 && (_jsxs(_Fragment, { children: [_jsx("div", { className: "my-1 border-t border-border" }), _jsx("div", { className: "px-3 py-1.5 text-[11px] font-medium text-muted-foreground uppercase tracking-wide", children: "Effort" }), effortOptions.map((option) => (_jsxs("button", { type: "button", onClick: () => onEffortChange?.(option), className: "flex w-full items-center gap-3 px-3 py-1.5 text-left hover:bg-accent/50", children: [_jsx("span", { className: "flex-1 min-w-0 text-[13px] text-foreground truncate", children: reasoningEffortLabel(option) }), option === effort && (_jsx(IconCheck, { className: "h-3.5 w-3.5 shrink-0 text-blue-500" }))] }, option)))] }))] }) })] }));
263
263
  }
264
- export function TiptapComposer({ placeholder = "Message agent...", disabled = false, focusRef, onSubmit, actionButton, extraActionButton, attachButton, onSlashCommand, execMode, onExecModeChange, voiceEnabled = true, selectedModel, selectedEffort, availableModels, onModelChange, onEffortChange, draftScope, }) {
264
+ export function TiptapComposer({ placeholder = "Message agent...", disabled = false, focusRef, onSubmit, actionButton, extraActionButton, attachButton, onSlashCommand, execMode, onExecModeChange, voiceEnabled = true, selectedModel, selectedEffort, availableModels, onModelChange, onEffortChange, draftScope, plusMenuMode = "full", }) {
265
265
  const [popover, setPopover] = useState(null);
266
266
  const popoverRef = useRef(null);
267
267
  const composerRuntime = useComposerRuntime();
@@ -734,7 +734,8 @@ export function TiptapComposer({ placeholder = "Message agent...", disabled = fa
734
734
  if (!ed)
735
735
  return;
736
736
  const { text, references } = syncComposerState();
737
- if (!text.trim() && references.length === 0)
737
+ const attachments = composerRuntime.getState().attachments;
738
+ if (!text.trim() && references.length === 0 && attachments.length === 0)
738
739
  return;
739
740
  // Intercept slash commands typed directly (e.g. "/clear" + Enter)
740
741
  const trimmed = text.trim();
@@ -773,7 +774,9 @@ export function TiptapComposer({ placeholder = "Message agent...", disabled = fa
773
774
  return;
774
775
  }
775
776
  if (onSubmit) {
776
- onSubmit(text, references);
777
+ onSubmit(text, references, attachments);
778
+ // Clear any pending attachments now that the host has them.
779
+ void composerRuntime.clearAttachments().catch(() => { });
777
780
  }
778
781
  else {
779
782
  composerRuntime.send();
@@ -971,6 +974,7 @@ export function TiptapComposer({ placeholder = "Message agent...", disabled = fa
971
974
  setComposerMode(null);
972
975
  composerModeRef.current = null;
973
976
  editor?.commands.focus("end");
974
- } }) })), _jsx("div", { className: composerMode ? "px-2 pt-1 pb-1" : "px-2 pt-2 pb-1", children: _jsx(EditorContent, { editor: editor, className: "aui-composer flex-1 min-w-0 [&_.ProseMirror]:outline-none [&_.ProseMirror_p]:m-0 px-0.5" }) }), voiceEnabled && _jsx(VoiceRecordingOverlay, { voice: voice }), _jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [attachButton ?? _jsx(ComposerPlusMenu, { onSelectMode: handleSelectMode }), _jsx("div", { className: "flex-1" }), actionButton ?? (_jsxs(_Fragment, { children: [selectedModel && availableModels && onModelChange && (_jsx(ModelSelector, { model: selectedModel, effort: selectedEffort, engines: availableModels, onChange: onModelChange, onEffortChange: onEffortChange })), execMode && onExecModeChange && (_jsx(ModeSelector, { mode: execMode, onChange: onExecModeChange })), voiceEnabled && (_jsx(VoiceButton, { voice: voice, isMac: isMac, disabled: disabled })), extraActionButton, _jsx("button", { type: "button", onClick: submitComposer, disabled: !canSend, className: "shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-primary text-primary-foreground hover:opacity-90 disabled:opacity-30 disabled:cursor-not-allowed", title: "Send message", children: _jsx(IconArrowUp, { className: "h-3.5 w-3.5" }) })] }))] }), _jsx(MentionPopover, { ref: popoverRef, type: popover?.type ?? "@", position: popover?.position ?? null, mentionItems: mentionItems, skills: filteredSkills, commands: filteredCommands, hint: hint, isLoading: popover?.type === "@" ? mentionsLoading : skillsLoading, query: popover?.query ?? "", onSelectMention: handleSelectMention, onSelectSkill: handleSelectSkill, onSelectCommand: handleSelectCommand, onClose: closePopover })] }));
977
+ } }) })), _jsx("div", { className: composerMode ? "px-2 pt-1 pb-1" : "px-2 pt-2 pb-1", children: _jsx(EditorContent, { editor: editor, className: "aui-composer flex-1 min-w-0 [&_.ProseMirror]:outline-none [&_.ProseMirror_p]:m-0 px-0.5" }) }), voiceEnabled && _jsx(VoiceRecordingOverlay, { voice: voice }), _jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [attachButton ??
978
+ (plusMenuMode === "hidden" ? null : (_jsx(ComposerPlusMenu, { onSelectMode: handleSelectMode, mode: plusMenuMode }))), _jsx("div", { className: "flex-1" }), actionButton ?? (_jsxs(_Fragment, { children: [selectedModel && availableModels && onModelChange && (_jsx(ModelSelector, { model: selectedModel, effort: selectedEffort, engines: availableModels, onChange: onModelChange, onEffortChange: onEffortChange })), execMode && onExecModeChange && (_jsx(ModeSelector, { mode: execMode, onChange: onExecModeChange })), voiceEnabled && (_jsx(VoiceButton, { voice: voice, isMac: isMac, disabled: disabled })), extraActionButton, _jsx("button", { type: "button", onClick: submitComposer, disabled: !canSend, className: "shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-primary text-primary-foreground hover:opacity-90 disabled:opacity-30 disabled:cursor-not-allowed", title: "Send message", children: _jsx(IconArrowUp, { className: "h-3.5 w-3.5" }) })] }))] }), _jsx(MentionPopover, { ref: popoverRef, type: popover?.type ?? "@", position: popover?.position ?? null, mentionItems: mentionItems, skills: filteredSkills, commands: filteredCommands, hint: hint, isLoading: popover?.type === "@" ? mentionsLoading : skillsLoading, query: popover?.query ?? "", onSelectMention: handleSelectMention, onSelectSkill: handleSelectSkill, onSelectCommand: handleSelectCommand, onClose: closePopover })] }));
975
979
  }
976
980
  //# sourceMappingURL=TiptapComposer.js.map