@xopcai/xopc 0.0.22 → 0.0.24

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 (128) hide show
  1. package/dist/extensions/telegram/xopc.extension.json +1 -1
  2. package/dist/gateway/static/root/assets/agents-CiZMJZRp.js +216 -0
  3. package/dist/gateway/static/root/assets/agents-CiZMJZRp.js.map +1 -0
  4. package/dist/gateway/static/root/assets/apps-page-tZz69XM3.js +2 -0
  5. package/dist/gateway/static/root/assets/apps-page-tZz69XM3.js.map +1 -0
  6. package/dist/gateway/static/root/assets/{attachment-preview-renderer-CebH7fCz.js → attachment-preview-renderer-CxMJMbD2.js} +4 -4
  7. package/dist/gateway/static/root/assets/{attachment-preview-renderer-CebH7fCz.js.map → attachment-preview-renderer-CxMJMbD2.js.map} +1 -1
  8. package/dist/gateway/static/root/assets/{attachment-process-heavy-Dbf1--O6.js → attachment-process-heavy-EFXPGfWk.js} +6 -6
  9. package/dist/gateway/static/root/assets/{attachment-process-heavy-Dbf1--O6.js.map → attachment-process-heavy-EFXPGfWk.js.map} +1 -1
  10. package/dist/gateway/static/root/assets/{attachment-utils-core-Dt6UxMPV.js → attachment-utils-core-ECbeoa9H.js} +1 -1
  11. package/dist/gateway/static/root/assets/attachment-utils-core-ECbeoa9H.js.map +1 -0
  12. package/dist/gateway/static/root/assets/channels-settings-BAvk9-aK.js +9 -0
  13. package/dist/gateway/static/root/assets/{channels-settings-BGueHxMv.js.map → channels-settings-BAvk9-aK.js.map} +1 -1
  14. package/dist/gateway/static/root/assets/cn-BMCV0OMB.js +2 -0
  15. package/dist/gateway/static/root/assets/cn-BMCV0OMB.js.map +1 -0
  16. package/dist/gateway/static/root/assets/cron-page-CANqvhK7.js +2 -0
  17. package/dist/gateway/static/root/assets/{cron-page-DsVZzPqv.js.map → cron-page-CANqvhK7.js.map} +1 -1
  18. package/dist/gateway/static/root/assets/cron-utils-DyOO6TdN.js +3 -0
  19. package/dist/gateway/static/root/assets/{cron-utils-zbRs2yND.js.map → cron-utils-DyOO6TdN.js.map} +1 -1
  20. package/dist/gateway/static/root/assets/dist-Brod9LF3.js +2 -0
  21. package/dist/gateway/static/root/assets/{dist-CDA7gR_M.js.map → dist-Brod9LF3.js.map} +1 -1
  22. package/dist/gateway/static/root/assets/{docx-preview-DxcHM3sR.js → docx-preview-F-jKDMNv.js} +2 -2
  23. package/dist/gateway/static/root/assets/{docx-preview-DxcHM3sR.js.map → docx-preview-F-jKDMNv.js.map} +1 -1
  24. package/dist/gateway/static/root/assets/{excel-worksheet-utils-Dk66snKA.js → excel-worksheet-utils-DPfAinZn.js} +1 -1
  25. package/dist/gateway/static/root/assets/{excel-worksheet-utils-Dk66snKA.js.map → excel-worksheet-utils-DPfAinZn.js.map} +1 -1
  26. package/dist/gateway/static/root/assets/extension-debug-page-CDD7ozsC.js +2 -0
  27. package/dist/gateway/static/root/assets/{extension-debug-page-CDLp4DAs.js.map → extension-debug-page-CDD7ozsC.js.map} +1 -1
  28. package/dist/gateway/static/root/assets/extension-page-UUFMjoWf.js +2 -0
  29. package/dist/gateway/static/root/assets/{extension-page-DwSCjzHO.js.map → extension-page-UUFMjoWf.js.map} +1 -1
  30. package/dist/gateway/static/root/assets/extension-settings-page-CP9JNc4m.js +2 -0
  31. package/dist/gateway/static/root/assets/extension-settings-page-CP9JNc4m.js.map +1 -0
  32. package/dist/gateway/static/root/assets/index-BZvlG48D.js +150 -0
  33. package/dist/gateway/static/root/assets/index-BZvlG48D.js.map +1 -0
  34. package/dist/gateway/static/root/assets/index-DxkgyT8R.css +1 -0
  35. package/dist/gateway/static/root/assets/{jszip.min-DVUfmhpE.js → jszip.min-CL3dfyxs.js} +1 -1
  36. package/dist/gateway/static/root/assets/{jszip.min-DVUfmhpE.js.map → jszip.min-CL3dfyxs.js.map} +1 -1
  37. package/dist/gateway/static/root/assets/logs-page-Cr0eCGb4.js +2 -0
  38. package/dist/gateway/static/root/assets/{logs-page-ChJ0nsPh.js.map → logs-page-Cr0eCGb4.js.map} +1 -1
  39. package/dist/gateway/static/root/assets/{pdf--jE7rvON.js → pdf-CX6ji-QC.js} +1 -1
  40. package/dist/gateway/static/root/assets/{pdf--jE7rvON.js.map → pdf-CX6ji-QC.js.map} +1 -1
  41. package/dist/gateway/static/root/assets/sessions-page-DwLHN5GJ.js +2 -0
  42. package/dist/gateway/static/root/assets/{sessions-page-Cle4fPla.js.map → sessions-page-DwLHN5GJ.js.map} +1 -1
  43. package/dist/gateway/static/root/assets/settings-page-B3O3R0E4.js +2 -0
  44. package/dist/gateway/static/root/assets/settings-page-B3O3R0E4.js.map +1 -0
  45. package/dist/gateway/static/root/assets/skills-page-DgBYvH6B.js +3 -0
  46. package/dist/gateway/static/root/assets/{skills-page-B-smhcB2.js.map → skills-page-DgBYvH6B.js.map} +1 -1
  47. package/dist/gateway/static/root/assets/vendor-swr-B5fPo7KK.js +2 -0
  48. package/dist/gateway/static/root/assets/{vendor-swr-Dp4nzp5h.js.map → vendor-swr-B5fPo7KK.js.map} +1 -1
  49. package/dist/gateway/static/root/assets/{xlsx-DVk38js7.js → xlsx-CPtvfmVF.js} +1 -1
  50. package/dist/gateway/static/root/assets/{xlsx-DVk38js7.js.map → xlsx-CPtvfmVF.js.map} +1 -1
  51. package/dist/gateway/static/root/index.html +5 -4
  52. package/dist/package.js +1 -1
  53. package/dist/src/agent/image/tool-model-config.js +2 -2
  54. package/dist/src/agent/image/tool-model-config.js.map +1 -1
  55. package/dist/src/agent/tools/execute-code-tool.js +1 -1
  56. package/dist/src/agent/tools/execute-code-tool.js.map +1 -1
  57. package/dist/src/cli/commands/extension-dev.d.ts +2 -0
  58. package/dist/src/cli/commands/extension-dev.js +196 -0
  59. package/dist/src/cli/commands/extension-dev.js.map +1 -0
  60. package/dist/src/cli/commands/extension-marketplace.d.ts +4 -0
  61. package/dist/src/cli/commands/extension-marketplace.js +145 -0
  62. package/dist/src/cli/commands/extension-marketplace.js.map +1 -0
  63. package/dist/src/cli/commands/extension-pack.d.ts +2 -0
  64. package/dist/src/cli/commands/extension-pack.js +242 -0
  65. package/dist/src/cli/commands/extension-pack.js.map +1 -0
  66. package/dist/src/cli/commands/extension.js +13 -0
  67. package/dist/src/cli/commands/extension.js.map +1 -1
  68. package/dist/src/cli/index.js +5 -1
  69. package/dist/src/cli/index.js.map +1 -1
  70. package/dist/src/config/schema.js +1 -1
  71. package/dist/src/config/schema.js.map +1 -1
  72. package/dist/src/extensions/api.d.ts +6 -1
  73. package/dist/src/extensions/api.js +30 -0
  74. package/dist/src/extensions/api.js.map +1 -1
  75. package/dist/src/extensions/engine-check.d.ts +14 -0
  76. package/dist/src/extensions/engine-check.js +148 -0
  77. package/dist/src/extensions/engine-check.js.map +1 -0
  78. package/dist/src/extensions/loader.js +23 -0
  79. package/dist/src/extensions/loader.js.map +1 -1
  80. package/dist/src/extensions/marketplace.d.ts +24 -0
  81. package/dist/src/extensions/marketplace.js +98 -0
  82. package/dist/src/extensions/marketplace.js.map +1 -0
  83. package/dist/src/extensions/normalize-manifest.js +16 -4
  84. package/dist/src/extensions/normalize-manifest.js.map +1 -1
  85. package/dist/src/extensions/sdk/index.d.ts +2 -0
  86. package/dist/src/extensions/sdk/index.js +2 -1
  87. package/dist/src/extensions/sdk/index.js.map +1 -1
  88. package/dist/src/extensions/sdk/testing.d.ts +49 -3
  89. package/dist/src/extensions/sdk/testing.js +174 -5
  90. package/dist/src/extensions/sdk/testing.js.map +1 -1
  91. package/dist/src/extensions/types/core.d.ts +5 -0
  92. package/dist/src/extensions/types/manifest.d.ts +17 -0
  93. package/dist/src/extensions/when-context.d.ts +6 -0
  94. package/dist/src/extensions/when-context.js +28 -0
  95. package/dist/src/extensions/when-context.js.map +1 -0
  96. package/dist/src/extensions/when-expression.d.ts +11 -0
  97. package/dist/src/extensions/when-expression.js +215 -0
  98. package/dist/src/extensions/when-expression.js.map +1 -0
  99. package/dist/src/gateway/hono/app.js +1 -1
  100. package/dist/src/gateway/hono/app.js.map +1 -1
  101. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +28 -0
  102. package/dist/src/gateway/hono/routes/auth-registry-extensions.js.map +1 -1
  103. package/dist/src/providers/index.d.ts +6 -3
  104. package/dist/src/providers/index.js +12 -23
  105. package/dist/src/providers/index.js.map +1 -1
  106. package/package.json +2 -1
  107. package/dist/gateway/static/root/assets/agents-BcLv59-r.js +0 -71
  108. package/dist/gateway/static/root/assets/agents-BcLv59-r.js.map +0 -1
  109. package/dist/gateway/static/root/assets/apps-page-Bl-yxbQo.js +0 -2
  110. package/dist/gateway/static/root/assets/apps-page-Bl-yxbQo.js.map +0 -1
  111. package/dist/gateway/static/root/assets/attachment-utils-core-Dt6UxMPV.js.map +0 -1
  112. package/dist/gateway/static/root/assets/channels-settings-BGueHxMv.js +0 -9
  113. package/dist/gateway/static/root/assets/cron-page-DsVZzPqv.js +0 -2
  114. package/dist/gateway/static/root/assets/cron-utils-zbRs2yND.js +0 -3
  115. package/dist/gateway/static/root/assets/dist-CDA7gR_M.js +0 -2
  116. package/dist/gateway/static/root/assets/extension-debug-page-CDLp4DAs.js +0 -2
  117. package/dist/gateway/static/root/assets/extension-page-DwSCjzHO.js +0 -2
  118. package/dist/gateway/static/root/assets/extension-settings-page-Rdmxe24_.js +0 -2
  119. package/dist/gateway/static/root/assets/extension-settings-page-Rdmxe24_.js.map +0 -1
  120. package/dist/gateway/static/root/assets/index-D9Wmfh2f.css +0 -1
  121. package/dist/gateway/static/root/assets/index-DG8WvMbu.js +0 -150
  122. package/dist/gateway/static/root/assets/index-DG8WvMbu.js.map +0 -1
  123. package/dist/gateway/static/root/assets/logs-page-ChJ0nsPh.js +0 -2
  124. package/dist/gateway/static/root/assets/sessions-page-Cle4fPla.js +0 -2
  125. package/dist/gateway/static/root/assets/settings-page-Dyo2NYdy.js +0 -2
  126. package/dist/gateway/static/root/assets/settings-page-Dyo2NYdy.js.map +0 -1
  127. package/dist/gateway/static/root/assets/skills-page-B-smhcB2.js +0 -3
  128. package/dist/gateway/static/root/assets/vendor-swr-Dp4nzp5h.js +0 -2
