@agent-native/core 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/a2a/caller-auth.d.ts +12 -0
  2. package/dist/a2a/caller-auth.d.ts.map +1 -0
  3. package/dist/a2a/caller-auth.js +54 -0
  4. package/dist/a2a/caller-auth.js.map +1 -0
  5. package/dist/action.d.ts +17 -0
  6. package/dist/action.d.ts.map +1 -1
  7. package/dist/action.js +22 -0
  8. package/dist/action.js.map +1 -1
  9. package/dist/agent/production-agent.d.ts.map +1 -1
  10. package/dist/agent/production-agent.js +32 -19
  11. package/dist/agent/production-agent.js.map +1 -1
  12. package/dist/client/AgentPanel.d.ts.map +1 -1
  13. package/dist/client/AgentPanel.js +3 -3
  14. package/dist/client/AgentPanel.js.map +1 -1
  15. package/dist/client/AssistantChat.d.ts.map +1 -1
  16. package/dist/client/AssistantChat.js +17 -6
  17. package/dist/client/AssistantChat.js.map +1 -1
  18. package/dist/client/components/ui/dropdown-menu.d.ts +28 -0
  19. package/dist/client/components/ui/dropdown-menu.d.ts.map +1 -0
  20. package/dist/client/components/ui/dropdown-menu.js +34 -0
  21. package/dist/client/components/ui/dropdown-menu.js.map +1 -0
  22. package/dist/client/composer/TiptapComposer.js +1 -1
  23. package/dist/client/composer/TiptapComposer.js.map +1 -1
  24. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  25. package/dist/client/extensions/EmbeddedExtension.js +2 -0
  26. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  27. package/dist/client/extensions/ExtensionSlot.js +14 -1
  28. package/dist/client/extensions/ExtensionSlot.js.map +1 -1
  29. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  30. package/dist/client/extensions/ExtensionViewer.js +2 -0
  31. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  32. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
  33. package/dist/client/extensions/ExtensionsListPage.js +2 -2
  34. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  35. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
  36. package/dist/client/extensions/ExtensionsSidebarSection.js +6 -17
  37. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  38. package/dist/client/extensions/iframe-bridge.d.ts.map +1 -1
  39. package/dist/client/extensions/iframe-bridge.js +5 -8
  40. package/dist/client/extensions/iframe-bridge.js.map +1 -1
  41. package/dist/client/org/OrgSwitcher.d.ts +7 -1
  42. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  43. package/dist/client/org/OrgSwitcher.js +8 -3
  44. package/dist/client/org/OrgSwitcher.js.map +1 -1
  45. package/dist/client/org/TeamPage.d.ts.map +1 -1
  46. package/dist/client/org/TeamPage.js +153 -20
  47. package/dist/client/org/TeamPage.js.map +1 -1
  48. package/dist/client/org/hooks.d.ts +29 -1
  49. package/dist/client/org/hooks.d.ts.map +1 -1
  50. package/dist/client/org/hooks.js +39 -2
  51. package/dist/client/org/hooks.js.map +1 -1
  52. package/dist/client/org/index.d.ts +2 -1
  53. package/dist/client/org/index.d.ts.map +1 -1
  54. package/dist/client/org/index.js +1 -1
  55. package/dist/client/org/index.js.map +1 -1
  56. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  57. package/dist/client/resources/ResourceTree.js +11 -3
  58. package/dist/client/resources/ResourceTree.js.map +1 -1
  59. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  60. package/dist/client/resources/ResourcesPanel.js +21 -5
  61. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  62. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  63. package/dist/client/settings/SettingsPanel.js +39 -3
  64. package/dist/client/settings/SettingsPanel.js.map +1 -1
  65. package/dist/deploy/build.d.ts.map +1 -1
  66. package/dist/deploy/build.js +20 -49
  67. package/dist/deploy/build.js.map +1 -1
  68. package/dist/index.browser.d.ts +1 -1
  69. package/dist/index.browser.d.ts.map +1 -1
  70. package/dist/index.browser.js +1 -1
  71. package/dist/index.browser.js.map +1 -1
  72. package/dist/index.d.ts +1 -1
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +1 -1
  75. package/dist/index.js.map +1 -1
  76. package/dist/org/accept-pending.d.ts.map +1 -1
  77. package/dist/org/accept-pending.js +5 -3
  78. package/dist/org/accept-pending.js.map +1 -1
  79. package/dist/org/free-email-providers.d.ts +18 -0
  80. package/dist/org/free-email-providers.d.ts.map +1 -0
  81. package/dist/org/free-email-providers.js +124 -0
  82. package/dist/org/free-email-providers.js.map +1 -0
  83. package/dist/org/handlers.d.ts +29 -5
  84. package/dist/org/handlers.d.ts.map +1 -1
  85. package/dist/org/handlers.js +178 -37
  86. package/dist/org/handlers.js.map +1 -1
  87. package/dist/org/index.d.ts +2 -1
  88. package/dist/org/index.d.ts.map +1 -1
  89. package/dist/org/index.js +2 -1
  90. package/dist/org/index.js.map +1 -1
  91. package/dist/org/migrations.d.ts.map +1 -1
  92. package/dist/org/migrations.js +4 -0
  93. package/dist/org/migrations.js.map +1 -1
  94. package/dist/org/plugin.d.ts.map +1 -1
  95. package/dist/org/plugin.js +13 -4
  96. package/dist/org/plugin.js.map +1 -1
  97. package/dist/org/schema.d.ts +19 -0
  98. package/dist/org/schema.d.ts.map +1 -1
  99. package/dist/org/schema.js +1 -0
  100. package/dist/org/schema.js.map +1 -1
  101. package/dist/org/types.d.ts +1 -0
  102. package/dist/org/types.d.ts.map +1 -1
  103. package/dist/org/types.js.map +1 -1
  104. package/dist/resources/metadata.d.ts +1 -0
  105. package/dist/resources/metadata.d.ts.map +1 -1
  106. package/dist/resources/metadata.js +13 -3
  107. package/dist/resources/metadata.js.map +1 -1
  108. package/dist/resources/store.d.ts.map +1 -1
  109. package/dist/resources/store.js +44 -6
  110. package/dist/resources/store.js.map +1 -1
  111. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  112. package/dist/server/agent-chat-plugin.js +38 -11
  113. package/dist/server/agent-chat-plugin.js.map +1 -1
  114. package/dist/server/google-oauth.d.ts.map +1 -1
  115. package/dist/server/google-oauth.js +10 -3
  116. package/dist/server/google-oauth.js.map +1 -1
  117. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/client/org/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EACT,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAoC5B,wBAAgB,MAAM,mEAMrB;AAED,wBAAgB,aAAa;aACA,SAAS,EAAE;UAKvC;AAED,wBAAgB,iBAAiB;iBACA,oBAAoB,EAAE;UAKtD;AAmBD,wBAAgB,YAAY,mFAe3B;AAED,wBAAgB,eAAe,mFAe9B;AAED,wBAAgB,mBAAmB,mFAclC;AAED,wBAAgB,eAAe,mFAW9B;AAED,wBAAgB,YAAY,mFAY3B;AAED,wBAAgB,YAAY,mFAa3B;AAED,wBAAgB,eAAe,mFAY9B;AAED,wBAAgB,eAAe,mFAY9B;AAED,wBAAgB,eAAe;eAGd,MAAM;oBAAkB,MAAM,GAAG,IAAI;2BAarD;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,KAAK,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,EAAE,EAAE,OAAO,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB;iBAIb,MAAM;YAWxB"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/client/org/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EACT,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAoC5B,wBAAgB,MAAM,mEAMrB;AAED,wBAAgB,aAAa;aACA,SAAS,EAAE;UAKvC;AAED,wBAAgB,iBAAiB;iBACA,oBAAoB,EAAE;UAKtD;AAmBD,wBAAgB,YAAY,mFAe3B;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,wBAAgB,eAAe,gGAoB9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,UAAU,CAAC;QACjB,MAAM,EAAE,SAAS,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,oBAAoB,sGAoBnC;AAED,wBAAgB,mBAAmB;WAGtB,MAAM;UAAQ,UAAU;;WAExB,MAAM;UAAQ,UAAU;YAWpC;AAED,wBAAgB,mBAAmB,mFAclC;AAED,wBAAgB,eAAe,mFAW9B;AAED,wBAAgB,YAAY,mFAY3B;AAED,wBAAgB,YAAY,mFAa3B;AAED,wBAAgB,eAAe,mFAY9B;AAED,wBAAgB,eAAe,mFAY9B;AAED,wBAAgB,eAAe;eAGd,MAAM;oBAAkB,MAAM,GAAG,IAAI;2BAarD;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,KAAK,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,EAAE,EAAE,OAAO,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB;iBAIb,MAAM;YAWxB"}