@@ -1,2 +1,2 @@
1
1
  function e(e){return!!(e&&typeof e[`!ref`]==`string`&&e[`!ref`].length>0)}function t(t,n,r){if(!n)return`(Sheet "${r}" is missing from the workbook.)`;if(!e(n))return``;try{return t.utils.sheet_to_csv(n)}catch{return`(Could not read sheet "${r}".)`}}export{t as n,e as t};
2
- //# sourceMappingURL=excel-worksheet-utils-Dk66snKA.js.map
2
+ //# sourceMappingURL=excel-worksheet-utils-DPfAinZn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"excel-worksheet-utils-Dk66snKA.js","names":[],"sources":["../../../../../web/src/features/chat/excel-worksheet-utils.ts"],"sourcesContent":["import type { WorkSheet } from 'xlsx';\n\n/** SheetJS utils assume `!ref` exists; some workbooks list sheet names without a matching `Sheets` entry or range. */\nexport function isRenderableWorksheet(ws: WorkSheet | undefined): ws is WorkSheet {\n return Boolean(ws && typeof ws['!ref'] === 'string' && ws['!ref'].length > 0);\n}\n\nexport function safeSheetToCsv(\n XLSX: typeof import('xlsx'),\n worksheet: WorkSheet | undefined,\n sheetName: string,\n): string {\n if (!worksheet) {\n return `(Sheet \"${sheetName}\" is missing from the workbook.)`;\n }\n if (!isRenderableWorksheet(worksheet)) {\n return '';\n }\n try {\n return XLSX.utils.sheet_to_csv(worksheet);\n } catch {\n return `(Could not read sheet \"${sheetName}\".)`;\n }\n}\n"],"mappings":"AAGA,SAAgB,EAAsB,EAA4C,CAChF,MAAO,GAAQ,GAAM,OAAO,EAAG,SAAY,UAAY,EAAG,QAAQ,OAAS,GAG7E,SAAgB,EACd,EACA,EACA,EACQ,CACR,GAAI,CAAC,EACH,MAAO,WAAW,EAAU,kCAE9B,GAAI,CAAC,EAAsB,EAAU,CACnC,MAAO,GAET,GAAI,CACF,OAAO,EAAK,MAAM,aAAa,EAAU,MACnC,CACN,MAAO,0BAA0B,EAAU"}
1
+ {"version":3,"file":"excel-worksheet-utils-DPfAinZn.js","names":[],"sources":["../../../../../web/src/features/chat/excel-worksheet-utils.ts"],"sourcesContent":["import type { WorkSheet } from 'xlsx';\n\n/** SheetJS utils assume `!ref` exists; some workbooks list sheet names without a matching `Sheets` entry or range. */\nexport function isRenderableWorksheet(ws: WorkSheet | undefined): ws is WorkSheet {\n return Boolean(ws && typeof ws['!ref'] === 'string' && ws['!ref'].length > 0);\n}\n\nexport function safeSheetToCsv(\n XLSX: typeof import('xlsx'),\n worksheet: WorkSheet | undefined,\n sheetName: string,\n): string {\n if (!worksheet) {\n return `(Sheet \"${sheetName}\" is missing from the workbook.)`;\n }\n if (!isRenderableWorksheet(worksheet)) {\n return '';\n }\n try {\n return XLSX.utils.sheet_to_csv(worksheet);\n } catch {\n return `(Could not read sheet \"${sheetName}\".)`;\n }\n}\n"],"mappings":"AAGA,SAAgB,EAAsB,EAA4C,CAChF,MAAO,GAAQ,GAAM,OAAO,EAAG,SAAY,UAAY,EAAG,QAAQ,OAAS,GAG7E,SAAgB,EACd,EACA,EACA,EACQ,CACR,GAAI,CAAC,EACH,MAAO,WAAW,EAAU,kCAE9B,GAAI,CAAC,EAAsB,EAAU,CACnC,MAAO,GAET,GAAI,CACF,OAAO,EAAK,MAAM,aAAa,EAAU,MACnC,CACN,MAAO,0BAA0B,EAAU"}
@@ -0,0 +1,2 @@
1
+ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{i as t,t as n}from"./vendor-react-DbimaAId.js";import{Bt as r,Jr as i}from"./index-BZvlG48D.js";var a=e(t(),1),o=n(),s=`xopc.extensionUiGrants.v1`;function c(){let{t:e}=i(),t=r(),[n,s]=(0,a.useState)(()=>l()),c=(0,a.useMemo)(()=>[...t].sort((e,t)=>e.id.localeCompare(t.id)),[t]);return(0,o.jsxs)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-6 px-4 py-8`,children:[(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h1`,{className:`text-lg font-semibold text-fg`,children:e(`extensionDebug.title`)}),(0,o.jsx)(`p`,{className:`mt-1 text-sm text-fg-muted`,children:e(`extensionDebug.subtitle`)})]}),(0,o.jsxs)(`section`,{className:`rounded-xl border border-edge bg-surface-base p-4`,children:[(0,o.jsx)(`h2`,{className:`text-sm font-semibold text-fg`,children:e(`extensionDebug.grantsHeading`)}),(0,o.jsx)(`p`,{className:`mt-1 text-xs text-fg-muted`,children:e(`extensionDebug.grantsHint`)}),(0,o.jsx)(`pre`,{className:`mt-3 max-h-48 overflow-auto rounded-lg border border-edge-subtle bg-surface-muted p-3 font-mono text-xs text-fg`,children:n}),(0,o.jsx)(`button`,{type:`button`,className:`mt-3 rounded-lg border border-edge px-3 py-1.5 text-xs font-medium text-fg hover:bg-surface-hover`,onClick:()=>s(l()),children:e(`extensionDebug.refresh`)})]}),(0,o.jsxs)(`section`,{className:`rounded-xl border border-edge bg-surface-base p-4`,children:[(0,o.jsx)(`h2`,{className:`text-sm font-semibold text-fg`,children:e(`extensionDebug.listHeading`)}),(0,o.jsx)(`div`,{className:`mt-3 overflow-x-auto`,children:(0,o.jsxs)(`table`,{className:`w-full min-w-[32rem] border-collapse text-left text-sm`,children:[(0,o.jsx)(`thead`,{children:(0,o.jsxs)(`tr`,{className:`border-b border-edge text-xs uppercase text-fg-muted`,children:[(0,o.jsx)(`th`,{className:`py-2 pr-2`,children:e(`extensionDebug.colId`)}),(0,o.jsx)(`th`,{className:`py-2 pr-2`,children:e(`extensionDebug.colName`)}),(0,o.jsx)(`th`,{className:`py-2`,children:e(`extensionDebug.colPermissions`)})]})}),(0,o.jsx)(`tbody`,{children:c.map(e=>(0,o.jsxs)(`tr`,{className:`border-b border-edge-subtle`,children:[(0,o.jsx)(`td`,{className:`py-2 pr-2 font-mono text-xs text-fg`,children:e.id}),(0,o.jsx)(`td`,{className:`py-2 pr-2 text-fg`,children:e.name}),(0,o.jsx)(`td`,{className:`py-2 font-mono text-xs text-fg-muted`,children:(e.ui?.permissions??[]).join(`, `)||`—`})]},e.id))})]})})]}),(0,o.jsxs)(`section`,{className:`rounded-xl border border-dashed border-edge-subtle bg-surface-muted/50 p-4 text-sm text-fg-muted`,children:[(0,o.jsx)(`h2`,{className:`text-sm font-semibold text-fg`,children:e(`extensionDebug.futureHeading`)}),(0,o.jsx)(`p`,{className:`mt-2`,children:e(`extensionDebug.futureBody`)})]})]})}function l(){try{let e=localStorage.getItem(s);if(!e)return`{}`;let t=JSON.parse(e);return JSON.stringify(t,null,2)}catch(e){return e instanceof Error?e.message:String(e)}}export{c as ExtensionDebugPage};
2
+ //# sourceMappingURL=extension-debug-page-CDD7ozsC.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension-debug-page-CDLp4DAs.js","names":[],"sources":["../../../../../web/src/features/extensions/extension-debug-page.tsx"],"sourcesContent":["/**\n * Extension debug — Settings panel: extension list, declared permissions, UI grant fingerprints.\n */\n\nimport { useMemo, useState } from 'react';\n\nimport { useTranslation } from 'react-i18next';\n\nimport { useExtensions } from '@/features/extensions/extension-provider';\n\nconst GRANTS_STORAGE_KEY = 'xopc.extensionUiGrants.v1';\n\nexport function ExtensionDebugPage() {\n const { t } = useTranslation();\n const extensions = useExtensions();\n const [grantsRaw, setGrantsRaw] = useState(() => readGrantsSafe());\n\n const sorted = useMemo(\n () => [...extensions].sort((a, b) => a.id.localeCompare(b.id)),\n [extensions],\n );\n\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-6 px-4 py-8\">\n <div>\n <h1 className=\"text-lg font-semibold text-fg\">{t('extensionDebug.title')}</h1>\n <p className=\"mt-1 text-sm text-fg-muted\">{t('extensionDebug.subtitle')}</p>\n </div>\n\n <section className=\"rounded-xl border border-edge bg-surface-base p-4\">\n <h2 className=\"text-sm font-semibold text-fg\">{t('extensionDebug.grantsHeading')}</h2>\n <p className=\"mt-1 text-xs text-fg-muted\">{t('extensionDebug.grantsHint')}</p>\n <pre className=\"mt-3 max-h-48 overflow-auto rounded-lg border border-edge-subtle bg-surface-muted p-3 font-mono text-xs text-fg\">\n {grantsRaw}\n </pre>\n <button\n type=\"button\"\n className=\"mt-3 rounded-lg border border-edge px-3 py-1.5 text-xs font-medium text-fg hover:bg-surface-hover\"\n onClick={() => setGrantsRaw(readGrantsSafe())}\n >\n {t('extensionDebug.refresh')}\n </button>\n </section>\n\n <section className=\"rounded-xl border border-edge bg-surface-base p-4\">\n <h2 className=\"text-sm font-semibold text-fg\">{t('extensionDebug.listHeading')}</h2>\n <div className=\"mt-3 overflow-x-auto\">\n <table className=\"w-full min-w-[32rem] border-collapse text-left text-sm\">\n <thead>\n <tr className=\"border-b border-edge text-xs uppercase text-fg-muted\">\n <th className=\"py-2 pr-2\">{t('extensionDebug.colId')}</th>\n <th className=\"py-2 pr-2\">{t('extensionDebug.colName')}</th>\n <th className=\"py-2\">{t('extensionDebug.colPermissions')}</th>\n </tr>\n </thead>\n <tbody>\n {sorted.map((e) => (\n <tr key={e.id} className=\"border-b border-edge-subtle\">\n <td className=\"py-2 pr-2 font-mono text-xs text-fg\">{e.id}</td>\n <td className=\"py-2 pr-2 text-fg\">{e.name}</td>\n <td className=\"py-2 font-mono text-xs text-fg-muted\">\n {(e.ui?.permissions ?? []).join(', ') || '—'}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </section>\n\n <section className=\"rounded-xl border border-dashed border-edge-subtle bg-surface-muted/50 p-4 text-sm text-fg-muted\">\n <h2 className=\"text-sm font-semibold text-fg\">{t('extensionDebug.futureHeading')}</h2>\n <p className=\"mt-2\">{t('extensionDebug.futureBody')}</p>\n </section>\n </div>\n );\n}\n\nfunction readGrantsSafe(): string {\n try {\n const raw = localStorage.getItem(GRANTS_STORAGE_KEY);\n if (!raw) return '{}';\n const parsed = JSON.parse(raw) as unknown;\n return JSON.stringify(parsed, null, 2);\n } catch (e) {\n return e instanceof Error ? e.message : String(e);\n }\n}\n"],"mappings":"8KAUM,EAAqB,4BAE3B,SAAgB,GAAqB,CACnC,GAAM,CAAE,KAAM,GAAgB,CACxB,EAAa,GAAe,CAC5B,CAAC,EAAW,IAAA,EAAA,EAAA,cAA+B,GAAgB,CAAC,CAE5D,GAAA,EAAA,EAAA,aACE,CAAC,GAAG,EAAW,CAAC,MAAM,EAAG,IAAM,EAAE,GAAG,cAAc,EAAE,GAAG,CAAC,CAC9D,CAAC,EAAW,CACb,CAED,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,uEAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,yCAAiC,EAAE,uBAAuB,CAAM,CAAA,EAC9E,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,sCAA8B,EAAE,0BAA0B,CAAK,CAAA,CACxE,CAAA,CAAA,EAEN,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,6DAAnB,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,yCAAiC,EAAE,+BAA+B,CAAM,CAAA,EACtF,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,sCAA8B,EAAE,4BAA4B,CAAK,CAAA,EAC9E,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,2HACZ,EACG,CAAA,EACN,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,UAAU,oGACV,YAAe,EAAa,GAAgB,CAAC,UAE5C,EAAE,yBAAyB,CACrB,CAAA,CACD,IAEV,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,6DAAnB,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,yCAAiC,EAAE,6BAA6B,CAAM,CAAA,EACpF,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,iCACb,EAAA,EAAA,MAAC,QAAD,CAAO,UAAU,kEAAjB,EACE,EAAA,EAAA,KAAC,QAAD,CAAA,UACE,EAAA,EAAA,MAAC,KAAD,CAAI,UAAU,gEAAd,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,qBAAa,EAAE,uBAAuB,CAAM,CAAA,EAC1D,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,qBAAa,EAAE,yBAAyB,CAAM,CAAA,EAC5D,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,gBAAQ,EAAE,gCAAgC,CAAM,CAAA,CAC3D,GACC,CAAA,EACR,EAAA,EAAA,KAAC,QAAD,CAAA,SACG,EAAO,IAAK,IACX,EAAA,EAAA,MAAC,KAAD,CAAe,UAAU,uCAAzB,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,+CAAuC,EAAE,GAAQ,CAAA,EAC/D,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,6BAAqB,EAAE,KAAU,CAAA,EAC/C,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,iDACV,EAAE,IAAI,aAAe,EAAE,EAAE,KAAK,KAAK,EAAI,IACtC,CAAA,CACF,EANI,EAAE,GAMN,CACL,CACI,CAAA,CACF,GACJ,CAAA,CACE,IAEV,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,4GAAnB,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,yCAAiC,EAAE,+BAA+B,CAAM,CAAA,EACtF,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,gBAAQ,EAAE,4BAA4B,CAAK,CAAA,CAChD,GACN,GAIV,SAAS,GAAyB,CAChC,GAAI,CACF,IAAM,EAAM,aAAa,QAAQ,EAAmB,CACpD,GAAI,CAAC,EAAK,MAAO,KACjB,IAAM,EAAS,KAAK,MAAM,EAAI,CAC9B,OAAO,KAAK,UAAU,EAAQ,KAAM,EAAE,OAC/B,EAAG,CACV,OAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,EAAE"}
1
+ {"version":3,"file":"extension-debug-page-CDD7ozsC.js","names":[],"sources":["../../../../../web/src/features/extensions/extension-debug-page.tsx"],"sourcesContent":["/**\n * Extension debug — Settings panel: extension list, declared permissions, UI grant fingerprints.\n */\n\nimport { useMemo, useState } from 'react';\n\nimport { useTranslation } from 'react-i18next';\n\nimport { useExtensions } from '@/features/extensions/extension-provider';\n\nconst GRANTS_STORAGE_KEY = 'xopc.extensionUiGrants.v1';\n\nexport function ExtensionDebugPage() {\n const { t } = useTranslation();\n const extensions = useExtensions();\n const [grantsRaw, setGrantsRaw] = useState(() => readGrantsSafe());\n\n const sorted = useMemo(\n () => [...extensions].sort((a, b) => a.id.localeCompare(b.id)),\n [extensions],\n );\n\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-6 px-4 py-8\">\n <div>\n <h1 className=\"text-lg font-semibold text-fg\">{t('extensionDebug.title')}</h1>\n <p className=\"mt-1 text-sm text-fg-muted\">{t('extensionDebug.subtitle')}</p>\n </div>\n\n <section className=\"rounded-xl border border-edge bg-surface-base p-4\">\n <h2 className=\"text-sm font-semibold text-fg\">{t('extensionDebug.grantsHeading')}</h2>\n <p className=\"mt-1 text-xs text-fg-muted\">{t('extensionDebug.grantsHint')}</p>\n <pre className=\"mt-3 max-h-48 overflow-auto rounded-lg border border-edge-subtle bg-surface-muted p-3 font-mono text-xs text-fg\">\n {grantsRaw}\n </pre>\n <button\n type=\"button\"\n className=\"mt-3 rounded-lg border border-edge px-3 py-1.5 text-xs font-medium text-fg hover:bg-surface-hover\"\n onClick={() => setGrantsRaw(readGrantsSafe())}\n >\n {t('extensionDebug.refresh')}\n </button>\n </section>\n\n <section className=\"rounded-xl border border-edge bg-surface-base p-4\">\n <h2 className=\"text-sm font-semibold text-fg\">{t('extensionDebug.listHeading')}</h2>\n <div className=\"mt-3 overflow-x-auto\">\n <table className=\"w-full min-w-[32rem] border-collapse text-left text-sm\">\n <thead>\n <tr className=\"border-b border-edge text-xs uppercase text-fg-muted\">\n <th className=\"py-2 pr-2\">{t('extensionDebug.colId')}</th>\n <th className=\"py-2 pr-2\">{t('extensionDebug.colName')}</th>\n <th className=\"py-2\">{t('extensionDebug.colPermissions')}</th>\n </tr>\n </thead>\n <tbody>\n {sorted.map((e) => (\n <tr key={e.id} className=\"border-b border-edge-subtle\">\n <td className=\"py-2 pr-2 font-mono text-xs text-fg\">{e.id}</td>\n <td className=\"py-2 pr-2 text-fg\">{e.name}</td>\n <td className=\"py-2 font-mono text-xs text-fg-muted\">\n {(e.ui?.permissions ?? []).join(', ') || '—'}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </section>\n\n <section className=\"rounded-xl border border-dashed border-edge-subtle bg-surface-muted/50 p-4 text-sm text-fg-muted\">\n <h2 className=\"text-sm font-semibold text-fg\">{t('extensionDebug.futureHeading')}</h2>\n <p className=\"mt-2\">{t('extensionDebug.futureBody')}</p>\n </section>\n </div>\n );\n}\n\nfunction readGrantsSafe(): string {\n try {\n const raw = localStorage.getItem(GRANTS_STORAGE_KEY);\n if (!raw) return '{}';\n const parsed = JSON.parse(raw) as unknown;\n return JSON.stringify(parsed, null, 2);\n } catch (e) {\n return e instanceof Error ? e.message : String(e);\n }\n}\n"],"mappings":"+KAUM,EAAqB,4BAE3B,SAAgB,GAAqB,CACnC,GAAM,CAAE,KAAM,GAAgB,CACxB,EAAa,GAAe,CAC5B,CAAC,EAAW,IAAA,EAAA,EAAA,cAA+B,GAAgB,CAAC,CAE5D,GAAA,EAAA,EAAA,aACE,CAAC,GAAG,EAAW,CAAC,MAAM,EAAG,IAAM,EAAE,GAAG,cAAc,EAAE,GAAG,CAAC,CAC9D,CAAC,EAAW,CACb,CAED,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,uEAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,yCAAiC,EAAE,uBAAuB,CAAM,CAAA,EAC9E,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,sCAA8B,EAAE,0BAA0B,CAAK,CAAA,CACxE,CAAA,CAAA,EAEN,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,6DAAnB,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,yCAAiC,EAAE,+BAA+B,CAAM,CAAA,EACtF,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,sCAA8B,EAAE,4BAA4B,CAAK,CAAA,EAC9E,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,2HACZ,EACG,CAAA,EACN,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,UAAU,oGACV,YAAe,EAAa,GAAgB,CAAC,UAE5C,EAAE,yBAAyB,CACrB,CAAA,CACD,IAEV,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,6DAAnB,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,yCAAiC,EAAE,6BAA6B,CAAM,CAAA,EACpF,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,iCACb,EAAA,EAAA,MAAC,QAAD,CAAO,UAAU,kEAAjB,EACE,EAAA,EAAA,KAAC,QAAD,CAAA,UACE,EAAA,EAAA,MAAC,KAAD,CAAI,UAAU,gEAAd,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,qBAAa,EAAE,uBAAuB,CAAM,CAAA,EAC1D,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,qBAAa,EAAE,yBAAyB,CAAM,CAAA,EAC5D,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,gBAAQ,EAAE,gCAAgC,CAAM,CAAA,CAC3D,GACC,CAAA,EACR,EAAA,EAAA,KAAC,QAAD,CAAA,SACG,EAAO,IAAK,IACX,EAAA,EAAA,MAAC,KAAD,CAAe,UAAU,uCAAzB,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,+CAAuC,EAAE,GAAQ,CAAA,EAC/D,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,6BAAqB,EAAE,KAAU,CAAA,EAC/C,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,iDACV,EAAE,IAAI,aAAe,EAAE,EAAE,KAAK,KAAK,EAAI,IACtC,CAAA,CACF,EANI,EAAE,GAMN,CACL,CACI,CAAA,CACF,GACJ,CAAA,CACE,IAEV,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,4GAAnB,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,yCAAiC,EAAE,+BAA+B,CAAM,CAAA,EACtF,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,gBAAQ,EAAE,4BAA4B,CAAK,CAAA,CAChD,GACN,GAIV,SAAS,GAAyB,CAChC,GAAI,CACF,IAAM,EAAM,aAAa,QAAQ,EAAmB,CACpD,GAAI,CAAC,EAAK,MAAO,KACjB,IAAM,EAAS,KAAK,MAAM,EAAI,CAC9B,OAAO,KAAK,UAAU,EAAQ,KAAM,EAAE,OAC/B,EAAG,CACV,OAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,EAAE"}
@@ -0,0 +1,2 @@
1
+ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{i as t,t as n}from"./vendor-react-DbimaAId.js";import{Ht as r,Kr as i,Kt as a,u as o}from"./index-BZvlG48D.js";var s=e(t(),1),c=n();function l(){let{extensionId:e,pageId:t}=i(),n=r(),l=a(e=>e.setPageHeader),d=a(e=>e.clearPageHeader),f=e?n.find(t=>t.id===e):void 0,p=f?.ui?.contributions?.pages,m=e&&p?.length?t?p.find(n=>n.id===t||n.id===`${e}.${t}`):p[0]:void 0;return(0,s.useLayoutEffect)(()=>{if(!e||!f||!m)return d(),()=>d();let t=m.title?.trim()||f.name||e;return l({startExtra:null,main:(0,c.jsx)(`div`,{className:`w-full min-w-0 px-3 sm:px-5 xl:px-6`,children:(0,c.jsx)(`h1`,{className:`min-w-0 truncate text-base font-semibold tracking-tight text-fg`,title:t,children:t})}),end:null}),()=>d()},[d,f,e,m,l]),e?f?p?.length?m?(0,c.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col`,children:(0,c.jsx)(o,{extensionId:e,extensionName:f.name,entrypoint:m.entrypoint,permissions:f.ui?.permissions,title:m.title,className:`min-h-0 flex-1`,fixedHeight:void 0,maxHeight:99999})}):(0,c.jsx)(u,{message:`Page "${t}" not found in extension "${e}".`}):(0,c.jsx)(u,{message:`Extension "${e}" has no page contributions.`}):(0,c.jsx)(u,{message:`Extension "${e}" not found or has no UI.`}):(0,c.jsx)(u,{message:`No extension ID provided.`})}function u({message:e}){return(0,c.jsx)(`div`,{className:`flex min-h-[min(40vh,16rem)] flex-1 items-center justify-center`,children:(0,c.jsx)(`div`,{className:`text-center`,children:(0,c.jsx)(`p`,{className:`text-sm text-fg-muted`,children:e})})})}export{l as ExtensionPage};
2
+ //# sourceMappingURL=extension-page-UUFMjoWf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension-page-DwSCjzHO.js","names":[],"sources":["../../../../../web/src/features/extensions/extension-page.tsx"],"sourcesContent":["/**\n * ExtensionPage — renders a full-page extension UI via ExtensionIframeHost.\n *\n * Mounted at /apps/:extensionId (or /apps/:extensionId/:pageId for multi-page extensions).\n */\n\nimport { useLayoutEffect } from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport { usePageHeaderStore } from '@/stores/page-header-store';\n\nimport { ExtensionIframeHost } from './extension-iframe-host';\nimport { useUiExtensions } from './extension-provider';\n\nexport function ExtensionPage() {\n const { extensionId, pageId } = useParams<{ extensionId: string; pageId?: string }>();\n const uiExtensions = useUiExtensions();\n const setPageHeader = usePageHeaderStore((s) => s.setPageHeader);\n const clearPageHeader = usePageHeaderStore((s) => s.clearPageHeader);\n\n const extension = extensionId ? uiExtensions.find((ext) => ext.id === extensionId) : undefined;\n const pages = extension?.ui?.contributions?.pages;\n const page =\n extensionId && pages?.length\n ? pageId\n ? pages.find((p) => p.id === pageId || p.id === `${extensionId}.${pageId}`)\n : pages[0]\n : undefined;\n\n useLayoutEffect(() => {\n if (!extensionId || !extension || !page) {\n clearPageHeader();\n return () => clearPageHeader();\n }\n const headline = page.title?.trim() || extension.name || extensionId;\n setPageHeader({\n startExtra: null,\n main: (\n <div className=\"w-full min-w-0 px-3 sm:px-5 xl:px-6\">\n <h1\n className=\"min-w-0 truncate text-base font-semibold tracking-tight text-fg\"\n title={headline}\n >\n {headline}\n </h1>\n </div>\n ),\n end: null,\n });\n return () => clearPageHeader();\n }, [clearPageHeader, extension, extensionId, page, setPageHeader]);\n\n if (!extensionId) {\n return <ExtensionPageNotFound message=\"No extension ID provided.\" />;\n }\n\n if (!extension) {\n return (\n <ExtensionPageNotFound message={`Extension \"${extensionId}\" not found or has no UI.`} />\n );\n }\n\n if (!pages?.length) {\n return (\n <ExtensionPageNotFound message={`Extension \"${extensionId}\" has no page contributions.`} />\n );\n }\n\n if (!page) {\n return (\n <ExtensionPageNotFound message={`Page \"${pageId}\" not found in extension \"${extensionId}\".`} />\n );\n }\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col\">\n <ExtensionIframeHost\n extensionId={extensionId}\n extensionName={extension.name}\n entrypoint={page.entrypoint}\n permissions={extension.ui?.permissions}\n title={page.title}\n className=\"min-h-0 flex-1\"\n fixedHeight={undefined}\n maxHeight={99999}\n />\n </div>\n );\n}\n\nfunction ExtensionPageNotFound({ message }: { message: string }) {\n return (\n <div className=\"flex min-h-[min(40vh,16rem)] flex-1 items-center justify-center\">\n <div className=\"text-center\">\n <p className=\"text-sm text-fg-muted\">{message}</p>\n </div>\n </div>\n );\n}\n"],"mappings":"4LAcA,SAAgB,GAAgB,CAC9B,GAAM,CAAE,cAAa,UAAW,GAAqD,CAC/E,EAAe,GAAiB,CAChC,EAAgB,EAAoB,GAAM,EAAE,cAAc,CAC1D,EAAkB,EAAoB,GAAM,EAAE,gBAAgB,CAE9D,EAAY,EAAc,EAAa,KAAM,GAAQ,EAAI,KAAO,EAAY,CAAG,IAAA,GAC/E,EAAQ,GAAW,IAAI,eAAe,MACtC,EACJ,GAAe,GAAO,OAClB,EACE,EAAM,KAAM,GAAM,EAAE,KAAO,GAAU,EAAE,KAAO,GAAG,EAAY,GAAG,IAAS,CACzE,EAAM,GACR,IAAA,GA+CN,OA7CA,EAAA,EAAA,qBAAsB,CACpB,GAAI,CAAC,GAAe,CAAC,GAAa,CAAC,EAEjC,OADA,GAAiB,KACJ,GAAiB,CAEhC,IAAM,EAAW,EAAK,OAAO,MAAM,EAAI,EAAU,MAAQ,EAezD,OAdA,EAAc,CACZ,WAAY,KACZ,MACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,gDACb,EAAA,EAAA,KAAC,KAAD,CACE,UAAU,kEACV,MAAO,WAEN,EACE,CAAA,CACD,CAAA,CAER,IAAK,KACN,CAAC,KACW,GAAiB,EAC7B,CAAC,EAAiB,EAAW,EAAa,EAAM,EAAc,CAAC,CAE7D,EAIA,EAMA,GAAO,OAMP,GAOH,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,yCACb,EAAA,EAAA,KAAC,EAAD,CACe,cACb,cAAe,EAAU,KACzB,WAAY,EAAK,WACjB,YAAa,EAAU,IAAI,YAC3B,MAAO,EAAK,MACZ,UAAU,iBACV,YAAa,IAAA,GACb,UAAW,MACX,CAAA,CACE,CAAA,EAhBJ,EAAA,EAAA,KAAC,EAAD,CAAuB,QAAS,SAAS,EAAO,4BAA4B,EAAY,IAAO,CAAA,EAN/F,EAAA,EAAA,KAAC,EAAD,CAAuB,QAAS,cAAc,EAAY,8BAAiC,CAAA,EAN3F,EAAA,EAAA,KAAC,EAAD,CAAuB,QAAS,cAAc,EAAY,2BAA8B,CAAA,EALnF,EAAA,EAAA,KAAC,EAAD,CAAuB,QAAQ,4BAA8B,CAAA,CAqCxE,SAAS,EAAsB,CAAE,WAAgC,CAC/D,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,4EACb,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,wBACb,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,iCAAyB,EAAY,CAAA,CAC9C,CAAA,CACF,CAAA"}
1
+ {"version":3,"file":"extension-page-UUFMjoWf.js","names":[],"sources":["../../../../../web/src/features/extensions/extension-page.tsx"],"sourcesContent":["/**\n * ExtensionPage — renders a full-page extension UI via ExtensionIframeHost.\n *\n * Mounted at /apps/:extensionId (or /apps/:extensionId/:pageId for multi-page extensions).\n */\n\nimport { useLayoutEffect } from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport { usePageHeaderStore } from '@/stores/page-header-store';\n\nimport { ExtensionIframeHost } from './extension-iframe-host';\nimport { useUiExtensions } from './extension-provider';\n\nexport function ExtensionPage() {\n const { extensionId, pageId } = useParams<{ extensionId: string; pageId?: string }>();\n const uiExtensions = useUiExtensions();\n const setPageHeader = usePageHeaderStore((s) => s.setPageHeader);\n const clearPageHeader = usePageHeaderStore((s) => s.clearPageHeader);\n\n const extension = extensionId ? uiExtensions.find((ext) => ext.id === extensionId) : undefined;\n const pages = extension?.ui?.contributions?.pages;\n const page =\n extensionId && pages?.length\n ? pageId\n ? pages.find((p) => p.id === pageId || p.id === `${extensionId}.${pageId}`)\n : pages[0]\n : undefined;\n\n useLayoutEffect(() => {\n if (!extensionId || !extension || !page) {\n clearPageHeader();\n return () => clearPageHeader();\n }\n const headline = page.title?.trim() || extension.name || extensionId;\n setPageHeader({\n startExtra: null,\n main: (\n <div className=\"w-full min-w-0 px-3 sm:px-5 xl:px-6\">\n <h1\n className=\"min-w-0 truncate text-base font-semibold tracking-tight text-fg\"\n title={headline}\n >\n {headline}\n </h1>\n </div>\n ),\n end: null,\n });\n return () => clearPageHeader();\n }, [clearPageHeader, extension, extensionId, page, setPageHeader]);\n\n if (!extensionId) {\n return <ExtensionPageNotFound message=\"No extension ID provided.\" />;\n }\n\n if (!extension) {\n return (\n <ExtensionPageNotFound message={`Extension \"${extensionId}\" not found or has no UI.`} />\n );\n }\n\n if (!pages?.length) {\n return (\n <ExtensionPageNotFound message={`Extension \"${extensionId}\" has no page contributions.`} />\n );\n }\n\n if (!page) {\n return (\n <ExtensionPageNotFound message={`Page \"${pageId}\" not found in extension \"${extensionId}\".`} />\n );\n }\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col\">\n <ExtensionIframeHost\n extensionId={extensionId}\n extensionName={extension.name}\n entrypoint={page.entrypoint}\n permissions={extension.ui?.permissions}\n title={page.title}\n className=\"min-h-0 flex-1\"\n fixedHeight={undefined}\n maxHeight={99999}\n />\n </div>\n );\n}\n\nfunction ExtensionPageNotFound({ message }: { message: string }) {\n return (\n <div className=\"flex min-h-[min(40vh,16rem)] flex-1 items-center justify-center\">\n <div className=\"text-center\">\n <p className=\"text-sm text-fg-muted\">{message}</p>\n </div>\n </div>\n );\n}\n"],"mappings":"8LAcA,SAAgB,GAAgB,CAC9B,GAAM,CAAE,cAAa,UAAW,GAAqD,CAC/E,EAAe,GAAiB,CAChC,EAAgB,EAAoB,GAAM,EAAE,cAAc,CAC1D,EAAkB,EAAoB,GAAM,EAAE,gBAAgB,CAE9D,EAAY,EAAc,EAAa,KAAM,GAAQ,EAAI,KAAO,EAAY,CAAG,IAAA,GAC/E,EAAQ,GAAW,IAAI,eAAe,MACtC,EACJ,GAAe,GAAO,OAClB,EACE,EAAM,KAAM,GAAM,EAAE,KAAO,GAAU,EAAE,KAAO,GAAG,EAAY,GAAG,IAAS,CACzE,EAAM,GACR,IAAA,GA+CN,OA7CA,EAAA,EAAA,qBAAsB,CACpB,GAAI,CAAC,GAAe,CAAC,GAAa,CAAC,EAEjC,OADA,GAAiB,KACJ,GAAiB,CAEhC,IAAM,EAAW,EAAK,OAAO,MAAM,EAAI,EAAU,MAAQ,EAezD,OAdA,EAAc,CACZ,WAAY,KACZ,MACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,gDACb,EAAA,EAAA,KAAC,KAAD,CACE,UAAU,kEACV,MAAO,WAEN,EACE,CAAA,CACD,CAAA,CAER,IAAK,KACN,CAAC,KACW,GAAiB,EAC7B,CAAC,EAAiB,EAAW,EAAa,EAAM,EAAc,CAAC,CAE7D,EAIA,EAMA,GAAO,OAMP,GAOH,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,yCACb,EAAA,EAAA,KAAC,EAAD,CACe,cACb,cAAe,EAAU,KACzB,WAAY,EAAK,WACjB,YAAa,EAAU,IAAI,YAC3B,MAAO,EAAK,MACZ,UAAU,iBACV,YAAa,IAAA,GACb,UAAW,MACX,CAAA,CACE,CAAA,EAhBJ,EAAA,EAAA,KAAC,EAAD,CAAuB,QAAS,SAAS,EAAO,4BAA4B,EAAY,IAAO,CAAA,EAN/F,EAAA,EAAA,KAAC,EAAD,CAAuB,QAAS,cAAc,EAAY,8BAAiC,CAAA,EAN3F,EAAA,EAAA,KAAC,EAAD,CAAuB,QAAS,cAAc,EAAY,2BAA8B,CAAA,EALnF,EAAA,EAAA,KAAC,EAAD,CAAuB,QAAQ,4BAA8B,CAAA,CAqCxE,SAAS,EAAsB,CAAE,WAAgC,CAC/D,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,4EACb,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,wBACb,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,iCAAyB,EAAY,CAAA,CAC9C,CAAA,CACF,CAAA"}
@@ -0,0 +1,2 @@
1
+ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{i as t,t as n}from"./vendor-react-DbimaAId.js";import{i as r}from"./vendor-swr-B5fPo7KK.js";import{t as i}from"./cn-BMCV0OMB.js";import{Bt as a,Gt as o,Kr as s,Ut as c,Wt as l,qt as u,sn as d,u as f}from"./index-BZvlG48D.js";var p=e(t(),1),m=n();function h(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function g(e){let t=e[`x-order`];return typeof t==`number`&&!Number.isNaN(t)?t:999}function _(e){let t=e[`x-group`];return typeof t==`string`&&t.length>0?t:``}function v(e){return e[`x-hidden`]===!0}function y(e){let t=e.properties;if(!h(t))return[];let n=[];for(let[e,r]of Object.entries(t))h(r)&&(v(r)||n.push({key:e,sub:r,order:g(r),group:_(r),hidden:!1}));return n.sort((e,t)=>e.order-t.order||e.key.localeCompare(t.key)),n}function b(e){let t=new Map;for(let n of e){let e=n.group;t.has(e)||t.set(e,[]),t.get(e).push(n)}return t}function x({name:e,s:t,value:n,onChange:r,disabled:i}){let a=typeof t.description==`string`?t.description:void 0,o=(typeof t[`x-placeholder`]==`string`?t[`x-placeholder`]:null)||a,s=t.format;return Array.isArray(t.enum)&&t.enum.every(e=>typeof e==`string`)?(0,m.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[a?(0,m.jsx)(`label`,{className:`text-xs text-fg-muted`,children:a}):null,(0,m.jsx)(`select`,{name:e,className:`ui-input h-9 rounded-md border border-edge bg-surface-base px-2 text-sm text-fg`,value:n,disabled:i,onChange:e=>r(e.target.value),children:t.enum.map(e=>(0,m.jsx)(`option`,{value:e,children:e},e))})]}):(0,m.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[a?(0,m.jsx)(`label`,{className:`text-xs text-fg-muted`,children:a}):null,(0,m.jsx)(`input`,{name:e,type:s===`password`?`password`:`text`,className:`ui-input h-9 rounded-md border border-edge bg-surface-base px-2.5 text-sm text-fg placeholder:text-fg-muted/70`,value:n,placeholder:o,disabled:i,onChange:e=>r(e.target.value)})]})}function S({s:e,value:t,onChange:n,disabled:r}){let i=typeof e.description==`string`?e.description:void 0;return(0,m.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[i?(0,m.jsx)(`label`,{className:`text-xs text-fg-muted`,children:i}):null,(0,m.jsx)(`input`,{type:`number`,className:`ui-input h-9 rounded-md border border-edge bg-surface-base px-2.5 text-sm text-fg`,value:Number.isFinite(t)?t:0,disabled:r,onChange:e=>n(Number(e.target.value))})]})}function C({s:e,value:t,onChange:n,disabled:r}){let i=(typeof e.description==`string`?e.description:void 0)??(typeof e.title==`string`&&e.title.length>0?e.title:`Enable`);return(0,m.jsxs)(`label`,{className:`flex items-center gap-2 text-sm text-fg`,children:[(0,m.jsx)(`input`,{type:`checkbox`,className:`h-4 w-4 rounded border border-edge`,checked:t,disabled:r,onChange:e=>n(e.target.checked)}),(0,m.jsx)(`span`,{children:i})]})}function w({s:e,value:t,onChange:n,disabled:r}){let i=typeof e.description==`string`?e.description:void 0,a=e.items;if(!(h(a)&&a.type===`string`))return(0,m.jsx)(`p`,{className:`text-xs text-fg-muted`,children:`Unsupported array type`});let o=e=>{let r=e.trim();!r||t.includes(r)||n([...t,r])};return(0,m.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[i?(0,m.jsx)(`label`,{className:`text-xs text-fg-muted`,children:i}):null,(0,m.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:t.map(e=>(0,m.jsxs)(`span`,{className:`inline-flex items-center gap-1 rounded-md border border-edge bg-surface-panel px-2 py-0.5 text-sm`,children:[e,(0,m.jsx)(`button`,{type:`button`,className:`text-fg-muted hover:text-fg`,disabled:r,onClick:()=>n(t.filter(t=>t!==e)),children:`×`})]},e))}),(0,m.jsx)(`input`,{className:`ui-input h-9 rounded-md border border-edge bg-surface-base px-2.5 text-sm`,disabled:r,placeholder:`Add and press Enter`,onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),o(e.target.value),e.target.value=``)}})]})}function T({k:e,sub:t,value:n,onValue:r,disabled:i}){let a=t.type,o=(typeof t.title==`string`&&t.title.length>0?t.title:null)??e;if(a===`boolean`)return(0,m.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,m.jsx)(`p`,{className:`text-sm font-medium text-fg`,children:o}),(0,m.jsx)(C,{s:t,value:n===!0,disabled:i,onChange:e=>r(e)})]});if(a===`number`||a===`integer`)return(0,m.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,m.jsx)(`p`,{className:`text-sm font-medium text-fg`,children:o}),(0,m.jsx)(S,{s:t,value:typeof n==`number`?n:0,disabled:i,onChange:r})]});if(a===`string`)return(0,m.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,m.jsx)(`p`,{className:`text-sm font-medium text-fg`,children:o}),(0,m.jsx)(x,{name:e,s:t,value:typeof n==`string`?n:``,disabled:i,onChange:r})]});if(a===`array`){let e=t.items;if(h(e)&&e.type===`string`)return(0,m.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,m.jsx)(`p`,{className:`text-sm font-medium text-fg`,children:o}),(0,m.jsx)(w,{s:t,value:Array.isArray(n)&&n.every(e=>typeof e==`string`)?n:[],disabled:i,onChange:r})]})}return(0,m.jsxs)(`p`,{className:`text-xs text-fg-muted`,children:[o,`: unsupported field type`,typeof a==`string`?` (${a})`:``]})}function E({schema:e,values:t,onChange:n,disabled:r=!1,className:a}){let o=(0,p.useMemo)(()=>e.type===`object`?y(e):[],[e]),s=(0,p.useMemo)(()=>o.length===0?new Map:b(o),[o]),c=(0,p.useCallback)((e,r)=>{n({...t,[e]:r})},[n,t]);if(e.type!==`object`||!h(e.properties)||o.length===0)return null;let l=Array.from(s.keys()).sort((e,t)=>e===``?-1:t===``?1:e.localeCompare(t));return(0,m.jsx)(`div`,{className:i(`flex flex-col gap-4`,a),children:l.map(e=>{let n=(s.get(e)??[]).map(e=>(0,m.jsx)(T,{k:e.key,sub:e.sub,value:t[e.key],onValue:t=>c(e.key,t),disabled:r},e.key));return e===``?(0,m.jsx)(`div`,{children:n},`default`):(0,m.jsxs)(`details`,{className:`group rounded-lg border border-edge bg-surface-panel/40 open:bg-surface-base`,open:!0,children:[(0,m.jsx)(`summary`,{className:`cursor-pointer select-none px-3 py-2 text-sm font-medium text-fg group-open:rounded-b-none`,children:e}),(0,m.jsx)(`div`,{className:`space-y-4 border-t border-edge p-3`,children:n})]},e)})})}function D(e){let t={};if(e.type!==`object`||!h(e.properties))return t;for(let[n,r]of Object.entries(e.properties))h(r)&&Object.prototype.hasOwnProperty.call(r,`default`)&&(t[n]=r.default);return t}function O({extensionId:e}){let t=u(e=>!!e.token),{data:n,error:i}=r(t&&e?`ext-detail-${e}`:null,()=>o(c(`/api/extensions/${encodeURIComponent(e)}`))),{data:a,mutate:s,error:f}=r(t&&e?`ext-cfg-${e}`:null,()=>o(c(`/api/extensions/${encodeURIComponent(e)}/config`))),h=n?.manifest?.configSchema,g=(0,p.useMemo)(()=>h&&h.type===`object`?D(h):{},[h]),_=(0,p.useMemo)(()=>({...g,...a??{}}),[g,a]),[v,y]=(0,p.useState)({}),[b,x]=(0,p.useState)(!1),[S,C]=(0,p.useState)(!1),[w,T]=(0,p.useState)(null),[O,k]=(0,p.useState)(!1);(0,p.useEffect)(()=>{b||y(_)},[b,_]);let A=(0,p.useCallback)(e=>{y(e),x(!0),T(null)},[]),j=(0,p.useCallback)(()=>{y(_),x(!1),T(null)},[_]),M=(0,p.useCallback)(()=>{!h||h.type!==`object`||(y({...D(h)}),x(!0),T(null))},[h]),N=(0,p.useCallback)(async()=>{if(e){C(!0),T(null);try{let t=await l(c(`/api/extensions/${encodeURIComponent(e)}/config`),{method:`PATCH`,body:JSON.stringify(v)});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.error?.message??t.statusText)}await s(v,!1),x(!1),k(!0),window.setTimeout(()=>k(!1),3e3)}catch(e){T(e instanceof Error?e.message:String(e))}finally{C(!1)}}},[e,v,s]);if(!t)return null;if(i||f){let e=i??f;return(0,m.jsxs)(`p`,{className:`text-sm text-fg-muted`,children:[`Could not load extension settings: `,e instanceof Error?e.message:String(e)]})}return!h||h.type!==`object`?null:(0,m.jsxs)(`div`,{className:`mb-6 flex flex-col gap-3 rounded-xl border border-edge bg-surface-base p-4`,children:[(0,m.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,m.jsx)(`h2`,{className:`text-sm font-semibold text-fg`,children:`Configuration`}),(0,m.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[O?(0,m.jsx)(`span`,{className:`text-xs text-emerald-600 dark:text-emerald-400`,children:`Saved`}):null,w?(0,m.jsx)(`span`,{className:`text-xs text-red-600 dark:text-red-400`,children:w}):null,(0,m.jsx)(d,{type:`button`,variant:`ghost`,className:`h-8 text-xs`,disabled:!b,onClick:j,children:`Discard`}),(0,m.jsx)(d,{type:`button`,variant:`ghost`,className:`h-8 text-xs`,onClick:M,children:`Reset to defaults`}),(0,m.jsx)(d,{type:`button`,variant:`primary`,className:`h-8 text-xs`,disabled:!b||S,onClick:()=>void N(),children:S?`Saving…`:`Save`})]})]}),(0,m.jsx)(E,{schema:h,values:v,onChange:A,disabled:S})]})}function k(){let{extensionId:e,panelId:t}=s(),n=a();if(!e)return(0,m.jsx)(A,{message:`No extension ID provided.`});let r=n.find(t=>t.id===e);if(!r)return(0,m.jsx)(A,{message:`Extension "${e}" not found or is not available in this workspace.`});let i=r.ui?.contributions?.settingsPanels,o=t?i?.find(n=>n.id===t||n.id===`${e}.${t}`):i?.[0],c=!!(o&&r.ui);return!r.hasConfigSchema&&!c?(0,m.jsx)(A,{message:`Extension "${e}" has no settings panels or config schema.`}):(0,m.jsxs)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8`,children:[(0,m.jsx)(`h1`,{className:`text-lg font-semibold text-fg`,children:o?.title??`${r.name} Settings`}),(0,m.jsx)(O,{extensionId:e}),c&&o&&r.ui?(0,m.jsx)(`div`,{className:`overflow-hidden rounded-xl border border-edge bg-surface-base`,children:(0,m.jsx)(f,{extensionId:e,extensionName:r.name,entrypoint:o.entrypoint,permissions:r.ui?.permissions,title:o.title,className:`w-full`,minHeight:120,maxHeight:2e3})}):null]})}function A({message:e}){return(0,m.jsx)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8`,children:(0,m.jsx)(`p`,{className:`text-sm text-fg-muted`,children:e})})}export{k as ExtensionSettingsPage};
2
+ //# sourceMappingURL=extension-settings-page-CP9JNc4m.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-settings-page-CP9JNc4m.js","names":[],"sources":["../../../../../web/src/components/ui/schema-form.tsx","../../../../../web/src/features/extensions/extension-auto-settings.tsx","../../../../../web/src/features/extensions/extension-settings-page.tsx"],"sourcesContent":["import { useCallback, useMemo } from 'react';\n\nimport { cn } from '@/lib/cn';\n\nexport type JsonSchema = Record<string, unknown>;\n\ntype SchemaFormProps = {\n schema: JsonSchema;\n values: Record<string, unknown>;\n onChange: (values: Record<string, unknown>) => void;\n disabled?: boolean;\n className?: string;\n};\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\ntype FieldDef = {\n key: string;\n sub: JsonSchema;\n order: number;\n group: string;\n hidden: boolean;\n};\n\nfunction getXOrder(s: JsonSchema): number {\n const v = s['x-order'];\n return typeof v === 'number' && !Number.isNaN(v) ? v : 999;\n}\n\nfunction getXGroup(s: JsonSchema): string {\n const v = s['x-group'];\n return typeof v === 'string' && v.length > 0 ? v : '';\n}\n\nfunction isHidden(s: JsonSchema): boolean {\n return s['x-hidden'] === true;\n}\n\nfunction sortedFields(schema: JsonSchema): FieldDef[] {\n const props = schema.properties;\n if (!isRecord(props)) return [];\n const out: FieldDef[] = [];\n for (const [key, sub] of Object.entries(props)) {\n if (!isRecord(sub)) continue;\n if (isHidden(sub)) continue;\n out.push({\n key,\n sub: sub as JsonSchema,\n order: getXOrder(sub as JsonSchema),\n group: getXGroup(sub as JsonSchema),\n hidden: false,\n });\n }\n out.sort((a, b) => a.order - b.order || a.key.localeCompare(b.key));\n return out;\n}\n\nfunction groupFields(fields: FieldDef[]): Map<string, FieldDef[]> {\n const m = new Map<string, FieldDef[]>();\n for (const f of fields) {\n const g = f.group;\n if (!m.has(g)) m.set(g, []);\n m.get(g)!.push(f);\n }\n return m;\n}\n\nfunction StringField({\n name,\n s,\n value,\n onChange,\n disabled,\n}: {\n name: string;\n s: JsonSchema;\n value: string;\n onChange: (v: string) => void;\n disabled: boolean;\n}) {\n const desc = typeof s.description === 'string' ? s.description : undefined;\n const placeholder =\n (typeof s['x-placeholder'] === 'string' ? s['x-placeholder'] : null) || desc;\n const fmt = s.format;\n if (Array.isArray(s.enum) && s.enum.every((x) => typeof x === 'string')) {\n return (\n <div className=\"flex flex-col gap-1.5\">\n {desc ? <label className=\"text-xs text-fg-muted\">{desc}</label> : null}\n <select\n name={name}\n className=\"ui-input h-9 rounded-md border border-edge bg-surface-base px-2 text-sm text-fg\"\n value={value}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value)}\n >\n {(s.enum as string[]).map((op) => (\n <option key={op} value={op}>\n {op}\n </option>\n ))}\n </select>\n </div>\n );\n }\n const inputType = fmt === 'password' ? 'password' : 'text';\n return (\n <div className=\"flex flex-col gap-1.5\">\n {desc ? <label className=\"text-xs text-fg-muted\">{desc}</label> : null}\n <input\n name={name}\n type={inputType}\n className=\"ui-input h-9 rounded-md border border-edge bg-surface-base px-2.5 text-sm text-fg placeholder:text-fg-muted/70\"\n value={value}\n placeholder={placeholder}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value)}\n />\n </div>\n );\n}\n\nfunction NumberField({\n s,\n value,\n onChange,\n disabled,\n}: {\n s: JsonSchema;\n value: number;\n onChange: (v: number) => void;\n disabled: boolean;\n}) {\n const desc = typeof s.description === 'string' ? s.description : undefined;\n return (\n <div className=\"flex flex-col gap-1.5\">\n {desc ? <label className=\"text-xs text-fg-muted\">{desc}</label> : null}\n <input\n type=\"number\"\n className=\"ui-input h-9 rounded-md border border-edge bg-surface-base px-2.5 text-sm text-fg\"\n value={Number.isFinite(value) ? value : 0}\n disabled={disabled}\n onChange={(e) => onChange(Number(e.target.value))}\n />\n </div>\n );\n}\n\nfunction BooleanField({\n s,\n value,\n onChange,\n disabled,\n}: {\n s: JsonSchema;\n value: boolean;\n onChange: (v: boolean) => void;\n disabled: boolean;\n}) {\n const desc = typeof s.description === 'string' ? s.description : undefined;\n const labelText =\n desc ?? (typeof s.title === 'string' && s.title.length > 0 ? s.title : 'Enable');\n return (\n <label className=\"flex items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"h-4 w-4 rounded border border-edge\"\n checked={value}\n disabled={disabled}\n onChange={(e) => onChange(e.target.checked)}\n />\n <span>{labelText}</span>\n </label>\n );\n}\n\nfunction ArrayStringField({\n s,\n value,\n onChange,\n disabled,\n}: {\n s: JsonSchema;\n value: string[];\n onChange: (v: string[]) => void;\n disabled: boolean;\n}) {\n const desc = typeof s.description === 'string' ? s.description : undefined;\n const items = s.items;\n const isStringItems = isRecord(items) && items.type === 'string';\n if (!isStringItems) {\n return <p className=\"text-xs text-fg-muted\">Unsupported array type</p>;\n }\n const add = (t: string) => {\n const n = t.trim();\n if (!n || value.includes(n)) return;\n onChange([...value, n]);\n };\n return (\n <div className=\"flex flex-col gap-1.5\">\n {desc ? <label className=\"text-xs text-fg-muted\">{desc}</label> : null}\n <div className=\"flex flex-wrap gap-1\">\n {value.map((t) => (\n <span\n key={t}\n className=\"inline-flex items-center gap-1 rounded-md border border-edge bg-surface-panel px-2 py-0.5 text-sm\"\n >\n {t}\n <button\n type=\"button\"\n className=\"text-fg-muted hover:text-fg\"\n disabled={disabled}\n onClick={() => onChange(value.filter((x) => x !== t))}\n >\n ×\n </button>\n </span>\n ))}\n </div>\n <input\n className=\"ui-input h-9 rounded-md border border-edge bg-surface-base px-2.5 text-sm\"\n disabled={disabled}\n placeholder=\"Add and press Enter\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n add((e.target as HTMLInputElement).value);\n (e.target as HTMLInputElement).value = '';\n }\n }}\n />\n </div>\n );\n}\n\nfunction FieldRow({\n k,\n sub,\n value,\n onValue,\n disabled,\n}: {\n k: string;\n sub: JsonSchema;\n value: unknown;\n onValue: (next: unknown) => void;\n disabled: boolean;\n}) {\n const t = sub.type;\n const title =\n (typeof sub.title === 'string' && sub.title.length > 0 ? sub.title : null) ?? k;\n if (t === 'boolean') {\n return (\n <div className=\"space-y-1.5\">\n <p className=\"text-sm font-medium text-fg\">{title}</p>\n <BooleanField\n s={sub}\n value={value === true}\n disabled={disabled}\n onChange={(b) => onValue(b)}\n />\n </div>\n );\n }\n if (t === 'number' || t === 'integer') {\n return (\n <div className=\"space-y-1.5\">\n <p className=\"text-sm font-medium text-fg\">{title}</p>\n <NumberField\n s={sub}\n value={typeof value === 'number' ? value : 0}\n disabled={disabled}\n onChange={onValue}\n />\n </div>\n );\n }\n if (t === 'string') {\n return (\n <div className=\"space-y-1.5\">\n <p className=\"text-sm font-medium text-fg\">{title}</p>\n <StringField\n name={k}\n s={sub}\n value={typeof value === 'string' ? value : ''}\n disabled={disabled}\n onChange={onValue}\n />\n </div>\n );\n }\n if (t === 'array') {\n const items = sub.items;\n if (isRecord(items) && items.type === 'string') {\n return (\n <div className=\"space-y-1.5\">\n <p className=\"text-sm font-medium text-fg\">{title}</p>\n <ArrayStringField\n s={sub}\n value={Array.isArray(value) && value.every((x) => typeof x === 'string') ? value : []}\n disabled={disabled}\n onChange={onValue}\n />\n </div>\n );\n }\n }\n return (\n <p className=\"text-xs text-fg-muted\">\n {title}: unsupported field type\n {typeof t === 'string' ? ` (${t})` : ''}\n </p>\n );\n}\n\n/**\n * Renders a JSON Schema (type: object) as a form using Gateway Console design tokens.\n */\nexport function SchemaForm({ schema, values, onChange, disabled = false, className }: SchemaFormProps) {\n const fields = useMemo(() => {\n if (schema.type !== 'object') return [];\n return sortedFields(schema);\n }, [schema]);\n\n const grouped = useMemo(() => {\n if (fields.length === 0) return new Map<string, FieldDef[]>();\n return groupFields(fields);\n }, [fields]);\n\n const setKey = useCallback(\n (key: string, next: unknown) => {\n onChange({ ...values, [key]: next });\n },\n [onChange, values],\n );\n\n if (schema.type !== 'object' || !isRecord(schema.properties) || fields.length === 0) {\n return null;\n }\n\n const groupKeys = Array.from(grouped.keys()).sort((a, b) => {\n if (a === '') return -1;\n if (b === '') return 1;\n return a.localeCompare(b);\n });\n\n return (\n <div className={cn('flex flex-col gap-4', className)}>\n {groupKeys.map((gk) => {\n const list = grouped.get(gk) ?? [];\n const block = list.map((f) => (\n <FieldRow\n key={f.key}\n k={f.key}\n sub={f.sub}\n value={values[f.key]}\n onValue={(v) => setKey(f.key, v)}\n disabled={disabled}\n />\n ));\n if (gk === '') {\n return <div key=\"default\">{block}</div>;\n }\n return (\n <details\n key={gk}\n className=\"group rounded-lg border border-edge bg-surface-panel/40 open:bg-surface-base\"\n open\n >\n <summary className=\"cursor-pointer select-none px-3 py-2 text-sm font-medium text-fg group-open:rounded-b-none\">\n {gk}\n </summary>\n <div className=\"space-y-4 border-t border-edge p-3\">{block}</div>\n </details>\n );\n })}\n </div>\n );\n}\n\n/** Extract per-key defaults from a JSON object schema for \"Reset\" actions. */\nexport function extractObjectDefaults(\n schema: JsonSchema,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (schema.type !== 'object' || !isRecord(schema.properties)) {\n return out;\n }\n for (const [k, sub] of Object.entries(schema.properties)) {\n if (!isRecord(sub)) continue;\n if (Object.prototype.hasOwnProperty.call(sub, 'default')) {\n out[k] = sub.default;\n }\n }\n return out;\n}\n","import { useCallback, useEffect, useMemo, useState } from 'react';\nimport useSWR from 'swr';\n\nimport { Button } from '@/components/ui/button';\nimport { extractObjectDefaults, SchemaForm, type JsonSchema } from '@/components/ui/schema-form';\nimport { apiFetch, fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\nimport { useGatewayStore } from '@/stores/gateway-store';\n\ntype ExtensionDetailResponse = {\n manifest: { configSchema?: JsonSchema };\n};\n\nexport function ExtensionAutoSettings({ extensionId }: { extensionId: string }) {\n const hasToken = useGatewayStore((s) => Boolean(s.token));\n const { data: detail, error: detailError } = useSWR(\n hasToken && extensionId ? `ext-detail-${extensionId}` : null,\n () => fetchJson<ExtensionDetailResponse>(apiUrl(`/api/extensions/${encodeURIComponent(extensionId)}`)),\n );\n\n const { data: remoteConfig, mutate: mutateConfig, error: configError } = useSWR(\n hasToken && extensionId ? `ext-cfg-${extensionId}` : null,\n () =>\n fetchJson<Record<string, unknown>>(\n apiUrl(`/api/extensions/${encodeURIComponent(extensionId)}/config`),\n ),\n );\n\n const schema = detail?.manifest?.configSchema;\n const defaults = useMemo(\n () => (schema && schema.type === 'object' ? extractObjectDefaults(schema) : {}),\n [schema],\n );\n\n const savedValues = useMemo(\n () => ({ ...defaults, ...(remoteConfig ?? {}) }),\n [defaults, remoteConfig],\n );\n\n const [localValues, setLocalValues] = useState<Record<string, unknown>>({});\n const [isDirty, setIsDirty] = useState(false);\n const [saving, setSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n const [saveSuccess, setSaveSuccess] = useState(false);\n\n useEffect(() => {\n if (isDirty) return;\n setLocalValues(savedValues);\n }, [isDirty, savedValues]);\n\n const onChange = useCallback((next: Record<string, unknown>) => {\n setLocalValues(next);\n setIsDirty(true);\n setSaveError(null);\n }, []);\n\n const handleDiscard = useCallback(() => {\n setLocalValues(savedValues);\n setIsDirty(false);\n setSaveError(null);\n }, [savedValues]);\n\n const handleResetDefaults = useCallback(() => {\n if (!schema || schema.type !== 'object') return;\n setLocalValues({ ...extractObjectDefaults(schema) });\n setIsDirty(true);\n setSaveError(null);\n }, [schema]);\n\n const handleSave = useCallback(async () => {\n if (!extensionId) return;\n setSaving(true);\n setSaveError(null);\n try {\n const res = await apiFetch(\n apiUrl(`/api/extensions/${encodeURIComponent(extensionId)}/config`),\n { method: 'PATCH', body: JSON.stringify(localValues) },\n );\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: { message?: string } };\n throw new Error(body.error?.message ?? res.statusText);\n }\n await mutateConfig(localValues, false);\n setIsDirty(false);\n setSaveSuccess(true);\n window.setTimeout(() => setSaveSuccess(false), 3000);\n } catch (e) {\n setSaveError(e instanceof Error ? e.message : String(e));\n } finally {\n setSaving(false);\n }\n }, [extensionId, localValues, mutateConfig]);\n\n if (!hasToken) {\n return null;\n }\n\n if (detailError || configError) {\n const err = (detailError ?? configError) as Error;\n return (\n <p className=\"text-sm text-fg-muted\">\n Could not load extension settings: {err instanceof Error ? err.message : String(err)}\n </p>\n );\n }\n\n if (!schema || schema.type !== 'object') {\n return null;\n }\n\n return (\n <div className=\"mb-6 flex flex-col gap-3 rounded-xl border border-edge bg-surface-base p-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-sm font-semibold text-fg\">Configuration</h2>\n <div className=\"flex flex-wrap items-center gap-2\">\n {saveSuccess ? (\n <span className=\"text-xs text-emerald-600 dark:text-emerald-400\">Saved</span>\n ) : null}\n {saveError ? <span className=\"text-xs text-red-600 dark:text-red-400\">{saveError}</span> : null}\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-8 text-xs\"\n disabled={!isDirty}\n onClick={handleDiscard}\n >\n Discard\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-8 text-xs\"\n onClick={handleResetDefaults}\n >\n Reset to defaults\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n className=\"h-8 text-xs\"\n disabled={!isDirty || saving}\n onClick={() => void handleSave()}\n >\n {saving ? 'Saving…' : 'Save'}\n </Button>\n </div>\n </div>\n <SchemaForm schema={schema} values={localValues} onChange={onChange} disabled={saving} />\n </div>\n );\n}\n","/**\n * Extension settings: auto-generated config form (configSchema) + optional iframe (settingsPanels).\n *\n * Routes: /settings/ext/:extensionId, /settings/ext/:extensionId/:panelId\n */\n\nimport { useParams } from 'react-router-dom';\n\nimport { ExtensionAutoSettings } from './extension-auto-settings';\nimport { ExtensionIframeHost } from './extension-iframe-host';\nimport { useExtensions } from './extension-provider';\n\nexport function ExtensionSettingsPage() {\n const { extensionId, panelId } = useParams<{ extensionId: string; panelId?: string }>();\n const extensions = useExtensions();\n\n if (!extensionId) {\n return <SettingsPanelNotFound message=\"No extension ID provided.\" />;\n }\n\n const extension = extensions.find((ext) => ext.id === extensionId);\n if (!extension) {\n return (\n <SettingsPanelNotFound\n message={`Extension \"${extensionId}\" not found or is not available in this workspace.`}\n />\n );\n }\n\n const panels = extension.ui?.contributions?.settingsPanels;\n const panel = panelId\n ? panels?.find((p) => p.id === panelId || p.id === `${extensionId}.${panelId}`)\n : panels?.[0];\n\n const hasIframe = Boolean(panel && extension.ui);\n const hasAuto = Boolean(extension.hasConfigSchema);\n\n if (!hasAuto && !hasIframe) {\n return (\n <SettingsPanelNotFound\n message={`Extension \"${extensionId}\" has no settings panels or config schema.`}\n />\n );\n }\n\n const title = panel?.title ?? `${extension.name} Settings`;\n\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8\">\n <h1 className=\"text-lg font-semibold text-fg\">{title}</h1>\n <ExtensionAutoSettings extensionId={extensionId} />\n {hasIframe && panel && extension.ui ? (\n <div className=\"overflow-hidden rounded-xl border border-edge bg-surface-base\">\n <ExtensionIframeHost\n extensionId={extensionId}\n extensionName={extension.name}\n entrypoint={panel.entrypoint}\n permissions={extension.ui?.permissions}\n title={panel.title}\n className=\"w-full\"\n minHeight={120}\n maxHeight={2000}\n />\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction SettingsPanelNotFound({ message }: { message: string }) {\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8\">\n <p className=\"text-sm text-fg-muted\">{message}</p>\n </div>\n );\n}\n"],"mappings":"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"}