@@ -84,9 +84,34 @@ export function useCreateOrg() {
84
84
  export function useInviteMember() {
85
85
  const qc = useQueryClient();
86
86
  return useMutation({
87
- mutationFn: (email) => apiFetch(`${ORG_BASE}/invitations`, {
87
+ mutationFn: (vars) => {
88
+ const body = typeof vars === "string"
89
+ ? { email: vars, role: "member" }
90
+ : { email: vars.email, role: vars.role ?? "member" };
91
+ return apiFetch(`${ORG_BASE}/invitations`, {
92
+ method: "POST",
93
+ body: JSON.stringify(body),
94
+ });
95
+ },
96
+ onSuccess: async () => {
97
+ await Promise.all([
98
+ qc.invalidateQueries({ queryKey: ["org-members"] }),
99
+ qc.invalidateQueries({ queryKey: ["org-invitations"] }),
100
+ ]);
101
+ },
102
+ });
103
+ }
104
+ export function useBulkInviteMembers() {
105
+ const qc = useQueryClient();
106
+ return useMutation({
107
+ mutationFn: (invites) => apiFetch(`${ORG_BASE}/invitations`, {
88
108
  method: "POST",
89
- body: JSON.stringify({ email }),
109
+ body: JSON.stringify({
110
+ invites: invites.map((i) => ({
111
+ email: i.email,
112
+ role: i.role ?? "member",
113
+ })),
114
+ }),
90
115
  }),
91
116
  onSuccess: async () => {
92
117
  await Promise.all([
@@ -96,6 +121,18 @@ export function useInviteMember() {
96
121
  },
97
122
  });
98
123
  }
124
+ export function useChangeMemberRole() {
125
+ const qc = useQueryClient();
126
+ return useMutation({
127
+ mutationFn: ({ email, role }) => apiFetch(`${ORG_BASE}/members/${encodeURIComponent(email)}/role`, {
128
+ method: "PUT",
129
+ body: JSON.stringify({ role }),
130
+ }),
131
+ onSuccess: async () => {
132
+ await qc.invalidateQueries({ queryKey: ["org-members"] });
133
+ },
134
+ });
135
+ }
99
136
  export function useAcceptInvitation() {
100
137
  const qc = useQueryClient();
101
138
  return useMutation({
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/client/org/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAM9E,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,QAAQ,GAAG,eAAe,CAAC,oBAAoB,CAAC,CAAC;AAEvD,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,IAAkB;IACtD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE;QAC5B,GAAG,IAAI;QACP,WAAW,EAAE,SAAS;QACtB,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,GAAG,IAAI,EAAE,OAAO;SACjB;KACF,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,uEAAuE;QACvE,qEAAqE;QACrE,2DAA2D;QAC3D,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,IAAI,OAAO,GAAW,GAAG,CAAC,UAAU,CAAC;QACrC,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAG7B,CAAC;gBACF,OAAO,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC;YACnD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,OAAO,QAAQ,CAAU;QACvB,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,KAAK,CAAC;QACzC,SAAS,EAAE,MAAM;KAClB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,QAAQ,CAA2B;QACxC,QAAQ,EAAE,CAAC,aAAa,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,UAAU,CAAC;QAC9C,SAAS,EAAE,MAAM;KAClB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,QAAQ,CAA0C;QACvD,QAAQ,EAAE,CAAC,iBAAiB,CAAC;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,cAAc,CAAC;QAClD,SAAS,EAAE,MAAM;KAClB,CAAC,CAAC;AACL,CAAC;AAED,mEAAmE;AACnE,wCAAwC;AACxC,oEAAoE;AACpE,qEAAqE;AACrE,qEAAqE;AACrE,4CAA4C;AAC5C,8DAA8D;AAC9D,oEAAoE;AACpE,EAAE;AACF,mEAAmE;AACnE,kEAAkE;AAClE,6DAA6D;AAC7D,oEAAoE;AACpE,qEAAqE;AACrE,oEAAoE;AACpE,yCAAyC;AAEzC,MAAM,UAAU,YAAY;IAC1B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,IAAY,EAAE,EAAE,CAC3B,QAAQ,CAAC,QAAQ,EAAE;YACjB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;SAC/B,CAAC;QACJ,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,OAAO,CAAC,GAAG,CAAC;gBAChB,EAAE,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9C,EAAE,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;aACpD,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,KAAa,EAAE,EAAE,CAC5B,QAAQ,CAAC,GAAG,QAAQ,cAAc,EAAE;YAClC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;SAChC,CAAC;QACJ,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,OAAO,CAAC,GAAG,CAAC;gBAChB,EAAE,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;gBACnD,EAAE,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;aACxD,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,YAAoB,EAAE,EAAE,CACnC,QAAQ,CAAC,GAAG,QAAQ,gBAAgB,YAAY,SAAS,EAAE;YACzD,MAAM,EAAE,MAAM;SACf,CAAC;QACJ,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,kEAAkE;YAClE,iEAAiE;YACjE,mCAAmC;YACnC,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAC/B,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,KAAa,EAAE,EAAE,CAC5B,QAAQ,CAAC,GAAG,QAAQ,YAAY,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE;YAC3D,MAAM,EAAE,QAAQ;SACjB,CAAC;QACJ,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,EAAE,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QAC5D,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,IAAY,EAAE,EAAE,CAC3B,QAAQ,CAAC,QAAQ,EAAE;YACjB,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;SAC/B,CAAC;QACJ,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,EAAE,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvD,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,KAAoB,EAAE,EAAE,CACnC,QAAQ,CAAC,GAAG,QAAQ,SAAS,EAAE;YAC7B,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;SAChC,CAAC;QACJ,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,2DAA2D;YAC3D,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAC/B,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,KAAa,EAAE,EAAE,CAC5B,QAAQ,CAAC,GAAG,QAAQ,iBAAiB,EAAE;YACrC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;SAChC,CAAC;QACJ,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAC/B,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,MAAqB,EAAE,EAAE,CACpC,QAAQ,CAAC,GAAG,QAAQ,SAAS,EAAE;YAC7B,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;SACjC,CAAC;QACJ,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,EAAE,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvD,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,OAAO,WAAW,CAIhB;QACA,UAAU,EAAE,CAAC,MAAe,EAAE,EAAE,CAC9B,QAAQ,CAAC,GAAG,QAAQ,aAAa,EAAE;YACjC,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;SACjC,CAAC;QACJ,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,EAAE,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvD,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAgBD;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,WAAW,CAIhB;QACA,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CACnB,QAAQ,CAAC,GAAG,QAAQ,kBAAkB,EAAE;YACtC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,UAAU,EACR,IAAI,IAAI,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;aAC7D,CAAC;SACH,CAAC;KACL,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { useQuery, useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n OrgInfo,\n OrgMember,\n OrgPendingInvitation,\n} from \"../../org/types.js\";\nimport { agentNativePath } from \"../api-path.js\";\n\nconst ORG_BASE = agentNativePath(\"/_agent-native/org\");\n\nasync function apiFetch(path: string, init?: RequestInit) {\n const res = await fetch(path, {\n ...init,\n credentials: \"include\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...init?.headers,\n },\n });\n if (!res.ok) {\n // Prefer a JSON `error` / `message` field when the server returns one,\n // and only fall back to the raw body for plaintext responses. Avoids\n // surfacing `{\"error\":\"...\"}` as the user-visible message.\n const text = await res.text().catch(() => \"\");\n let message: string = res.statusText;\n if (text) {\n try {\n const parsed = JSON.parse(text) as {\n error?: string;\n message?: string;\n };\n message = parsed.error ?? parsed.message ?? text;\n } catch {\n message = text;\n }\n }\n throw new Error(message);\n }\n return res.json();\n}\n\nexport function useOrg() {\n return useQuery<OrgInfo>({\n queryKey: [\"org-me\"],\n queryFn: () => apiFetch(`${ORG_BASE}/me`),\n staleTime: 30_000,\n });\n}\n\nexport function useOrgMembers() {\n return useQuery<{ members: OrgMember[] }>({\n queryKey: [\"org-members\"],\n queryFn: () => apiFetch(`${ORG_BASE}/members`),\n staleTime: 30_000,\n });\n}\n\nexport function useOrgInvitations() {\n return useQuery<{ invitations: OrgPendingInvitation[] }>({\n queryKey: [\"org-invitations\"],\n queryFn: () => apiFetch(`${ORG_BASE}/invitations`),\n staleTime: 30_000,\n });\n}\n\n// NOTE: the onSuccess handlers below `await invalidateQueries`. In\n// TanStack Query v5, invalidateQueries:\n// 1. Marks every matching query as stale, so the next mount of an\n// INACTIVE query (e.g. the org-members table on a settings page\n// the user hasn't visited yet) refetches immediately instead of\n// serving 30-second-stale cached data.\n// 2. Triggers a refetch of every ACTIVE query that matches.\n// 3. Returns a promise that resolves once those refetches settle.\n//\n// `await`ing therefore keeps `mutation.isPending` true through the\n// full read-after-write window — closing the create-org / accept-\n// invite race where a button could re-enable mid-refetch. We\n// previously tried refetchQueries here for \"unambiguous semantics\",\n// but that variant doesn't mark inactive queries stale, leaving them\n// to serve stale data on next mount. invalidateQueries is the right\n// primitive — it just needed an `await`.\n\nexport function useCreateOrg() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (name: string) =>\n apiFetch(ORG_BASE, {\n method: \"POST\",\n body: JSON.stringify({ name }),\n }),\n onSuccess: async () => {\n await Promise.all([\n qc.invalidateQueries({ queryKey: [\"org-me\"] }),\n qc.invalidateQueries({ queryKey: [\"org-members\"] }),\n ]);\n },\n });\n}\n\nexport function useInviteMember() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (email: string) =>\n apiFetch(`${ORG_BASE}/invitations`, {\n method: \"POST\",\n body: JSON.stringify({ email }),\n }),\n onSuccess: async () => {\n await Promise.all([\n qc.invalidateQueries({ queryKey: [\"org-members\"] }),\n qc.invalidateQueries({ queryKey: [\"org-invitations\"] }),\n ]);\n },\n });\n}\n\nexport function useAcceptInvitation() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (invitationId: string) =>\n apiFetch(`${ORG_BASE}/invitations/${invitationId}/accept`, {\n method: \"POST\",\n }),\n onSuccess: async () => {\n // Joining/switching orgs changes all org-scoped data — invalidate\n // every cached query (no key filter) so each one refetches or is\n // marked stale for the next mount.\n await qc.invalidateQueries();\n },\n });\n}\n\nexport function useRemoveMember() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (email: string) =>\n apiFetch(`${ORG_BASE}/members/${encodeURIComponent(email)}`, {\n method: \"DELETE\",\n }),\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: [\"org-members\"] });\n },\n });\n}\n\nexport function useUpdateOrg() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (name: string) =>\n apiFetch(ORG_BASE, {\n method: \"PATCH\",\n body: JSON.stringify({ name }),\n }),\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: [\"org-me\"] });\n },\n });\n}\n\nexport function useSwitchOrg() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (orgId: string | null) =>\n apiFetch(`${ORG_BASE}/switch`, {\n method: \"PUT\",\n body: JSON.stringify({ orgId }),\n }),\n onSuccess: async () => {\n // Switching org changes everything scoped to AGENT_ORG_ID.\n await qc.invalidateQueries();\n },\n });\n}\n\nexport function useJoinByDomain() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (orgId: string) =>\n apiFetch(`${ORG_BASE}/join-by-domain`, {\n method: \"POST\",\n body: JSON.stringify({ orgId }),\n }),\n onSuccess: async () => {\n await qc.invalidateQueries();\n },\n });\n}\n\nexport function useSetOrgDomain() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (domain: string | null) =>\n apiFetch(`${ORG_BASE}/domain`, {\n method: \"PUT\",\n body: JSON.stringify({ domain }),\n }),\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: [\"org-me\"] });\n },\n });\n}\n\nexport function useSetA2ASecret() {\n const qc = useQueryClient();\n return useMutation<\n { a2aSecret: string; previousSecret: string | null },\n Error,\n string | undefined\n >({\n mutationFn: (secret?: string) =>\n apiFetch(`${ORG_BASE}/a2a-secret`, {\n method: \"PUT\",\n body: JSON.stringify({ secret }),\n }),\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: [\"org-me\"] });\n },\n });\n}\n\nexport interface SyncA2ASecretResult {\n total: number;\n succeeded: number;\n failed: number;\n results: Array<{\n id: string;\n name: string;\n url: string;\n ok: boolean;\n status?: number;\n error?: string;\n }>;\n}\n\n/**\n * Push the org's A2A secret to every connected app so cross-app delegation\n * works without manual copy/paste. Optionally pass a `signSecret` to sign\n * the outbound JWTs with a different secret (used by the regenerate-then-\n * sync flow where the new secret is in DB but peers still hold the old\n * one).\n */\nexport function useSyncA2ASecret() {\n return useMutation<\n SyncA2ASecretResult,\n Error,\n { signSecret?: string } | void\n >({\n mutationFn: (vars) =>\n apiFetch(`${ORG_BASE}/a2a-secret/sync`, {\n method: \"POST\",\n body: JSON.stringify({\n signSecret:\n vars && \"signSecret\" in vars ? vars.signSecret : undefined,\n }),\n }),\n });\n}\n"]}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/client/org/hooks.ts"],"names":[],"mappings":"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","sourcesContent":["import { useQuery, useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n OrgInfo,\n OrgMember,\n OrgPendingInvitation,\n} from \"../../org/types.js\";\nimport { agentNativePath } from \"../api-path.js\";\n\nconst ORG_BASE = agentNativePath(\"/_agent-native/org\");\n\nasync function apiFetch(path: string, init?: RequestInit) {\n const res = await fetch(path, {\n ...init,\n credentials: \"include\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...init?.headers,\n },\n });\n if (!res.ok) {\n // Prefer a JSON `error` / `message` field when the server returns one,\n // and only fall back to the raw body for plaintext responses. Avoids\n // surfacing `{\"error\":\"...\"}` as the user-visible message.\n const text = await res.text().catch(() => \"\");\n let message: string = res.statusText;\n if (text) {\n try {\n const parsed = JSON.parse(text) as {\n error?: string;\n message?: string;\n };\n message = parsed.error ?? parsed.message ?? text;\n } catch {\n message = text;\n }\n }\n throw new Error(message);\n }\n return res.json();\n}\n\nexport function useOrg() {\n return useQuery<OrgInfo>({\n queryKey: [\"org-me\"],\n queryFn: () => apiFetch(`${ORG_BASE}/me`),\n staleTime: 30_000,\n });\n}\n\nexport function useOrgMembers() {\n return useQuery<{ members: OrgMember[] }>({\n queryKey: [\"org-members\"],\n queryFn: () => apiFetch(`${ORG_BASE}/members`),\n staleTime: 30_000,\n });\n}\n\nexport function useOrgInvitations() {\n return useQuery<{ invitations: OrgPendingInvitation[] }>({\n queryKey: [\"org-invitations\"],\n queryFn: () => apiFetch(`${ORG_BASE}/invitations`),\n staleTime: 30_000,\n });\n}\n\n// NOTE: the onSuccess handlers below `await invalidateQueries`. In\n// TanStack Query v5, invalidateQueries:\n// 1. Marks every matching query as stale, so the next mount of an\n// INACTIVE query (e.g. the org-members table on a settings page\n// the user hasn't visited yet) refetches immediately instead of\n// serving 30-second-stale cached data.\n// 2. Triggers a refetch of every ACTIVE query that matches.\n// 3. Returns a promise that resolves once those refetches settle.\n//\n// `await`ing therefore keeps `mutation.isPending` true through the\n// full read-after-write window — closing the create-org / accept-\n// invite race where a button could re-enable mid-refetch. We\n// previously tried refetchQueries here for \"unambiguous semantics\",\n// but that variant doesn't mark inactive queries stale, leaving them\n// to serve stale data on next mount. invalidateQueries is the right\n// primitive — it just needed an `await`.\n\nexport function useCreateOrg() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (name: string) =>\n apiFetch(ORG_BASE, {\n method: \"POST\",\n body: JSON.stringify({ name }),\n }),\n onSuccess: async () => {\n await Promise.all([\n qc.invalidateQueries({ queryKey: [\"org-me\"] }),\n qc.invalidateQueries({ queryKey: [\"org-members\"] }),\n ]);\n },\n });\n}\n\nexport type InviteRole = \"admin\" | \"member\";\n\nexport interface InviteVars {\n email: string;\n role?: InviteRole;\n}\n\nexport function useInviteMember() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: string | InviteVars) => {\n const body: { email: string; role: InviteRole } =\n typeof vars === \"string\"\n ? { email: vars, role: \"member\" }\n : { email: vars.email, role: vars.role ?? \"member\" };\n return apiFetch(`${ORG_BASE}/invitations`, {\n method: \"POST\",\n body: JSON.stringify(body),\n });\n },\n onSuccess: async () => {\n await Promise.all([\n qc.invalidateQueries({ queryKey: [\"org-members\"] }),\n qc.invalidateQueries({ queryKey: [\"org-invitations\"] }),\n ]);\n },\n });\n}\n\nexport interface BulkInviteResult {\n succeeded: Array<{\n id: string;\n email: string;\n role: InviteRole;\n status: \"pending\";\n emailSent: boolean;\n emailError?: string;\n }>;\n failed: Array<{ email: string; error: string }>;\n total: number;\n}\n\nexport function useBulkInviteMembers() {\n const qc = useQueryClient();\n return useMutation<BulkInviteResult, Error, InviteVars[]>({\n mutationFn: (invites) =>\n apiFetch(`${ORG_BASE}/invitations`, {\n method: \"POST\",\n body: JSON.stringify({\n invites: invites.map((i) => ({\n email: i.email,\n role: i.role ?? \"member\",\n })),\n }),\n }),\n onSuccess: async () => {\n await Promise.all([\n qc.invalidateQueries({ queryKey: [\"org-members\"] }),\n qc.invalidateQueries({ queryKey: [\"org-invitations\"] }),\n ]);\n },\n });\n}\n\nexport function useChangeMemberRole() {\n const qc = useQueryClient();\n return useMutation<\n { email: string; role: InviteRole },\n Error,\n { email: string; role: InviteRole }\n >({\n mutationFn: ({ email, role }) =>\n apiFetch(`${ORG_BASE}/members/${encodeURIComponent(email)}/role`, {\n method: \"PUT\",\n body: JSON.stringify({ role }),\n }),\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: [\"org-members\"] });\n },\n });\n}\n\nexport function useAcceptInvitation() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (invitationId: string) =>\n apiFetch(`${ORG_BASE}/invitations/${invitationId}/accept`, {\n method: \"POST\",\n }),\n onSuccess: async () => {\n // Joining/switching orgs changes all org-scoped data — invalidate\n // every cached query (no key filter) so each one refetches or is\n // marked stale for the next mount.\n await qc.invalidateQueries();\n },\n });\n}\n\nexport function useRemoveMember() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (email: string) =>\n apiFetch(`${ORG_BASE}/members/${encodeURIComponent(email)}`, {\n method: \"DELETE\",\n }),\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: [\"org-members\"] });\n },\n });\n}\n\nexport function useUpdateOrg() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (name: string) =>\n apiFetch(ORG_BASE, {\n method: \"PATCH\",\n body: JSON.stringify({ name }),\n }),\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: [\"org-me\"] });\n },\n });\n}\n\nexport function useSwitchOrg() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (orgId: string | null) =>\n apiFetch(`${ORG_BASE}/switch`, {\n method: \"PUT\",\n body: JSON.stringify({ orgId }),\n }),\n onSuccess: async () => {\n // Switching org changes everything scoped to AGENT_ORG_ID.\n await qc.invalidateQueries();\n },\n });\n}\n\nexport function useJoinByDomain() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (orgId: string) =>\n apiFetch(`${ORG_BASE}/join-by-domain`, {\n method: \"POST\",\n body: JSON.stringify({ orgId }),\n }),\n onSuccess: async () => {\n await qc.invalidateQueries();\n },\n });\n}\n\nexport function useSetOrgDomain() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (domain: string | null) =>\n apiFetch(`${ORG_BASE}/domain`, {\n method: \"PUT\",\n body: JSON.stringify({ domain }),\n }),\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: [\"org-me\"] });\n },\n });\n}\n\nexport function useSetA2ASecret() {\n const qc = useQueryClient();\n return useMutation<\n { a2aSecret: string; previousSecret: string | null },\n Error,\n string | undefined\n >({\n mutationFn: (secret?: string) =>\n apiFetch(`${ORG_BASE}/a2a-secret`, {\n method: \"PUT\",\n body: JSON.stringify({ secret }),\n }),\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: [\"org-me\"] });\n },\n });\n}\n\nexport interface SyncA2ASecretResult {\n total: number;\n succeeded: number;\n failed: number;\n results: Array<{\n id: string;\n name: string;\n url: string;\n ok: boolean;\n status?: number;\n error?: string;\n }>;\n}\n\n/**\n * Push the org's A2A secret to every connected app so cross-app delegation\n * works without manual copy/paste. Optionally pass a `signSecret` to sign\n * the outbound JWTs with a different secret (used by the regenerate-then-\n * sync flow where the new secret is in DB but peers still hold the old\n * one).\n */\nexport function useSyncA2ASecret() {\n return useMutation<\n SyncA2ASecretResult,\n Error,\n { signSecret?: string } | void\n >({\n mutationFn: (vars) =>\n apiFetch(`${ORG_BASE}/a2a-secret/sync`, {\n method: \"POST\",\n body: JSON.stringify({\n signSecret:\n vars && \"signSecret\" in vars ? vars.signSecret : undefined,\n }),\n }),\n });\n}\n"]}
@@ -1,4 +1,5 @@
1
- export { useOrg, useOrgMembers, useOrgInvitations, useCreateOrg, useUpdateOrg, useInviteMember, useAcceptInvitation, useRemoveMember, useSwitchOrg, useJoinByDomain, useSetOrgDomain, } from "./hooks.js";
1
+ export { useOrg, useOrgMembers, useOrgInvitations, useCreateOrg, useUpdateOrg, useInviteMember, useBulkInviteMembers, useChangeMemberRole, useAcceptInvitation, useRemoveMember, useSwitchOrg, useJoinByDomain, useSetOrgDomain, } from "./hooks.js";
2
+ export type { InviteRole, InviteVars, BulkInviteResult } from "./hooks.js";
2
3
  export { OrgSwitcher, type OrgSwitcherProps } from "./OrgSwitcher.js";
3
4
  export { InvitationBanner, type InvitationBannerProps, } from "./InvitationBanner.js";
4
5
  export { TeamPage, type TeamPageProps } from "./TeamPage.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/org/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACV,OAAO,EACP,OAAO,EACP,SAAS,EACT,oBAAoB,EACpB,UAAU,EACV,oBAAoB,EACpB,cAAc,GACf,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/org/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE3E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACV,OAAO,EACP,OAAO,EACP,SAAS,EACT,oBAAoB,EACpB,UAAU,EACV,oBAAoB,EACpB,cAAc,GACf,MAAM,oBAAoB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  // Public client API for the org module.
2
- export { useOrg, useOrgMembers, useOrgInvitations, useCreateOrg, useUpdateOrg, useInviteMember, useAcceptInvitation, useRemoveMember, useSwitchOrg, useJoinByDomain, useSetOrgDomain, } from "./hooks.js";
2
+ export { useOrg, useOrgMembers, useOrgInvitations, useCreateOrg, useUpdateOrg, useInviteMember, useBulkInviteMembers, useChangeMemberRole, useAcceptInvitation, useRemoveMember, useSwitchOrg, useJoinByDomain, useSetOrgDomain, } from "./hooks.js";
3
3
  export { OrgSwitcher } from "./OrgSwitcher.js";
4
4
  export { InvitationBanner, } from "./InvitationBanner.js";
5
5
  export { TeamPage } from "./TeamPage.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/org/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AAExC,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAyB,MAAM,kBAAkB,CAAC;AACtE,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAsB,MAAM,eAAe,CAAC;AAC7D,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC","sourcesContent":["// Public client API for the org module.\n\nexport {\n useOrg,\n useOrgMembers,\n useOrgInvitations,\n useCreateOrg,\n useUpdateOrg,\n useInviteMember,\n useAcceptInvitation,\n useRemoveMember,\n useSwitchOrg,\n useJoinByDomain,\n useSetOrgDomain,\n} from \"./hooks.js\";\n\nexport { OrgSwitcher, type OrgSwitcherProps } from \"./OrgSwitcher.js\";\nexport {\n InvitationBanner,\n type InvitationBannerProps,\n} from \"./InvitationBanner.js\";\nexport { TeamPage, type TeamPageProps } from \"./TeamPage.js\";\nexport {\n RequireActiveOrg,\n type RequireActiveOrgProps,\n} from \"./RequireActiveOrg.js\";\n\n// Re-export the shared types so consumers can import them from one place.\nexport type {\n OrgRole,\n OrgInfo,\n OrgMember,\n OrgPendingInvitation,\n OrgSummary,\n OrgInvitationSummary,\n DomainMatchOrg,\n} from \"../../org/types.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/org/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AAExC,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,WAAW,EAAyB,MAAM,kBAAkB,CAAC;AACtE,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAsB,MAAM,eAAe,CAAC;AAC7D,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC","sourcesContent":["// Public client API for the org module.\n\nexport {\n useOrg,\n useOrgMembers,\n useOrgInvitations,\n useCreateOrg,\n useUpdateOrg,\n useInviteMember,\n useBulkInviteMembers,\n useChangeMemberRole,\n useAcceptInvitation,\n useRemoveMember,\n useSwitchOrg,\n useJoinByDomain,\n useSetOrgDomain,\n} from \"./hooks.js\";\n\nexport type { InviteRole, InviteVars, BulkInviteResult } from \"./hooks.js\";\n\nexport { OrgSwitcher, type OrgSwitcherProps } from \"./OrgSwitcher.js\";\nexport {\n InvitationBanner,\n type InvitationBannerProps,\n} from \"./InvitationBanner.js\";\nexport { TeamPage, type TeamPageProps } from \"./TeamPage.js\";\nexport {\n RequireActiveOrg,\n type RequireActiveOrgProps,\n} from \"./RequireActiveOrg.js\";\n\n// Re-export the shared types so consumers can import them from one place.\nexport type {\n OrgRole,\n OrgInfo,\n OrgMember,\n OrgPendingInvitation,\n OrgSummary,\n OrgInvitationSummary,\n DomainMatchOrg,\n} from \"../../org/types.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ResourceTree.d.ts","sourceRoot":"","sources":["../../../src/client/resources/ResourceTree.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAkB7D,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAe,MAAM,oBAAoB,CAAC;AAoE9E,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC3C,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC/B;AA8QD,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,MAAM,EACN,KAAe,EACf,YAAY,EACZ,SAAiB,EACjB,UAAiB,EACjB,QAAgB,EAChB,WAAW,GACZ,EAAE,iBAAiB,2CA2LnB"}
1
+ {"version":3,"file":"ResourceTree.d.ts","sourceRoot":"","sources":["../../../src/client/resources/ResourceTree.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAkB7D,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAe,MAAM,oBAAoB,CAAC;AAoE9E,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC3C,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC/B;AAkSD,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,MAAM,EACN,KAAe,EACf,YAAY,EACZ,SAAiB,EACjB,UAAiB,EACjB,QAAgB,EAChB,WAAW,GACZ,EAAE,iBAAiB,2CA2LnB"}
@@ -61,6 +61,7 @@ function TreeNodeRow({ node, depth, expanded, selectedId, deletingId, readOnly,
61
61
  const isExpanded = expanded.has(node.path);
62
62
  const isSelected = node.resource?.id === selectedId;
63
63
  const isDeleting = !!node.resource && node.resource.id === deletingId;
64
+ const [confirmingDelete, setConfirmingDelete] = useState(false);
64
65
  return (_jsxs("div", { children: [_jsxs("div", { className: cn("group/row flex items-center gap-1 rounded-md px-1.5 py-1 select-none", isDeleting ? "pointer-events-none opacity-40" : "cursor-pointer", isSelected
65
66
  ? "bg-accent text-foreground"
66
67
  : "text-muted-foreground hover:bg-accent/50 hover:text-foreground"), style: { paddingLeft: depth * 16 + 6 }, onClick: () => {
@@ -72,14 +73,21 @@ function TreeNodeRow({ node, depth, expanded, selectedId, deletingId, readOnly,
72
73
  else if (node.resource) {
73
74
  onSelect(node.resource);
74
75
  }
75
- }, children: [isFolder ? (isExpanded ? (_jsx(IconChevronDown, { className: "h-3 w-3 shrink-0" })) : (_jsx(IconChevronRight, { className: "h-3 w-3 shrink-0" }))) : (_jsx("span", { className: "w-3 shrink-0" })), isFolder ? (_jsx(IconFolder, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })) : (getFileIcon(node)), _jsx("span", { className: "min-w-0 truncate text-[12px] leading-none", children: node.name }), node.jobMeta && _jsx(JobStatusDot, { meta: node.jobMeta }), node.mcpServerMeta && _jsx(McpStatusDot, { server: node.mcpServerMeta }), !readOnly && (_jsx("div", { className: "ml-auto flex shrink-0 items-center gap-0.5 opacity-0 group-hover/row:opacity-100", children: _jsxs(TooltipProvider, { delayDuration: 200, children: [isFolder && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: (e) => {
76
+ }, onMouseLeave: () => setConfirmingDelete(false), children: [isFolder ? (isExpanded ? (_jsx(IconChevronDown, { className: "h-3 w-3 shrink-0" })) : (_jsx(IconChevronRight, { className: "h-3 w-3 shrink-0" }))) : (_jsx("span", { className: "w-3 shrink-0" })), isFolder ? (_jsx(IconFolder, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })) : (getFileIcon(node)), _jsx("span", { className: "min-w-0 truncate text-[12px] leading-none", children: node.name }), node.jobMeta && _jsx(JobStatusDot, { meta: node.jobMeta }), node.mcpServerMeta && _jsx(McpStatusDot, { server: node.mcpServerMeta }), !readOnly && (_jsx("div", { className: cn("ml-auto flex shrink-0 items-center gap-0.5 opacity-0 group-hover/row:opacity-100", confirmingDelete && "opacity-100"), children: _jsxs(TooltipProvider, { delayDuration: 200, children: [isFolder && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: (e) => {
76
77
  e.stopPropagation();
77
78
  onStartCreate(node.path, "file");
78
79
  }, "aria-label": "New file", className: "flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconPlus, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: "New file" })] })), node.resource &&
79
80
  (isDeleting ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { "aria-label": "Deleting\u2026", className: "flex h-5 w-5 items-center justify-center rounded text-muted-foreground", children: _jsx(IconLoader2, { className: "h-3 w-3 animate-spin" }) }) }), _jsx(TooltipContent, { children: "Deleting\u2026" })] })) : (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: (e) => {
80
81
  e.stopPropagation();
81
- onDelete(node.resource.id);
82
- }, "aria-label": "Delete", className: "flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-destructive hover:bg-accent/50", children: _jsx(IconTrash, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: "Delete" })] })))] }) }))] }), isFolder && isExpanded && node.children && (_jsx("div", { children: node.children.map((child) => (_jsx(TreeNodeRow, { node: child, depth: depth + 1, expanded: expanded, selectedId: selectedId, deletingId: deletingId, readOnly: readOnly, onToggle: onToggle, onSelect: onSelect, onDelete: onDelete, onStartCreate: onStartCreate }, child.resource?.id ?? child.path))) }))] }));
82
+ if (confirmingDelete) {
83
+ onDelete(node.resource.id);
84
+ setConfirmingDelete(false);
85
+ }
86
+ else {
87
+ setConfirmingDelete(true);
88
+ }
89
+ }, "aria-label": confirmingDelete ? "Confirm delete" : "Delete", className: cn("flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-destructive hover:bg-accent/50", confirmingDelete &&
90
+ "bg-destructive/10 text-destructive"), children: _jsx(IconTrash, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: confirmingDelete ? "Click again to delete" : "Delete" })] })))] }) }))] }), isFolder && isExpanded && node.children && (_jsx("div", { children: node.children.map((child) => (_jsx(TreeNodeRow, { node: child, depth: depth + 1, expanded: expanded, selectedId: selectedId, deletingId: deletingId, readOnly: readOnly, onToggle: onToggle, onSelect: onSelect, onDelete: onDelete, onStartCreate: onStartCreate }, child.resource?.id ?? child.path))) }))] }));
83
91
  }
84
92
  // ─── InlineInput ────────────────────────────────────────────────────────────
85
93
  function InlineInput({ depth, onConfirm, onCancel, }) {
@@ -1 +1 @@
1
- {"version":3,"file":"ResourceTree.js","sourceRoot":"","sources":["../../../src/client/resources/ResourceTree.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useRef, useCallback } from \"react\";\nimport {\n IconChevronRight,\n IconChevronDown,\n IconFolder,\n IconFileText,\n IconFileCode,\n IconPhoto,\n IconFile,\n IconPlus,\n IconTrash,\n IconMessageChatbot,\n IconPlugConnected,\n IconBulb,\n IconClockHour3,\n IconLoader2,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport type { TreeNode, ResourceMeta, JobMetadata } from \"./use-resources.js\";\nimport type { McpServer } from \"./use-mcp-servers.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\n\nfunction StatusDot({\n className,\n tooltip,\n}: {\n className: string;\n tooltip: string;\n}) {\n return (\n <TooltipProvider delayDuration={200}>\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n aria-label={tooltip}\n className={cn(\"ml-1 inline-block h-1.5 w-1.5 shrink-0\", className)}\n />\n </TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction getFileIcon(node: TreeNode): React.ReactNode {\n if (node.kind === \"agent\") {\n return (\n <IconMessageChatbot className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n );\n }\n if (node.kind === \"remote-agent\" || node.kind === \"mcp-server\") {\n return (\n <IconPlugConnected className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n );\n }\n if (node.kind === \"skill\") {\n return <IconBulb className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />;\n }\n if (node.kind === \"job\") {\n return (\n <IconClockHour3 className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n );\n }\n const name = node.name;\n const ext = name.split(\".\").pop()?.toLowerCase() ?? \"\";\n const iconClass = \"h-3.5 w-3.5 shrink-0 text-muted-foreground\";\n if (ext === \"md\" || ext === \"mdx\")\n return <IconFileText className={iconClass} />;\n if (\n [\"ts\", \"tsx\", \"js\", \"jsx\", \"json\", \"css\", \"html\", \"py\", \"sh\"].includes(ext)\n )\n return <IconFileCode className={iconClass} />;\n if ([\"png\", \"jpg\", \"jpeg\", \"gif\", \"svg\", \"webp\", \"ico\"].includes(ext))\n return <IconPhoto className={iconClass} />;\n return <IconFile className={iconClass} />;\n}\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport interface ResourceTreeProps {\n tree: TreeNode[];\n selectedId: string | null;\n onSelect: (resource: ResourceMeta) => void;\n onCreateFile: (parentPath: string, name: string) => void;\n onCreateFolder: (parentPath: string, name: string) => void;\n onDelete: (id: string) => void;\n onRename: (id: string, newPath: string) => void;\n onDrop: (files: FileList) => void;\n /** Section title displayed as heading */\n title?: string;\n /** Tooltip for the section heading */\n titleTooltip?: string;\n /** Whether this section's tree is still loading */\n isLoading?: boolean;\n /** Resource id currently being deleted (shows spinner + muted row) */\n deletingId?: string | null;\n /** When true, hide create/delete/rename/upload affordances. Files stay readable. */\n readOnly?: boolean;\n /** Optional hint shown next to the heading (e.g. \"Read only\") */\n headingHint?: React.ReactNode;\n}\n\ninterface CreatingState {\n parentPath: string;\n type: \"file\" | \"folder\";\n}\n\nfunction McpStatusDot({ server }: { server: McpServer }) {\n if (server.status.state === \"connected\") {\n return (\n <StatusDot\n className=\"rounded-full bg-green-500\"\n tooltip={`Connected — ${server.status.toolCount} tool${server.status.toolCount === 1 ? \"\" : \"s\"}`}\n />\n );\n }\n if (server.status.state === \"error\") {\n return (\n <StatusDot\n className=\"rounded-full bg-red-500\"\n tooltip={`Error: ${server.status.error}`}\n />\n );\n }\n return (\n <StatusDot\n className=\"rounded-full bg-muted-foreground/40\"\n tooltip=\"Connecting…\"\n />\n );\n}\n\nfunction JobStatusDot({ meta }: { meta: JobMetadata }) {\n if (!meta.enabled) {\n return (\n <StatusDot\n className=\"rounded-full bg-muted-foreground/40\"\n tooltip=\"Disabled\"\n />\n );\n }\n if (meta.lastStatus === \"running\") {\n return (\n <StatusDot\n className=\"rounded-full bg-blue-500 animate-pulse\"\n tooltip=\"Running\"\n />\n );\n }\n if (meta.lastStatus === \"error\") {\n return (\n <StatusDot\n className=\"rounded-full bg-red-500\"\n tooltip=\"Last run failed\"\n />\n );\n }\n if (meta.lastStatus === \"success\") {\n return (\n <StatusDot\n className=\"rounded-full bg-green-500\"\n tooltip=\"Last run succeeded\"\n />\n );\n }\n return (\n <StatusDot\n className=\"rounded-full bg-amber-500\"\n tooltip=\"Scheduled (not yet run)\"\n />\n );\n}\n\n// ─── TreeNodeRow ────────────────────────────────────────────────────────────\n\nfunction TreeNodeRow({\n node,\n depth,\n expanded,\n selectedId,\n deletingId,\n readOnly,\n onToggle,\n onSelect,\n onDelete,\n onStartCreate,\n}: {\n node: TreeNode;\n depth: number;\n expanded: Set<string>;\n selectedId: string | null;\n deletingId?: string | null;\n readOnly?: boolean;\n onToggle: (path: string) => void;\n onSelect: (resource: ResourceMeta) => void;\n onDelete: (id: string) => void;\n onStartCreate: (parentPath: string, type: \"file\" | \"folder\") => void;\n}) {\n const isFolder = node.type === \"folder\";\n const isExpanded = expanded.has(node.path);\n const isSelected = node.resource?.id === selectedId;\n const isDeleting = !!node.resource && node.resource.id === deletingId;\n\n return (\n <div>\n <div\n className={cn(\n \"group/row flex items-center gap-1 rounded-md px-1.5 py-1 select-none\",\n isDeleting ? \"pointer-events-none opacity-40\" : \"cursor-pointer\",\n isSelected\n ? \"bg-accent text-foreground\"\n : \"text-muted-foreground hover:bg-accent/50 hover:text-foreground\",\n )}\n style={{ paddingLeft: depth * 16 + 6 }}\n onClick={() => {\n if (isDeleting) return;\n if (isFolder) {\n onToggle(node.path);\n } else if (node.resource) {\n onSelect(node.resource);\n }\n }}\n >\n {isFolder ? (\n isExpanded ? (\n <IconChevronDown className=\"h-3 w-3 shrink-0\" />\n ) : (\n <IconChevronRight className=\"h-3 w-3 shrink-0\" />\n )\n ) : (\n <span className=\"w-3 shrink-0\" />\n )}\n {isFolder ? (\n <IconFolder className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n ) : (\n getFileIcon(node)\n )}\n <span className=\"min-w-0 truncate text-[12px] leading-none\">\n {node.name}\n </span>\n {node.jobMeta && <JobStatusDot meta={node.jobMeta} />}\n {node.mcpServerMeta && <McpStatusDot server={node.mcpServerMeta} />}\n {!readOnly && (\n <div className=\"ml-auto flex shrink-0 items-center gap-0.5 opacity-0 group-hover/row:opacity-100\">\n <TooltipProvider delayDuration={200}>\n {isFolder && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onStartCreate(node.path, \"file\");\n }}\n aria-label=\"New file\"\n className=\"flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n >\n <IconPlus className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>New file</TooltipContent>\n </Tooltip>\n )}\n {node.resource &&\n (isDeleting ? (\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n aria-label=\"Deleting…\"\n className=\"flex h-5 w-5 items-center justify-center rounded text-muted-foreground\"\n >\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n </span>\n </TooltipTrigger>\n <TooltipContent>Deleting…</TooltipContent>\n </Tooltip>\n ) : (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDelete(node.resource!.id);\n }}\n aria-label=\"Delete\"\n className=\"flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-destructive hover:bg-accent/50\"\n >\n <IconTrash className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Delete</TooltipContent>\n </Tooltip>\n ))}\n </TooltipProvider>\n </div>\n )}\n </div>\n {isFolder && isExpanded && node.children && (\n <div>\n {node.children.map((child) => (\n <TreeNodeRow\n key={child.resource?.id ?? child.path}\n node={child}\n depth={depth + 1}\n expanded={expanded}\n selectedId={selectedId}\n deletingId={deletingId}\n readOnly={readOnly}\n onToggle={onToggle}\n onSelect={onSelect}\n onDelete={onDelete}\n onStartCreate={onStartCreate}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ─── InlineInput ────────────────────────────────────────────────────────────\n\nfunction InlineInput({\n depth,\n onConfirm,\n onCancel,\n}: {\n depth: number;\n onConfirm: (name: string) => void;\n onCancel: () => void;\n}) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [value, setValue] = useState(\"\");\n\n React.useEffect(() => {\n inputRef.current?.focus();\n }, []);\n\n return (\n <div\n className=\"flex items-center gap-1 px-1.5 py-0.5\"\n style={{ paddingLeft: depth * 16 + 6 + 16 }}\n >\n <IconFile className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <input\n ref={inputRef}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && value.trim()) {\n onConfirm(value.trim());\n } else if (e.key === \"Escape\") {\n onCancel();\n }\n }}\n onBlur={() => {\n if (value.trim()) {\n onConfirm(value.trim());\n } else {\n onCancel();\n }\n }}\n className=\"min-w-0 flex-1 bg-transparent text-[12px] leading-none text-foreground outline-none placeholder:text-muted-foreground/50\"\n placeholder=\"filename.md\"\n />\n </div>\n );\n}\n\n// ─── ResourceTree ───────────────────────────────────────────────────────────\n\nexport function ResourceTree({\n tree,\n selectedId,\n onSelect,\n onCreateFile,\n onCreateFolder,\n onDelete,\n onDrop,\n title = \"Files\",\n titleTooltip,\n isLoading = false,\n deletingId = null,\n readOnly = false,\n headingHint,\n}: ResourceTreeProps) {\n const [expanded, setExpanded] = useState<Set<string>>(() => new Set());\n const [creating, setCreating] = useState<CreatingState | null>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const toggleExpand = useCallback((path: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(path)) {\n next.delete(path);\n } else {\n next.add(path);\n }\n return next;\n });\n }, []);\n\n const handleStartCreate = useCallback(\n (parentPath: string, type: \"file\" | \"folder\") => {\n setCreating({ parentPath, type });\n // auto-expand the parent folder\n setExpanded((prev) => {\n const next = new Set(prev);\n next.add(parentPath);\n return next;\n });\n },\n [],\n );\n\n const handleConfirmCreate = useCallback(\n (name: string) => {\n if (!creating) return;\n if (creating.type === \"file\") {\n onCreateFile(creating.parentPath, name);\n } else {\n onCreateFolder(creating.parentPath, name);\n }\n setCreating(null);\n },\n [creating, onCreateFile, onCreateFolder],\n );\n\n const handleCancelCreate = useCallback(() => {\n setCreating(null);\n }, []);\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setDragOver(true);\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setDragOver(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setDragOver(false);\n if (readOnly) return;\n if (e.dataTransfer.files.length > 0) {\n onDrop(e.dataTransfer.files);\n }\n },\n [onDrop, readOnly],\n );\n\n return (\n <div\n className={cn(\n \"p-1\",\n dragOver && !readOnly && \"ring-1 ring-inset ring-accent\",\n )}\n onDragOver={readOnly ? undefined : handleDragOver}\n onDragLeave={readOnly ? undefined : handleDragLeave}\n onDrop={readOnly ? undefined : handleDrop}\n >\n {/* Section heading */}\n <div className=\"group/root flex items-center justify-between px-1.5 py-1\">\n <TooltipProvider delayDuration={200}>\n {titleTooltip ? (\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"flex items-center gap-1.5 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/60\">\n {title}\n {headingHint && (\n <span className=\"text-[10px] font-normal normal-case tracking-normal text-muted-foreground/50\">\n {headingHint}\n </span>\n )}\n </span>\n </TooltipTrigger>\n <TooltipContent>{titleTooltip}</TooltipContent>\n </Tooltip>\n ) : (\n <span className=\"flex items-center gap-1.5 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/60\">\n {title}\n {headingHint && (\n <span className=\"text-[10px] font-normal normal-case tracking-normal text-muted-foreground/50\">\n {headingHint}\n </span>\n )}\n </span>\n )}\n {!readOnly && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={() => handleStartCreate(\"\", \"file\")}\n aria-label=\"New file\"\n className=\"flex h-5 w-5 items-center justify-center rounded text-muted-foreground/50 opacity-0 group-hover/root:opacity-100 hover:text-foreground hover:bg-accent/50\"\n >\n <IconPlus className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>New file</TooltipContent>\n </Tooltip>\n )}\n </TooltipProvider>\n </div>\n\n {tree.map((node) => (\n <TreeNodeRow\n key={node.resource?.id ?? node.path}\n node={node}\n depth={0}\n expanded={expanded}\n selectedId={selectedId}\n deletingId={deletingId}\n readOnly={readOnly}\n onToggle={toggleExpand}\n onSelect={onSelect}\n onDelete={onDelete}\n onStartCreate={handleStartCreate}\n />\n ))}\n\n {isLoading && tree.length === 0 && (\n <div className=\"px-1 py-1\">\n {Array.from({ length: 3 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-2 px-1.5 py-1\">\n <div\n className=\"h-3.5 w-3.5 rounded bg-muted-foreground/10 animate-pulse\"\n style={{ animationDelay: `${i * 75}ms` }}\n />\n <div\n className=\"h-3 rounded bg-muted-foreground/10 animate-pulse\"\n style={{\n width: `${50 + ((i * 37) % 40)}%`,\n animationDelay: `${i * 75}ms`,\n }}\n />\n </div>\n ))}\n </div>\n )}\n\n {/* Inline input for root-level creation */}\n {creating && creating.parentPath === \"\" && (\n <InlineInput\n depth={0}\n onConfirm={handleConfirmCreate}\n onCancel={handleCancelCreate}\n />\n )}\n\n {/* Inline input for folder-level creation */}\n {creating && creating.parentPath !== \"\" && (\n <InlineInput\n depth={creating.parentPath.split(\"/\").filter(Boolean).length}\n onConfirm={handleConfirmCreate}\n onCancel={handleCancelCreate}\n />\n )}\n\n {tree.length === 0 && !creating && !isLoading && (\n <div className=\"px-2 py-1\">\n <p className=\"text-[11px] text-muted-foreground/40\">No files yet</p>\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"ResourceTree.js","sourceRoot":"","sources":["../../../src/client/resources/ResourceTree.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useRef, useCallback } from \"react\";\nimport {\n IconChevronRight,\n IconChevronDown,\n IconFolder,\n IconFileText,\n IconFileCode,\n IconPhoto,\n IconFile,\n IconPlus,\n IconTrash,\n IconMessageChatbot,\n IconPlugConnected,\n IconBulb,\n IconClockHour3,\n IconLoader2,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport type { TreeNode, ResourceMeta, JobMetadata } from \"./use-resources.js\";\nimport type { McpServer } from \"./use-mcp-servers.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\n\nfunction StatusDot({\n className,\n tooltip,\n}: {\n className: string;\n tooltip: string;\n}) {\n return (\n <TooltipProvider delayDuration={200}>\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n aria-label={tooltip}\n className={cn(\"ml-1 inline-block h-1.5 w-1.5 shrink-0\", className)}\n />\n </TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction getFileIcon(node: TreeNode): React.ReactNode {\n if (node.kind === \"agent\") {\n return (\n <IconMessageChatbot className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n );\n }\n if (node.kind === \"remote-agent\" || node.kind === \"mcp-server\") {\n return (\n <IconPlugConnected className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n );\n }\n if (node.kind === \"skill\") {\n return <IconBulb className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />;\n }\n if (node.kind === \"job\") {\n return (\n <IconClockHour3 className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n );\n }\n const name = node.name;\n const ext = name.split(\".\").pop()?.toLowerCase() ?? \"\";\n const iconClass = \"h-3.5 w-3.5 shrink-0 text-muted-foreground\";\n if (ext === \"md\" || ext === \"mdx\")\n return <IconFileText className={iconClass} />;\n if (\n [\"ts\", \"tsx\", \"js\", \"jsx\", \"json\", \"css\", \"html\", \"py\", \"sh\"].includes(ext)\n )\n return <IconFileCode className={iconClass} />;\n if ([\"png\", \"jpg\", \"jpeg\", \"gif\", \"svg\", \"webp\", \"ico\"].includes(ext))\n return <IconPhoto className={iconClass} />;\n return <IconFile className={iconClass} />;\n}\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport interface ResourceTreeProps {\n tree: TreeNode[];\n selectedId: string | null;\n onSelect: (resource: ResourceMeta) => void;\n onCreateFile: (parentPath: string, name: string) => void;\n onCreateFolder: (parentPath: string, name: string) => void;\n onDelete: (id: string) => void;\n onRename: (id: string, newPath: string) => void;\n onDrop: (files: FileList) => void;\n /** Section title displayed as heading */\n title?: string;\n /** Tooltip for the section heading */\n titleTooltip?: string;\n /** Whether this section's tree is still loading */\n isLoading?: boolean;\n /** Resource id currently being deleted (shows spinner + muted row) */\n deletingId?: string | null;\n /** When true, hide create/delete/rename/upload affordances. Files stay readable. */\n readOnly?: boolean;\n /** Optional hint shown next to the heading (e.g. \"Read only\") */\n headingHint?: React.ReactNode;\n}\n\ninterface CreatingState {\n parentPath: string;\n type: \"file\" | \"folder\";\n}\n\nfunction McpStatusDot({ server }: { server: McpServer }) {\n if (server.status.state === \"connected\") {\n return (\n <StatusDot\n className=\"rounded-full bg-green-500\"\n tooltip={`Connected — ${server.status.toolCount} tool${server.status.toolCount === 1 ? \"\" : \"s\"}`}\n />\n );\n }\n if (server.status.state === \"error\") {\n return (\n <StatusDot\n className=\"rounded-full bg-red-500\"\n tooltip={`Error: ${server.status.error}`}\n />\n );\n }\n return (\n <StatusDot\n className=\"rounded-full bg-muted-foreground/40\"\n tooltip=\"Connecting…\"\n />\n );\n}\n\nfunction JobStatusDot({ meta }: { meta: JobMetadata }) {\n if (!meta.enabled) {\n return (\n <StatusDot\n className=\"rounded-full bg-muted-foreground/40\"\n tooltip=\"Disabled\"\n />\n );\n }\n if (meta.lastStatus === \"running\") {\n return (\n <StatusDot\n className=\"rounded-full bg-blue-500 animate-pulse\"\n tooltip=\"Running\"\n />\n );\n }\n if (meta.lastStatus === \"error\") {\n return (\n <StatusDot\n className=\"rounded-full bg-red-500\"\n tooltip=\"Last run failed\"\n />\n );\n }\n if (meta.lastStatus === \"success\") {\n return (\n <StatusDot\n className=\"rounded-full bg-green-500\"\n tooltip=\"Last run succeeded\"\n />\n );\n }\n return (\n <StatusDot\n className=\"rounded-full bg-amber-500\"\n tooltip=\"Scheduled (not yet run)\"\n />\n );\n}\n\n// ─── TreeNodeRow ────────────────────────────────────────────────────────────\n\nfunction TreeNodeRow({\n node,\n depth,\n expanded,\n selectedId,\n deletingId,\n readOnly,\n onToggle,\n onSelect,\n onDelete,\n onStartCreate,\n}: {\n node: TreeNode;\n depth: number;\n expanded: Set<string>;\n selectedId: string | null;\n deletingId?: string | null;\n readOnly?: boolean;\n onToggle: (path: string) => void;\n onSelect: (resource: ResourceMeta) => void;\n onDelete: (id: string) => void;\n onStartCreate: (parentPath: string, type: \"file\" | \"folder\") => void;\n}) {\n const isFolder = node.type === \"folder\";\n const isExpanded = expanded.has(node.path);\n const isSelected = node.resource?.id === selectedId;\n const isDeleting = !!node.resource && node.resource.id === deletingId;\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n\n return (\n <div>\n <div\n className={cn(\n \"group/row flex items-center gap-1 rounded-md px-1.5 py-1 select-none\",\n isDeleting ? \"pointer-events-none opacity-40\" : \"cursor-pointer\",\n isSelected\n ? \"bg-accent text-foreground\"\n : \"text-muted-foreground hover:bg-accent/50 hover:text-foreground\",\n )}\n style={{ paddingLeft: depth * 16 + 6 }}\n onClick={() => {\n if (isDeleting) return;\n if (isFolder) {\n onToggle(node.path);\n } else if (node.resource) {\n onSelect(node.resource);\n }\n }}\n onMouseLeave={() => setConfirmingDelete(false)}\n >\n {isFolder ? (\n isExpanded ? (\n <IconChevronDown className=\"h-3 w-3 shrink-0\" />\n ) : (\n <IconChevronRight className=\"h-3 w-3 shrink-0\" />\n )\n ) : (\n <span className=\"w-3 shrink-0\" />\n )}\n {isFolder ? (\n <IconFolder className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n ) : (\n getFileIcon(node)\n )}\n <span className=\"min-w-0 truncate text-[12px] leading-none\">\n {node.name}\n </span>\n {node.jobMeta && <JobStatusDot meta={node.jobMeta} />}\n {node.mcpServerMeta && <McpStatusDot server={node.mcpServerMeta} />}\n {!readOnly && (\n <div\n className={cn(\n \"ml-auto flex shrink-0 items-center gap-0.5 opacity-0 group-hover/row:opacity-100\",\n confirmingDelete && \"opacity-100\",\n )}\n >\n <TooltipProvider delayDuration={200}>\n {isFolder && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onStartCreate(node.path, \"file\");\n }}\n aria-label=\"New file\"\n className=\"flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n >\n <IconPlus className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>New file</TooltipContent>\n </Tooltip>\n )}\n {node.resource &&\n (isDeleting ? (\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n aria-label=\"Deleting…\"\n className=\"flex h-5 w-5 items-center justify-center rounded text-muted-foreground\"\n >\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n </span>\n </TooltipTrigger>\n <TooltipContent>Deleting…</TooltipContent>\n </Tooltip>\n ) : (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={(e) => {\n e.stopPropagation();\n if (confirmingDelete) {\n onDelete(node.resource!.id);\n setConfirmingDelete(false);\n } else {\n setConfirmingDelete(true);\n }\n }}\n aria-label={\n confirmingDelete ? \"Confirm delete\" : \"Delete\"\n }\n className={cn(\n \"flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-destructive hover:bg-accent/50\",\n confirmingDelete &&\n \"bg-destructive/10 text-destructive\",\n )}\n >\n <IconTrash className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>\n {confirmingDelete ? \"Click again to delete\" : \"Delete\"}\n </TooltipContent>\n </Tooltip>\n ))}\n </TooltipProvider>\n </div>\n )}\n </div>\n {isFolder && isExpanded && node.children && (\n <div>\n {node.children.map((child) => (\n <TreeNodeRow\n key={child.resource?.id ?? child.path}\n node={child}\n depth={depth + 1}\n expanded={expanded}\n selectedId={selectedId}\n deletingId={deletingId}\n readOnly={readOnly}\n onToggle={onToggle}\n onSelect={onSelect}\n onDelete={onDelete}\n onStartCreate={onStartCreate}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ─── InlineInput ────────────────────────────────────────────────────────────\n\nfunction InlineInput({\n depth,\n onConfirm,\n onCancel,\n}: {\n depth: number;\n onConfirm: (name: string) => void;\n onCancel: () => void;\n}) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [value, setValue] = useState(\"\");\n\n React.useEffect(() => {\n inputRef.current?.focus();\n }, []);\n\n return (\n <div\n className=\"flex items-center gap-1 px-1.5 py-0.5\"\n style={{ paddingLeft: depth * 16 + 6 + 16 }}\n >\n <IconFile className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <input\n ref={inputRef}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && value.trim()) {\n onConfirm(value.trim());\n } else if (e.key === \"Escape\") {\n onCancel();\n }\n }}\n onBlur={() => {\n if (value.trim()) {\n onConfirm(value.trim());\n } else {\n onCancel();\n }\n }}\n className=\"min-w-0 flex-1 bg-transparent text-[12px] leading-none text-foreground outline-none placeholder:text-muted-foreground/50\"\n placeholder=\"filename.md\"\n />\n </div>\n );\n}\n\n// ─── ResourceTree ───────────────────────────────────────────────────────────\n\nexport function ResourceTree({\n tree,\n selectedId,\n onSelect,\n onCreateFile,\n onCreateFolder,\n onDelete,\n onDrop,\n title = \"Files\",\n titleTooltip,\n isLoading = false,\n deletingId = null,\n readOnly = false,\n headingHint,\n}: ResourceTreeProps) {\n const [expanded, setExpanded] = useState<Set<string>>(() => new Set());\n const [creating, setCreating] = useState<CreatingState | null>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const toggleExpand = useCallback((path: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(path)) {\n next.delete(path);\n } else {\n next.add(path);\n }\n return next;\n });\n }, []);\n\n const handleStartCreate = useCallback(\n (parentPath: string, type: \"file\" | \"folder\") => {\n setCreating({ parentPath, type });\n // auto-expand the parent folder\n setExpanded((prev) => {\n const next = new Set(prev);\n next.add(parentPath);\n return next;\n });\n },\n [],\n );\n\n const handleConfirmCreate = useCallback(\n (name: string) => {\n if (!creating) return;\n if (creating.type === \"file\") {\n onCreateFile(creating.parentPath, name);\n } else {\n onCreateFolder(creating.parentPath, name);\n }\n setCreating(null);\n },\n [creating, onCreateFile, onCreateFolder],\n );\n\n const handleCancelCreate = useCallback(() => {\n setCreating(null);\n }, []);\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setDragOver(true);\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setDragOver(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setDragOver(false);\n if (readOnly) return;\n if (e.dataTransfer.files.length > 0) {\n onDrop(e.dataTransfer.files);\n }\n },\n [onDrop, readOnly],\n );\n\n return (\n <div\n className={cn(\n \"p-1\",\n dragOver && !readOnly && \"ring-1 ring-inset ring-accent\",\n )}\n onDragOver={readOnly ? undefined : handleDragOver}\n onDragLeave={readOnly ? undefined : handleDragLeave}\n onDrop={readOnly ? undefined : handleDrop}\n >\n {/* Section heading */}\n <div className=\"group/root flex items-center justify-between px-1.5 py-1\">\n <TooltipProvider delayDuration={200}>\n {titleTooltip ? (\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"flex items-center gap-1.5 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/60\">\n {title}\n {headingHint && (\n <span className=\"text-[10px] font-normal normal-case tracking-normal text-muted-foreground/50\">\n {headingHint}\n </span>\n )}\n </span>\n </TooltipTrigger>\n <TooltipContent>{titleTooltip}</TooltipContent>\n </Tooltip>\n ) : (\n <span className=\"flex items-center gap-1.5 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/60\">\n {title}\n {headingHint && (\n <span className=\"text-[10px] font-normal normal-case tracking-normal text-muted-foreground/50\">\n {headingHint}\n </span>\n )}\n </span>\n )}\n {!readOnly && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={() => handleStartCreate(\"\", \"file\")}\n aria-label=\"New file\"\n className=\"flex h-5 w-5 items-center justify-center rounded text-muted-foreground/50 opacity-0 group-hover/root:opacity-100 hover:text-foreground hover:bg-accent/50\"\n >\n <IconPlus className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>New file</TooltipContent>\n </Tooltip>\n )}\n </TooltipProvider>\n </div>\n\n {tree.map((node) => (\n <TreeNodeRow\n key={node.resource?.id ?? node.path}\n node={node}\n depth={0}\n expanded={expanded}\n selectedId={selectedId}\n deletingId={deletingId}\n readOnly={readOnly}\n onToggle={toggleExpand}\n onSelect={onSelect}\n onDelete={onDelete}\n onStartCreate={handleStartCreate}\n />\n ))}\n\n {isLoading && tree.length === 0 && (\n <div className=\"px-1 py-1\">\n {Array.from({ length: 3 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-2 px-1.5 py-1\">\n <div\n className=\"h-3.5 w-3.5 rounded bg-muted-foreground/10 animate-pulse\"\n style={{ animationDelay: `${i * 75}ms` }}\n />\n <div\n className=\"h-3 rounded bg-muted-foreground/10 animate-pulse\"\n style={{\n width: `${50 + ((i * 37) % 40)}%`,\n animationDelay: `${i * 75}ms`,\n }}\n />\n </div>\n ))}\n </div>\n )}\n\n {/* Inline input for root-level creation */}\n {creating && creating.parentPath === \"\" && (\n <InlineInput\n depth={0}\n onConfirm={handleConfirmCreate}\n onCancel={handleCancelCreate}\n />\n )}\n\n {/* Inline input for folder-level creation */}\n {creating && creating.parentPath !== \"\" && (\n <InlineInput\n depth={creating.parentPath.split(\"/\").filter(Boolean).length}\n onConfirm={handleConfirmCreate}\n onCancel={handleCancelCreate}\n />\n )}\n\n {tree.length === 0 && !creating && !isLoading && (\n <div className=\"px-2 py-1\">\n <p className=\"text-[11px] text-muted-foreground/40\">No files yet</p>\n </div>\n )}\n </div>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ResourcesPanel.d.ts","sourceRoot":"","sources":["../../../src/client/resources/ResourcesPanel.tsx"],"names":[],"mappings":"AAk+BA,wBAAgB,cAAc,4CA4hB7B"}
1
+ {"version":3,"file":"ResourcesPanel.d.ts","sourceRoot":"","sources":["../../../src/client/resources/ResourcesPanel.tsx"],"names":[],"mappings":"AAk+BA,wBAAgB,cAAc,4CAqjB7B"}
@@ -140,7 +140,7 @@ Follow the create-skill pattern to build this. Before writing:
140
140
 
141
141
  1. **Determine the skill name** — derive a hyphen-case name from the description (e.g. "code review" → "code-review")
142
142
  2. **Determine the skill type** — Pattern (architectural rule), Workflow (step-by-step), or Generator (scaffolding)
143
- 3. **Write the skill** as a ${scope} resource at path "skills/<name>.md" using resource-write
143
+ 3. **Write the skill** as a ${scope} resource at path "skills/<name>/SKILL.md" using resource-write
144
144
 
145
145
  The skill file MUST have YAML frontmatter with name and description (under 40 words), then markdown with:
146
146
  - Clear rule/purpose statement
@@ -481,11 +481,11 @@ This file customizes how the AI agent behaves in this app. Edit it to add your o
481
481
 
482
482
  ## Skills
483
483
 
484
- Create skill files under \`skills/\` to give the agent specialized knowledge. Reference them here:
484
+ Create skill files under \`skills/<name>/SKILL.md\` to give the agent specialized knowledge. Reference them here:
485
485
 
486
486
  | Skill | Path | Description |
487
487
  |-------|------|-------------|
488
- | *(use the skill button to create one)* | | |
488
+ | *(use the skill button to create one)* | \`skills/example/SKILL.md\` | |
489
489
  `;
490
490
  // BuilderBrowserCard moved to settings/BrowserSection.tsx
491
491
  export function ResourcesPanel() {
@@ -495,6 +495,7 @@ export function ResourcesPanel() {
495
495
  const canEditOrg = !org?.orgId || org.role === "owner" || org.role === "admin";
496
496
  const [activeScope, setActiveScope] = useState(canEditOrg ? "shared" : "personal");
497
497
  const [selectedResourceId, setSelectedResourceId] = useState(null);
498
+ const [toolbarDeleteConfirmId, setToolbarDeleteConfirmId] = useState(null);
498
499
  const [dragOver, setDragOver] = useState(false);
499
500
  const [editorView, setEditorView] = useState(() => {
500
501
  try {
@@ -505,6 +506,9 @@ export function ResourcesPanel() {
505
506
  catch { }
506
507
  return "visual";
507
508
  });
509
+ useEffect(() => {
510
+ setToolbarDeleteConfirmId(null);
511
+ }, [selectedResourceId]);
508
512
  const [saveStatus, setSaveStatus] = useState("idle");
509
513
  const fileInputRef = useRef(null);
510
514
  const sharedTreeQuery = useResourceTree("shared");
@@ -674,9 +678,21 @@ export function ResourcesPanel() {
674
678
  : saveStatus === "saved"
675
679
  ? "Saved"
676
680
  : "" }), _jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: () => {
677
- if (selectedResourceId)
681
+ if (!selectedResourceId)
682
+ return;
683
+ if (toolbarDeleteConfirmId === selectedResourceId) {
678
684
  handleDelete(selectedResourceId);
679
- }, "aria-label": "Delete resource", className: "flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:text-destructive hover:bg-accent/50", children: _jsx(IconTrash, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Delete resource" })] }) })] })] })) : (_jsxs("div", { className: "absolute top-1 right-1 z-10 flex items-center gap-1", children: [_jsx(CreateMenu, { scope: activeScope, onCreateFile: handleCreateFromToolbar, onCreateResource: handleCreateResourceFromToolbar, onCreateMcpServer: handleCreateMcpServer, canCreateOrgMcp: canCreateOrgMcp, hasOrg: hasOrgForMcp }), _jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: () => fileInputRef.current?.click(), "aria-label": "Upload file", className: "flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconUpload, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Upload file" })] }) }), _jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("a", { href: WORKSPACE_DOCS_URL, target: "_blank", rel: "noopener noreferrer", "aria-label": "What is the Workspace? \u2014 open docs", className: "flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconHelp, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "What is the Workspace? \u2014 open docs" })] }) }), _jsx("input", { ref: fileInputRef, type: "file", multiple: true, className: "hidden", onChange: (e) => {
685
+ setToolbarDeleteConfirmId(null);
686
+ }
687
+ else {
688
+ setToolbarDeleteConfirmId(selectedResourceId);
689
+ }
690
+ }, "aria-label": toolbarDeleteConfirmId === selectedResourceId
691
+ ? "Confirm delete resource"
692
+ : "Delete resource", className: cn("flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:text-destructive hover:bg-accent/50", toolbarDeleteConfirmId === selectedResourceId &&
693
+ "bg-destructive/10 text-destructive"), children: _jsx(IconTrash, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: toolbarDeleteConfirmId === selectedResourceId
694
+ ? "Click again to delete"
695
+ : "Delete resource" })] }) })] })] })) : (_jsxs("div", { className: "absolute top-1 right-1 z-10 flex items-center gap-1", children: [_jsx(CreateMenu, { scope: activeScope, onCreateFile: handleCreateFromToolbar, onCreateResource: handleCreateResourceFromToolbar, onCreateMcpServer: handleCreateMcpServer, canCreateOrgMcp: canCreateOrgMcp, hasOrg: hasOrgForMcp }), _jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: () => fileInputRef.current?.click(), "aria-label": "Upload file", className: "flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconUpload, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Upload file" })] }) }), _jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("a", { href: WORKSPACE_DOCS_URL, target: "_blank", rel: "noopener noreferrer", "aria-label": "What is the Workspace? \u2014 open docs", className: "flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconHelp, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "What is the Workspace? \u2014 open docs" })] }) }), _jsx("input", { ref: fileInputRef, type: "file", multiple: true, className: "hidden", onChange: (e) => {
680
696
  if (e.target.files && e.target.files.length > 0) {
681
697
  handleUploadFiles(e.target.files);
682
698
  e.target.value = "";