@xopcai/xopc 0.0.102 → 0.0.103

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 (123) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/transport/webhook/monitor.js +2 -2
  5. package/dist/extensions/feishu/src/transport/webhook/monitor.js.map +1 -1
  6. package/dist/extensions/telegram/src/send-options.js +8 -5
  7. package/dist/extensions/telegram/src/send-options.js.map +1 -1
  8. package/dist/extensions/telegram/xopc.extension.json +1 -1
  9. package/dist/gateway/static/root/assets/{agents-DQ0mQxIA.js → agents-BwXkia_W.js} +1 -1
  10. package/dist/gateway/static/root/assets/{apps-page-Uv4kOmDE.js → apps-page-C5RmwmTT.js} +1 -1
  11. package/dist/gateway/static/root/assets/{channels-settings-BEtP53V6.js → channels-settings-tlOTdaXw.js} +1 -1
  12. package/dist/gateway/static/root/assets/{channels-status-swr-CxTtS1hI.js → channels-status-swr-D4XjqwqC.js} +1 -1
  13. package/dist/gateway/static/root/assets/{cron-api-CznlPIZT.js → cron-api-DcmfGuj0.js} +1 -1
  14. package/dist/gateway/static/root/assets/{cron-page-Dx6dE3eD.js → cron-page-CijJ4G6F.js} +1 -1
  15. package/dist/gateway/static/root/assets/{dist-DH4IuRV0.js → dist-CWm8hTXZ.js} +1 -1
  16. package/dist/gateway/static/root/assets/{extension-debug-page-BNkhvRQW.js → extension-debug-page-BzYgTkS9.js} +1 -1
  17. package/dist/gateway/static/root/assets/{extension-page-CcIGQah2.js → extension-page-BmTZH6gL.js} +1 -1
  18. package/dist/gateway/static/root/assets/{extension-settings-page-DuDCSb3J.js → extension-settings-page-CyJk_G64.js} +1 -1
  19. package/dist/gateway/static/root/assets/{fetch-drJUxxKP.js → fetch-CMoWY2Si.js} +1 -1
  20. package/dist/gateway/static/root/assets/{field-primitives-BUwUiDf5.js → field-primitives-C4GpxsDo.js} +1 -1
  21. package/dist/gateway/static/root/assets/{heartbeat-config-api-BjFW1cl-.js → heartbeat-config-api-CLD0Gpi3.js} +1 -1
  22. package/dist/gateway/static/root/assets/index-0HmunJW9.js +4845 -0
  23. package/dist/gateway/static/root/assets/index-Bk75Phrd.css +1 -0
  24. package/dist/gateway/static/root/assets/{logs-page-CiG0m81R.js → logs-page-BjdQjHwk.js} +1 -1
  25. package/dist/gateway/static/root/assets/{note-detail-page-DG3DVFTf.js → note-detail-page-8Er4197b.js} +1 -1
  26. package/dist/gateway/static/root/assets/{note-time-DjlllCF3.js → note-time-CF3vf1jm.js} +1 -1
  27. package/dist/gateway/static/root/assets/{notes-page-D40ZpS0Y.js → notes-page-BBnTh0uI.js} +1 -1
  28. package/dist/gateway/static/root/assets/{sessions-page-BvtdbmW8.js → sessions-page-B0riYK7j.js} +1 -1
  29. package/dist/gateway/static/root/assets/{settings-advanced-gate-BQamRjkV.js → settings-advanced-gate-DiP_WHu_.js} +1 -1
  30. package/dist/gateway/static/root/assets/{settings-form-section-C3_sEFfD.js → settings-form-section-C7qA7y0J.js} +1 -1
  31. package/dist/gateway/static/root/assets/{settings-page-D972_jaS.js → settings-page-1ZPhcCZ9.js} +2 -2
  32. package/dist/gateway/static/root/assets/share-preview-page-Tvr5Mtq5.js +2 -0
  33. package/dist/gateway/static/root/assets/{skills-page-QwFCB4yV.js → skills-page-BQ1hllKD.js} +1 -1
  34. package/dist/gateway/static/root/assets/{theme-store-B6KXPHgK.js → theme-store-HTvJlFLL.js} +1 -1
  35. package/dist/gateway/static/root/assets/url-F3_D_6zZ.js +3 -0
  36. package/dist/gateway/static/root/assets/{utils-DCm11_KW.js → utils-CPr3FBh2.js} +1 -1
  37. package/dist/gateway/static/root/assets/{voice-api-key-field-CywiB7Dw.js → voice-api-key-field-BkbDl6dH.js} +1 -1
  38. package/dist/gateway/static/root/assets/{workflow-page.utils-g57BRfEd.js → workflow-page.utils-CeBkAjP7.js} +1 -1
  39. package/dist/gateway/static/root/assets/{workflows-page-Be7l_SWw.js → workflows-page-D059ysoF.js} +1 -1
  40. package/dist/gateway/static/root/index.html +5 -5
  41. package/dist/package.js +1 -1
  42. package/dist/src/agent/inbound/attachment-pipeline.js +2 -2
  43. package/dist/src/agent/inbound/attachment-pipeline.js.map +1 -1
  44. package/dist/src/agent/tools/send-media.js +1 -2
  45. package/dist/src/agent/tools/send-media.js.map +1 -1
  46. package/dist/src/auth/credentials.d.ts +7 -0
  47. package/dist/src/auth/credentials.js +35 -2
  48. package/dist/src/auth/credentials.js.map +1 -1
  49. package/dist/src/auth/index.d.ts +1 -1
  50. package/dist/src/auth/index.js.map +1 -1
  51. package/dist/src/auth/oauth/github-copilot.d.ts +1 -1
  52. package/dist/src/auth/oauth/google-antigravity.d.ts +1 -3
  53. package/dist/src/auth/oauth/google-antigravity.js +1 -1
  54. package/dist/src/auth/oauth/google-gemini-cli.d.ts +1 -3
  55. package/dist/src/auth/oauth/google-gemini-cli.js +1 -1
  56. package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-antigravity.js +3 -5
  57. package/dist/src/auth/oauth/google-oauth/google-antigravity.js.map +1 -0
  58. package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-gemini-cli.js +4 -5
  59. package/dist/src/auth/oauth/google-oauth/google-gemini-cli.js.map +1 -0
  60. package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/oauth-page.js +12 -4
  61. package/dist/src/auth/oauth/google-oauth/oauth-page.js.map +1 -0
  62. package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/pkce.d.ts +1 -1
  63. package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/pkce.js +2 -2
  64. package/dist/src/auth/oauth/google-oauth/pkce.js.map +1 -0
  65. package/dist/src/auth/oauth/index.js +2 -2
  66. package/dist/src/auth/oauth/kimi-coding.d.ts +1 -1
  67. package/dist/src/auth/oauth/kimi-coding.js +1 -1
  68. package/dist/src/auth/oauth/kimi-coding.js.map +1 -1
  69. package/dist/src/auth/oauth/minimax-cn.js +1 -1
  70. package/dist/src/auth/oauth/minimax-cn.js.map +1 -1
  71. package/dist/src/auth/oauth/minimax.js +1 -1
  72. package/dist/src/auth/oauth/minimax.js.map +1 -1
  73. package/dist/src/auth/oauth/openai-codex.d.ts +7 -2
  74. package/dist/src/auth/oauth/openai-codex.js +318 -1
  75. package/dist/src/auth/oauth/openai-codex.js.map +1 -0
  76. package/dist/src/auth/profiles/store.js +3 -2
  77. package/dist/src/auth/profiles/store.js.map +1 -1
  78. package/dist/src/channels/attachments/attachment-classifiers.d.ts +1 -0
  79. package/dist/src/channels/attachments/attachment-classifiers.js +13 -2
  80. package/dist/src/channels/attachments/attachment-classifiers.js.map +1 -1
  81. package/dist/src/chat-commands/builtins/model.js +2 -2
  82. package/dist/src/chat-commands/builtins/model.js.map +1 -1
  83. package/dist/src/cli/command-manifest.js +1 -1
  84. package/dist/src/cli/command-manifest.js.map +1 -1
  85. package/dist/src/cli/commands/auth.js +39 -51
  86. package/dist/src/cli/commands/auth.js.map +1 -1
  87. package/dist/src/cli/commands/models.js +189 -54
  88. package/dist/src/cli/commands/models.js.map +1 -1
  89. package/dist/src/cli/commands/onboard/model.d.ts +1 -4
  90. package/dist/src/cli/commands/onboard/model.js +253 -183
  91. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  92. package/dist/src/cli/utils/oauth-login.d.ts +17 -0
  93. package/dist/src/cli/utils/oauth-login.js +93 -0
  94. package/dist/src/cli/utils/oauth-login.js.map +1 -0
  95. package/dist/src/cli/utils/oauth-providers.js +2 -2
  96. package/dist/src/gateway/heartbeat/service.js +1 -1
  97. package/dist/src/gateway/hono/oauth-async.js +2 -2
  98. package/dist/src/gateway/hono/oauth.js +2 -2
  99. package/dist/src/gateway/hono/routes/models.js +25 -5
  100. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  101. package/dist/src/heartbeat/index.js +1 -1
  102. package/dist/src/media/store.js +3 -0
  103. package/dist/src/media/store.js.map +1 -1
  104. package/dist/src/notes/service.js +1 -1
  105. package/dist/src/notes/service.js.map +1 -1
  106. package/dist/src/providers/index.d.ts +3 -3
  107. package/dist/src/providers/index.js +23 -15
  108. package/dist/src/providers/index.js.map +1 -1
  109. package/dist/src/providers/presentation.d.ts +34 -0
  110. package/dist/src/providers/presentation.js +162 -0
  111. package/dist/src/providers/presentation.js.map +1 -0
  112. package/package.json +1 -1
  113. package/dist/gateway/static/root/assets/index-DKgHC1Ta.js +0 -4840
  114. package/dist/gateway/static/root/assets/index-DjNDHzwG.css +0 -1
  115. package/dist/gateway/static/root/assets/share-preview-page-CKCTMo0_.js +0 -2
  116. package/dist/gateway/static/root/assets/url-q28QhI7l.js +0 -3
  117. package/dist/src/auth/oauth/vendor-pi-google/google-antigravity.js.map +0 -1
  118. package/dist/src/auth/oauth/vendor-pi-google/google-gemini-cli.js.map +0 -1
  119. package/dist/src/auth/oauth/vendor-pi-google/oauth-page.js.map +0 -1
  120. package/dist/src/auth/oauth/vendor-pi-google/pkce.js.map +0 -1
  121. /package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-antigravity.d.ts +0 -0
  122. /package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-gemini-cli.d.ts +0 -0
  123. /package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/oauth-page.d.ts +0 -0
@@ -1 +1 @@
1
- import{ci as e,di as t,li as n,oi as r}from"./index-DKgHC1Ta.js";function i(){return t(`w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-sm text-fg`,`placeholder:text-fg-subtle`,n,`dark:border-edge`)}function a(){return t(e,r)}function o(e){return e.split(/[,\n]/).flatMap(e=>{let t=e.trim();return t?[/^-?\d+$/.test(t)?Number(t):t]:[]})}function s(e){return e.map(String).join(`, `)}function c(e){let t=e.accounts?.default?.botToken;return typeof t==`string`?t:``}function l(e){return Object.values(e.accounts??{}).some(e=>typeof e.botToken==`string`&&e.botToken.trim().length>0)}function u(e){return Object.keys(e.accounts??{}).length>0||e.allowFrom.length>0}function d(e){return!!(e.appId?.trim()&&e.appSecret?.trim())||Object.keys(e.accounts??{}).length>0}export{u as a,c,l as i,a as n,s as o,d as r,o as s,i as t};
1
+ import{ci as e,di as t,li as n,oi as r}from"./index-0HmunJW9.js";function i(){return t(`w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-sm text-fg`,`placeholder:text-fg-subtle`,n,`dark:border-edge`)}function a(){return t(e,r)}function o(e){return e.split(/[,\n]/).flatMap(e=>{let t=e.trim();return t?[/^-?\d+$/.test(t)?Number(t):t]:[]})}function s(e){return e.map(String).join(`, `)}function c(e){let t=e.accounts?.default?.botToken;return typeof t==`string`?t:``}function l(e){return Object.values(e.accounts??{}).some(e=>typeof e.botToken==`string`&&e.botToken.trim().length>0)}function u(e){return Object.keys(e.accounts??{}).length>0||e.allowFrom.length>0}function d(e){return!!(e.appId?.trim()&&e.appSecret?.trim())||Object.keys(e.accounts??{}).length>0}export{u as a,c,l as i,a as n,s as o,d as r,o as s,i as t};
@@ -1 +1 @@
1
- import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{a as t,n,t as r}from"./vendor-react-BOUWij0V.js";import{t as i}from"./url-q28QhI7l.js";import{o as a}from"./vendor-swr-BIWyz7Rc.js";import{a as o,n as s}from"./fetch-drJUxxKP.js";import{$i as c,Jo as l,Mo as u,Oa as d,Q as f,U as p,Z as m,Zr as h,di as g,dr as _,li as v,lo as y,ui as b,ur as x}from"./index-DKgHC1Ta.js";var S=`/api/image/providers`;async function C(){return(await s(i(`/api/image/providers`)))?.payload?.providers??[]}var w=e(t(),1),ee=n();function T(){return{apiKey:``,region:``,baseUrl:``,imageBaseUrl:``}}function te(e){return e?.apiKey?`••••••••••••`:``}function E(e,t){let n=(()=>{if(!e||typeof e!=`object`||!(`providersConfig`in e))return;let t=e.providersConfig;if(!(!t||typeof t!=`object`||Array.isArray(t)))return t})(),r={};for(let e of t){let t=n?.[e];r[e]={apiKey:te(t),region:t?.region??``,baseUrl:t?.baseUrl??``,imageBaseUrl:t?.imageBaseUrl??``}}return r}function D(e,t,n){let r=e[n].trim();if(r!==t[n].trim())return r||null}function O(e,t){let n=e.trim(),r=t.trim();if(n!==r&&!(p(n)&&p(r)))return n||(r?null:void 0)}function k(e,t,n){let r={};for(let i of e){let e=t[i]??T(),a=n[i]??T();if(JSON.stringify(e)===JSON.stringify(a))continue;let o={},s=O(e.apiKey,a.apiKey);s!==void 0&&(o.apiKey=s);let c=D(e,a,`region`);c!==void 0&&(o.region=c);let l=D(e,a,`baseUrl`);l!==void 0&&(o.baseUrl=l);let u=D(e,a,`imageBaseUrl`);u!==void 0&&(o.imageBaseUrl=u),Object.keys(o).length>0&&(r[i]=o)}return r}async function A(e){let t=await s(i(`/api/image/providers/${encodeURIComponent(e)}/reveal-api-key`),{method:`POST`,headers:{"Content-Type":`application/json`},body:`{}`});if(!t.ok||!t.payload)throw Error(t.error?.message??`Reveal failed`);return t.payload}async function j(e){Object.keys(e).length!==0&&(await s(i(`/api/config`),{method:`PATCH`,body:JSON.stringify({providersConfig:e})}),await x())}var M=r();function ne(e){let t=(0,ee.c)(18),{providerId:n,value:r,onChange:i,labels:a,apiKeyLinks:o,apiKeyLinkLabels:s}=e,c;t[0]===n?c=t[1]:(c=()=>A(n).then(N),t[0]=n,t[1]=c);let l=c,u=`img-cred-key-${n}`,d;t[2]!==a.apiKeyLabel||t[3]!==u?(d=(0,M.jsx)(`label`,{className:`text-xs font-medium text-fg-muted`,htmlFor:u,children:a.apiKeyLabel}),t[2]=a.apiKeyLabel,t[3]=u,t[4]=d):d=t[4];let p;t[5]!==s||t[6]!==o?(p=o.length>0?(0,M.jsx)(`div`,{className:`flex flex-col gap-1`,children:o.map(e=>(0,M.jsxs)(`a`,{href:e.href,target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex w-fit items-center gap-1 text-xs font-medium text-accent-fg hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,children:[f(e.kind,s),(0,M.jsx)(y,{className:`size-3`,"aria-hidden":!0})]},`${e.kind}-${e.href}`))}):null,t[5]=s,t[6]=o,t[7]=p):p=t[7];let m=`img-cred-key-${n}`,g;t[8]!==a||t[9]!==i||t[10]!==l||t[11]!==m||t[12]!==r?(g=(0,M.jsx)(h,{id:m,value:r,onChange:i,placeholder:a.optionalPlaceholder,labels:a,reveal:l,loadFailedLabel:a.loadFailed,maskedHelp:a.maskedHelp,notInConfigFile:a.notInConfigFile}),t[8]=a,t[9]=i,t[10]=l,t[11]=m,t[12]=r,t[13]=g):g=t[13];let _;return t[14]!==d||t[15]!==p||t[16]!==g?(_=(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1 sm:col-span-2`,children:[d,p,g]}),t[14]=d,t[15]=p,t[16]=g,t[17]=_):_=t[17],_}function N(e){return e.apiKey??null}function P(){return g(`w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-sm text-fg`,`placeholder:text-fg-subtle`,v)}function re(){return g(P(),`appearance-none bg-[length:1rem] bg-[right_0.5rem_center] bg-no-repeat pr-9`)}var F=`__custom__`;function ie(e,t){if(!e.region.trim()&&!e.imageBaseUrl.trim())return``;let n=e.region.trim().toLowerCase();return t.some(e=>e.value===n)?n:F}function ae(e,t){let n=e.baseUrl.trim().replace(/\/+$/,``);if(!n)return``;let r=t.map(e=>e.value.replace(/\/+$/,``)).indexOf(n);return r>=0?t[r].value:F}function oe(e,t,n){return t===`beijing`?e.dashscopeRegion_beijing:t===`singapore`?e.dashscopeRegion_singapore:t===`us`?e.dashscopeRegion_us:n}function se(e,t){return t===`minimax`?e.minimaxClusterLabel:t===`fal`?e.falQueueBaseLabel:e.baseUrlLabel}function ce(e,t){return t===`minimax`?e.minimaxClusterHint:t===`fal`?e.falQueueBaseHint:null}function le(e,t){return JSON.stringify(e)!==JSON.stringify(t)}function ue(e,t){return t===1?e.modelCountOne:e.modelCountMany.replace(`{count}`,String(t))}function I(e){let t=(0,ee.c)(76),{summaries:n,credDraft:r,credBaseline:i,credDirty:a,credSaving:o,credError:s,credSavedFlash:f,credNoopFlash:p,updateCredRow:h,onDiscardCredentials:_,onSaveCredentials:v,extensionIds:x,showExtensionLinks:S,showImageModelsLink:C,hideActions:te,language:E,apiKeyLinkLabels:D,messages:O}=e,k=te===void 0?!1:te,A;t[0]===n?A=t[1]:(A=n.some(he),t[0]=n,t[1]=A);let j=A,N;t[2]===n?N=t[3]:(N=n.some(me),t[2]=n,t[3]=N);let I=N,[ge,_e]=(0,w.useState)(pe),[ve,L]=(0,w.useState)(fe),R;if(t[4]!==i||t[5]!==r||t[6]!==n){R=new Set;for(let e of n)le(r[e.id]??T(),i[e.id]??T())&&R.add(e.id);t[4]=i,t[5]=r,t[6]=n,t[7]=R}else R=t[7];let z=R,B;t[8]!==z||t[9]!==ve||t[10]!==ge?(B=e=>ve.has(e)?!1:ge.has(e)?!0:z.has(e),t[8]=z,t[9]=ve,t[10]=ge,t[11]=B):B=t[11];let V=B,H;t[12]===V?H=t[13]:(H=e=>{if(V(e)){L(t=>new Set(t).add(e)),_e(t=>{let n=new Set(t);return n.delete(e),n});return}L(t=>{let n=new Set(t);return n.delete(e),n}),_e(t=>new Set(t).add(e))},t[12]=V,t[13]=H);let U=H;if(n.length===0)return null;let W;t[14]===O.credentialsIntro?W=t[15]:(W=(0,M.jsx)(`p`,{children:O.credentialsIntro}),t[14]=O.credentialsIntro,t[15]=W);let G;t[16]!==j||t[17]!==O.regionHint?(G=j?(0,M.jsx)(`p`,{className:`text-fg-subtle`,children:O.regionHint}):null,t[16]=j,t[17]=O.regionHint,t[18]=G):G=t[18];let K;t[19]!==I||t[20]!==O.endpointPresetsHint?(K=I?(0,M.jsx)(`p`,{className:`text-fg-subtle`,children:O.endpointPresetsHint}):null,t[19]=I,t[20]=O.endpointPresetsHint,t[21]=K):K=t[21];let q;t[22]!==C||t[23]!==O.imageModelsLinkTitle||t[24]!==O.openImageModelsPage?(q=C?(0,M.jsx)(`p`,{children:(0,M.jsx)(l,{to:`/settings/credentials?tab=image-models`,className:`font-medium text-accent hover:underline`,title:O.imageModelsLinkTitle,children:O.openImageModelsPage})}):null,t[22]=C,t[23]=O.imageModelsLinkTitle,t[24]=O.openImageModelsPage,t[25]=q):q=t[25];let J;t[26]!==W||t[27]!==G||t[28]!==K||t[29]!==q?(J=(0,M.jsxs)(`div`,{className:`flex flex-col gap-1 text-xs leading-relaxed text-fg-muted`,children:[W,G,K,q]}),t[26]=W,t[27]=G,t[28]=K,t[29]=q,t[30]=J):J=t[30];let Y;t[31]===s?Y=t[32]:(Y=s?(0,M.jsx)(`div`,{className:`rounded-lg border border-red-500/30 bg-red-500/10 px-3 py-2 text-sm text-red-700 dark:text-red-300`,children:s}):null,t[31]=s,t[32]=Y);let X;t[33]!==a||t[34]!==p||t[35]!==f||t[36]!==o||t[37]!==k||t[38]!==_||t[39]!==v||t[40]!==O.credentialsNothingToSave||t[41]!==O.credentialsSaved||t[42]!==O.discardCredentials||t[43]!==O.saveCredentials||t[44]!==O.savingCredentials?(X=k?null:(0,M.jsxs)(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[f?(0,M.jsx)(`span`,{className:`text-sm text-fg-muted`,children:O.credentialsSaved}):null,p?(0,M.jsx)(`span`,{className:`text-sm text-fg-muted`,children:O.credentialsNothingToSave}):null,(0,M.jsx)(b,{type:`button`,variant:`secondary`,onClick:_,disabled:!a||o,children:O.discardCredentials}),(0,M.jsx)(b,{type:`button`,variant:`primary`,onClick:v,disabled:!a||o,children:o?(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(d,{className:`size-3.5 animate-spin`}),(0,M.jsx)(`span`,{className:`ml-1.5`,children:O.savingCredentials})]}):(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(c,{className:`size-3.5`}),(0,M.jsx)(`span`,{className:`ml-1.5`,children:O.saveCredentials})]})})]}),t[33]=a,t[34]=p,t[35]=f,t[36]=o,t[37]=k,t[38]=_,t[39]=v,t[40]=O.credentialsNothingToSave,t[41]=O.credentialsSaved,t[42]=O.discardCredentials,t[43]=O.saveCredentials,t[44]=O.savingCredentials,t[45]=X):X=t[45];let Z;if(t[46]!==D||t[47]!==i||t[48]!==r||t[49]!==x||t[50]!==V||t[51]!==E||t[52]!==S||t[53]!==n||t[54]!==O||t[55]!==U||t[56]!==h){let e;t[58]!==D||t[59]!==i||t[60]!==r||t[61]!==x||t[62]!==V||t[63]!==E||t[64]!==S||t[65]!==O||t[66]!==U||t[67]!==h?(e=e=>{let t=r[e.id]??T(),n=e.ui,a=S&&x.has(e.id)?`/settings/ext/${encodeURIComponent(e.id)}`:null,o=le(t,i[e.id]??T()),s=V(e.id),c=e.label??e.id,d=ue(O,e.models.length);return(0,M.jsxs)(`section`,{className:g(`overflow-hidden rounded-xl border bg-surface-panel shadow-sm transition-colors dark:shadow-none`,o?`border-accent/50`:`border-edge`),children:[(0,M.jsxs)(`button`,{type:`button`,className:`flex w-full items-start justify-between gap-3 px-4 py-3 text-left hover:bg-surface-hover/70`,"aria-expanded":s,"aria-controls":`img-provider-credentials-${e.id}`,onClick:()=>U(e.id),children:[(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-2`,children:[(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-2`,children:[(0,M.jsx)(`span`,{className:`truncate text-sm font-semibold text-fg`,children:c}),(0,M.jsx)(`span`,{className:`rounded-full bg-surface-subtle px-2 py-0.5 text-[11px] font-medium text-fg-muted`,children:e.id}),o?(0,M.jsx)(`span`,{className:`rounded-full bg-accent-soft px-2 py-0.5 text-[11px] font-medium text-accent-fg`,children:O.unsavedChanges}):null,e.configured?(0,M.jsx)(`span`,{className:`rounded-full bg-accent-soft px-2 py-0.5 text-[11px] font-medium text-accent-fg`,children:O.configured}):(0,M.jsx)(`span`,{className:`rounded-full border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-[11px] font-medium text-amber-700 dark:text-amber-300`,children:O.missingKey})]}),(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1 text-xs text-fg-subtle`,children:[(0,M.jsx)(`span`,{children:d}),e.defaultModel?(0,M.jsxs)(`span`,{className:`min-w-0 truncate`,children:[(0,M.jsxs)(`span`,{className:`text-fg-muted`,children:[O.defaultModel,`:`]}),` `,e.id,`/`,e.defaultModel]}):null]})]}),(0,M.jsx)(u,{className:g(`mt-0.5 size-4 shrink-0 text-fg-subtle transition-transform`,s?`rotate-180`:`rotate-0`),"aria-hidden":`true`}),(0,M.jsx)(`span`,{className:`sr-only`,children:s?O.collapseProvider:O.expandProvider})]}),s?(0,M.jsxs)(`div`,{id:`img-provider-credentials-${e.id}`,className:`border-t border-edge px-4 py-4`,children:[a?(0,M.jsxs)(l,{to:a,className:`mb-3 inline-flex items-center gap-1 text-xs font-medium text-accent hover:underline`,title:O.extensionSettingsLinkTitle,children:[(0,M.jsx)(y,{className:`size-3`}),O.openExtensionSettings]}):null,e.models.length>0?(0,M.jsxs)(`p`,{className:`mb-3 text-xs leading-relaxed text-fg-subtle`,children:[(0,M.jsxs)(`span`,{className:`text-fg-muted`,children:[O.modelsLabel,`:`]}),` `,e.models.map(t=>`${e.id}/${t}`).join(`, `)]}):null,(0,M.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,M.jsx)(ne,{providerId:e.id,value:t.apiKey,onChange:t=>h(e.id,{apiKey:t}),apiKeyLinks:m(e.id,E),apiKeyLinkLabels:D,labels:{apiKeyLabel:O.apiKeyLabel,optionalPlaceholder:O.optionalPlaceholder,maskedHelp:O.apiKeyMaskedHelp,copy:O.apiKeyCopy,copied:O.apiKeyCopied,show:O.apiKeyShow,hide:O.apiKeyHide,notInConfigFile:O.apiKeyNotInConfigFile,loadFailed:O.apiKeyRevealFailed}}),n?.regions?.length?(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1 sm:col-span-2`,children:[(0,M.jsx)(`label`,{className:`text-xs font-medium text-fg-muted`,htmlFor:`img-cred-region-preset-${e.id}`,children:O.regionLabel}),(0,M.jsxs)(`select`,{id:`img-cred-region-preset-${e.id}`,className:re(),value:ie(t,n.regions),onChange:t=>{let r=t.target.value;if(r===``){h(e.id,{region:``,imageBaseUrl:``});return}if(r===F){h(e.id,{region:``,imageBaseUrl:``});return}let i=n.regions.find(e=>e.value===r);i&&h(e.id,{region:i.value,imageBaseUrl:i.imageBaseUrl})},children:[(0,M.jsx)(`option`,{value:``,children:O.regionPresetDefault}),n.regions.map(e=>(0,M.jsx)(`option`,{value:e.value,children:oe(O,e.value,e.label)},e.value)),(0,M.jsx)(`option`,{value:F,children:O.regionPresetCustom})]}),ie(t,n.regions)===F?(0,M.jsxs)(`div`,{className:`mt-2 grid gap-2 sm:grid-cols-2`,children:[(0,M.jsx)(`input`,{type:`text`,className:P(),value:t.region,placeholder:`region`,onChange:t=>h(e.id,{region:t.target.value})}),(0,M.jsx)(`input`,{type:`url`,className:P(),value:t.imageBaseUrl,placeholder:O.imageBaseUrlLabel,onChange:t=>h(e.id,{imageBaseUrl:t.target.value})})]}):null]}):null,n?.baseUrlPresets?.length?(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1 sm:col-span-2`,children:[(0,M.jsx)(`label`,{className:`text-xs font-medium text-fg-muted`,htmlFor:`img-cred-base-preset-${e.id}`,children:se(O,n.baseUrlPresetKind)}),ce(O,n.baseUrlPresetKind)?(0,M.jsx)(`p`,{className:`text-[11px] text-fg-subtle`,children:ce(O,n.baseUrlPresetKind)}):null,(0,M.jsxs)(`select`,{id:`img-cred-base-preset-${e.id}`,className:re(),value:ae(t,n.baseUrlPresets),onChange:t=>{let n=t.target.value;if(n===``){h(e.id,{baseUrl:``});return}if(n===F){h(e.id,{baseUrl:``});return}h(e.id,{baseUrl:n.replace(/\/+$/,``)})},children:[(0,M.jsx)(`option`,{value:``,children:O.baseUrlPresetDefault}),n.baseUrlPresets.map(de),(0,M.jsx)(`option`,{value:F,children:O.baseUrlPresetCustom})]}),ae(t,n.baseUrlPresets)===F?(0,M.jsx)(`input`,{type:`url`,className:g(P(),`mt-2`),value:t.baseUrl,placeholder:`https://…`,onChange:t=>h(e.id,{baseUrl:t.target.value})}):null]}):null,n?.regions?.length&&ie(t,n.regions)!==F?(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1 sm:col-span-2`,children:[(0,M.jsx)(`label`,{className:`text-xs font-medium text-fg-muted`,htmlFor:`img-cred-imgbase-ro-${e.id}`,children:O.imageBaseUrlLabel}),(0,M.jsx)(`input`,{id:`img-cred-imgbase-ro-${e.id}`,type:`url`,readOnly:!0,className:g(P(),`cursor-not-allowed opacity-90`),value:t.imageBaseUrl,title:O.imageBaseUrlPresetHint}),(0,M.jsx)(`p`,{className:`text-[11px] text-fg-subtle`,children:O.imageBaseUrlPresetHint})]}):null]})]}):null]},e.id)},t[58]=D,t[59]=i,t[60]=r,t[61]=x,t[62]=V,t[63]=E,t[64]=S,t[65]=O,t[66]=U,t[67]=h,t[68]=e):e=t[68],Z=n.map(e),t[46]=D,t[47]=i,t[48]=r,t[49]=x,t[50]=V,t[51]=E,t[52]=S,t[53]=n,t[54]=O,t[55]=U,t[56]=h,t[57]=Z}else Z=t[57];let Q;t[69]===Z?Q=t[70]:(Q=(0,M.jsx)(`div`,{className:`flex flex-col gap-4`,children:Z}),t[69]=Z,t[70]=Q);let $;return t[71]!==J||t[72]!==Y||t[73]!==X||t[74]!==Q?($=(0,M.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[J,Y,X,Q]}),t[71]=J,t[72]=Y,t[73]=X,t[74]=Q,t[75]=$):$=t[75],$}function de(e){return(0,M.jsx)(`option`,{value:e.value,children:e.label},e.value)}function fe(){return new Set}function pe(){return new Set}function me(e){return(e.ui?.baseUrlPresets?.length??0)>0}function he(e){return(e.ui?.regions?.length??0)>0}function ge(e){let t=_(o(e=>!!e.token)),n=t.data,r=(0,w.useMemo)(()=>e.map(e=>e.id),[e]),s=(0,w.useRef)(!1),[c,l]=(0,w.useState)(null),[u,d]=(0,w.useState)(!1),[f,p]=(0,w.useState)(null),[m,h]=(0,w.useState)(!1),[g,v]=(0,w.useState)(!1),y=(0,w.useMemo)(()=>E(n?.payload?.config,r),[n?.payload?.config,r]),b=c??y,x=y;return{gwSwr:t,credDraft:b,credBaseline:x,credDirty:(0,w.useMemo)(()=>JSON.stringify(b)!==JSON.stringify(x),[b,x]),credSaving:u,credError:f,credSavedFlash:m,credNoopFlash:g,updateCredRow:(0,w.useCallback)((e,t)=>{s.current=!0,l(n=>{let r=n??y,i=r[e]??T();return{...r,[e]:{...i,...t}}})},[y]),onDiscardCredentials:(0,w.useCallback)(()=>{s.current=!1,l(null),p(null),h(!1),v(!1)},[]),saveCredentials:(0,w.useCallback)(async e=>{let n=k(r,b,x);if(Object.keys(n).length===0){v(!0),window.setTimeout(()=>v(!1),2200);return}d(!0),p(null),h(!1);try{await j(n),await t.mutate?.(),a(i(S)),s.current=!1,l(null),h(!0),window.setTimeout(()=>h(!1),2e3)}catch(t){p(t instanceof Error?t.message:e)}finally{d(!1)}},[r,b,x,t])}}function _e(){return{enabled:!1,provider:`alibaba`,alibaba:{model:`paraformer-v2`},openai:{model:`whisper-1`},fallback:{enabled:!0,order:[`alibaba`,`openai`]}}}function ve(){return{enabled:!1,provider:`openai`,trigger:`always`,maxTextLength:512,timeoutMs:6e4,alibaba:{model:`qwen-tts`,voice:`Cherry`},openai:{model:`tts-1`,voice:`alloy`},edge:{voice:`en-US-MichelleNeural`},minimax:{model:`speech-2.8-hd`,voice:`male-qn-qingse`},"tts-local-cli":{command:``,outputFormat:`wav`}}}function L(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function R(e){return typeof e==`string`&&e.trim().length>0?e.trim():`alibaba`}function z(e,t,n){let r=L(e.providers)?e.providers:void 0,i=r&&L(r[t])?r[t]:void 0;return{...n,...i??{}}}function B(e){let t=_e();if(!L(e))return t;let n=R(e.provider),r=z(e,`alibaba`,t.alibaba??{}),i=z(e,`openai`,t.openai??{}),a=t.fallback??{enabled:!0,order:[`alibaba`,`openai`]};if(L(e.fallback)){let t=Array.isArray(e.fallback.order)?e.fallback.order.filter(e=>typeof e==`string`&&e.trim().length>0):a.order;a={enabled:typeof e.fallback.enabled==`boolean`?e.fallback.enabled:a.enabled,order:t.length?t:a.order}}let o=L(e.providers)?Object.fromEntries(Object.entries(e.providers).map(([e,t])=>[e,L(t)?{...t}:{}])):void 0;return{enabled:!!e.enabled,provider:n,alibaba:r,openai:i,...o?{providers:o}:{},fallback:a}}function V(e){return typeof e==`string`&&e.trim().length>0?e.trim():`openai`}function H(e){let t=ve();if(!L(e))return t;let n=V(e.provider),r=e.trigger===`off`||e.trigger===`always`||e.trigger===`inbound`||e.trigger===`tagged`?e.trigger:`always`,i=t[`tts-local-cli`]??{},a=L(e.providers)?Object.fromEntries(Object.entries(e.providers).map(([e,t])=>[e,L(t)?{...t}:{}])):void 0;return{enabled:!!e.enabled,provider:n,trigger:r,maxTextLength:typeof e.maxTextLength==`number`&&Number.isFinite(e.maxTextLength)?e.maxTextLength:t.maxTextLength,timeoutMs:typeof e.timeoutMs==`number`&&Number.isFinite(e.timeoutMs)?e.timeoutMs:t.timeoutMs,...a?{providers:a}:{},alibaba:z(e,`alibaba`,t.alibaba??{}),openai:z(e,`openai`,t.openai??{}),edge:z(e,`edge`,t.edge??{}),minimax:z(e,`minimax`,t.minimax??{}),"tts-local-cli":z(e,`tts-local-cli`,i)}}function U(e){let{alibaba:t,openai:n,providers:r,...i}=e,a={...r??{}};return t&&(a.alibaba={...a.alibaba??{},...t}),n&&(a.openai={...a.openai??{},...n}),{...i,...Object.keys(a).length>0?{providers:a}:{}}}function W(e){let{alibaba:t,openai:n,edge:r,minimax:i,"tts-local-cli":a,providers:o,...s}=e,c={...o??{}};return t&&(c.alibaba={...c.alibaba??{},...t}),n&&(c.openai={...c.openai??{},...n}),r&&(c.edge={...c.edge??{},...r}),i&&(c.minimax={...c.minimax??{},...i}),a&&(c[`tts-local-cli`]={...c[`tts-local-cli`]??{},...a}),{...s,...Object.keys(c).length>0?{providers:c}:{}}}function G(e){let t=L(e)?e:{};return{stt:B(t.stt),tts:H(t.tts)}}async function K(){return G((await s(i(`/api/config`))).payload?.config??{})}async function q(e){await s(i(`/api/config`),{method:`PATCH`,body:JSON.stringify({stt:U(e.stt),tts:W(e.tts)})}),x()}async function J(){let e=await s(i(`/api/voice/models`));if(!e.payload?.models)throw Error(`Missing voice models payload`);return e.payload.models}async function Y(){let e=await s(i(`/api/voice/providers`));if(!e.payload?.providers)throw Error(`Missing voice providers payload`);return e.payload}async function X(){let e=await s(i(`/api/voice/stt-providers`));if(!e.payload?.providers)throw Error(`Missing STT providers payload`);return e.payload}async function Z(e){let t=await s(i(`/api/voice/reveal-api-key`),{method:`POST`,body:JSON.stringify(e)});if(!t.payload)throw Error(`Missing reveal payload`);return t.payload}function Q(e){let t=(0,ee.c)(15),{kind:n,providerId:r,fieldId:i,value:a,onChange:o,labels:s,placeholder:c,className:l}=e,u=c===void 0?`sk-...`:c,d;t[0]!==n||t[1]!==r?(d=()=>Z({kind:n,provider:r}).then($),t[0]=n,t[1]=r,t[2]=d):d=t[2];let f=d,p;t[3]===l?p=t[4]:(p=g(`flex min-w-0 flex-col gap-1.5`,l),t[3]=l,t[4]=p);let m;t[5]!==i||t[6]!==s||t[7]!==o||t[8]!==u||t[9]!==f||t[10]!==a?(m=(0,M.jsx)(h,{id:i,value:a,onChange:o,placeholder:u,labels:s,reveal:f,loadFailedLabel:s.loadFailed,maskedHelp:s.maskedHelp,notInConfigFile:s.notInConfigFile,inputClassName:`text-xs`}),t[5]=i,t[6]=s,t[7]=o,t[8]=u,t[9]=f,t[10]=a,t[11]=m):m=t[11];let _;return t[12]!==p||t[13]!==m?(_=(0,M.jsx)(`div`,{className:p,children:m}),t[12]=p,t[13]=m,t[14]=_):_=t[14],_}function $(e){return e.apiKey??null}export{X as a,ge as c,S as d,K as i,I as l,J as n,G as o,Y as r,q as s,Q as t,C as u};
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{a as t,n,t as r}from"./vendor-react-BOUWij0V.js";import{t as i}from"./url-F3_D_6zZ.js";import{o as a}from"./vendor-swr-BIWyz7Rc.js";import{a as o,n as s}from"./fetch-CMoWY2Si.js";import{$i as c,H as l,Jo as u,K as d,Mo as f,Oa as p,U as m,Zr as h,di as g,dr as _,li as v,lo as y,ui as b,ur as x}from"./index-0HmunJW9.js";var S=`/api/image/providers`;async function C(){return(await s(i(`/api/image/providers`)))?.payload?.providers??[]}var w=e(t(),1),ee=n();function T(){return{apiKey:``,region:``,baseUrl:``,imageBaseUrl:``}}function te(e){return e?.apiKey?`••••••••••••`:``}function E(e,t){let n=(()=>{if(!e||typeof e!=`object`||!(`providersConfig`in e))return;let t=e.providersConfig;if(!(!t||typeof t!=`object`||Array.isArray(t)))return t})(),r={};for(let e of t){let t=n?.[e];r[e]={apiKey:te(t),region:t?.region??``,baseUrl:t?.baseUrl??``,imageBaseUrl:t?.imageBaseUrl??``}}return r}function D(e,t,n){let r=e[n].trim();if(r!==t[n].trim())return r||null}function O(e,t){let n=e.trim(),r=t.trim();if(n!==r&&!(d(n)&&d(r)))return n||(r?null:void 0)}function k(e,t,n){let r={};for(let i of e){let e=t[i]??T(),a=n[i]??T();if(JSON.stringify(e)===JSON.stringify(a))continue;let o={},s=O(e.apiKey,a.apiKey);s!==void 0&&(o.apiKey=s);let c=D(e,a,`region`);c!==void 0&&(o.region=c);let l=D(e,a,`baseUrl`);l!==void 0&&(o.baseUrl=l);let u=D(e,a,`imageBaseUrl`);u!==void 0&&(o.imageBaseUrl=u),Object.keys(o).length>0&&(r[i]=o)}return r}async function A(e){let t=await s(i(`/api/image/providers/${encodeURIComponent(e)}/reveal-api-key`),{method:`POST`,headers:{"Content-Type":`application/json`},body:`{}`});if(!t.ok||!t.payload)throw Error(t.error?.message??`Reveal failed`);return t.payload}async function j(e){Object.keys(e).length!==0&&(await s(i(`/api/config`),{method:`PATCH`,body:JSON.stringify({providersConfig:e})}),await x())}var M=r();function ne(e){let t=(0,ee.c)(18),{providerId:n,value:r,onChange:i,labels:a,apiKeyLinks:o,apiKeyLinkLabels:s}=e,c;t[0]===n?c=t[1]:(c=()=>A(n).then(N),t[0]=n,t[1]=c);let l=c,u=`img-cred-key-${n}`,d;t[2]!==a.apiKeyLabel||t[3]!==u?(d=(0,M.jsx)(`label`,{className:`text-xs font-medium text-fg-muted`,htmlFor:u,children:a.apiKeyLabel}),t[2]=a.apiKeyLabel,t[3]=u,t[4]=d):d=t[4];let f;t[5]!==s||t[6]!==o?(f=o.length>0?(0,M.jsx)(`div`,{className:`flex flex-col gap-1`,children:o.map(e=>(0,M.jsxs)(`a`,{href:e.href,target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex w-fit items-center gap-1 text-xs font-medium text-accent-fg hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,children:[m(e.kind,s),(0,M.jsx)(y,{className:`size-3`,"aria-hidden":!0})]},`${e.kind}-${e.href}`))}):null,t[5]=s,t[6]=o,t[7]=f):f=t[7];let p=`img-cred-key-${n}`,g;t[8]!==a||t[9]!==i||t[10]!==l||t[11]!==p||t[12]!==r?(g=(0,M.jsx)(h,{id:p,value:r,onChange:i,placeholder:a.optionalPlaceholder,labels:a,reveal:l,loadFailedLabel:a.loadFailed,maskedHelp:a.maskedHelp,notInConfigFile:a.notInConfigFile}),t[8]=a,t[9]=i,t[10]=l,t[11]=p,t[12]=r,t[13]=g):g=t[13];let _;return t[14]!==d||t[15]!==f||t[16]!==g?(_=(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1 sm:col-span-2`,children:[d,f,g]}),t[14]=d,t[15]=f,t[16]=g,t[17]=_):_=t[17],_}function N(e){return e.apiKey??null}function P(){return g(`w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-sm text-fg`,`placeholder:text-fg-subtle`,v)}function re(){return g(P(),`appearance-none bg-[length:1rem] bg-[right_0.5rem_center] bg-no-repeat pr-9`)}var F=`__custom__`;function ie(e,t){if(!e.region.trim()&&!e.imageBaseUrl.trim())return``;let n=e.region.trim().toLowerCase();return t.some(e=>e.value===n)?n:F}function ae(e,t){let n=e.baseUrl.trim().replace(/\/+$/,``);if(!n)return``;let r=t.map(e=>e.value.replace(/\/+$/,``)).indexOf(n);return r>=0?t[r].value:F}function oe(e,t,n){return t===`beijing`?e.dashscopeRegion_beijing:t===`singapore`?e.dashscopeRegion_singapore:t===`us`?e.dashscopeRegion_us:n}function se(e,t){return t===`minimax`?e.minimaxClusterLabel:t===`fal`?e.falQueueBaseLabel:e.baseUrlLabel}function ce(e,t){return t===`minimax`?e.minimaxClusterHint:t===`fal`?e.falQueueBaseHint:null}function le(e,t){return JSON.stringify(e)!==JSON.stringify(t)}function ue(e,t){return t===1?e.modelCountOne:e.modelCountMany.replace(`{count}`,String(t))}function I(e){let t=(0,ee.c)(76),{summaries:n,credDraft:r,credBaseline:i,credDirty:a,credSaving:o,credError:s,credSavedFlash:d,credNoopFlash:m,updateCredRow:h,onDiscardCredentials:_,onSaveCredentials:v,extensionIds:x,showExtensionLinks:S,showImageModelsLink:C,hideActions:te,language:E,apiKeyLinkLabels:D,messages:O}=e,k=te===void 0?!1:te,A;t[0]===n?A=t[1]:(A=n.some(he),t[0]=n,t[1]=A);let j=A,N;t[2]===n?N=t[3]:(N=n.some(me),t[2]=n,t[3]=N);let I=N,[ge,_e]=(0,w.useState)(pe),[ve,L]=(0,w.useState)(fe),R;if(t[4]!==i||t[5]!==r||t[6]!==n){R=new Set;for(let e of n)le(r[e.id]??T(),i[e.id]??T())&&R.add(e.id);t[4]=i,t[5]=r,t[6]=n,t[7]=R}else R=t[7];let z=R,B;t[8]!==z||t[9]!==ve||t[10]!==ge?(B=e=>ve.has(e)?!1:ge.has(e)?!0:z.has(e),t[8]=z,t[9]=ve,t[10]=ge,t[11]=B):B=t[11];let V=B,H;t[12]===V?H=t[13]:(H=e=>{if(V(e)){L(t=>new Set(t).add(e)),_e(t=>{let n=new Set(t);return n.delete(e),n});return}L(t=>{let n=new Set(t);return n.delete(e),n}),_e(t=>new Set(t).add(e))},t[12]=V,t[13]=H);let U=H;if(n.length===0)return null;let W;t[14]===O.credentialsIntro?W=t[15]:(W=(0,M.jsx)(`p`,{children:O.credentialsIntro}),t[14]=O.credentialsIntro,t[15]=W);let G;t[16]!==j||t[17]!==O.regionHint?(G=j?(0,M.jsx)(`p`,{className:`text-fg-subtle`,children:O.regionHint}):null,t[16]=j,t[17]=O.regionHint,t[18]=G):G=t[18];let K;t[19]!==I||t[20]!==O.endpointPresetsHint?(K=I?(0,M.jsx)(`p`,{className:`text-fg-subtle`,children:O.endpointPresetsHint}):null,t[19]=I,t[20]=O.endpointPresetsHint,t[21]=K):K=t[21];let q;t[22]!==C||t[23]!==O.imageModelsLinkTitle||t[24]!==O.openImageModelsPage?(q=C?(0,M.jsx)(`p`,{children:(0,M.jsx)(u,{to:`/settings/credentials?tab=image-models`,className:`font-medium text-accent hover:underline`,title:O.imageModelsLinkTitle,children:O.openImageModelsPage})}):null,t[22]=C,t[23]=O.imageModelsLinkTitle,t[24]=O.openImageModelsPage,t[25]=q):q=t[25];let J;t[26]!==W||t[27]!==G||t[28]!==K||t[29]!==q?(J=(0,M.jsxs)(`div`,{className:`flex flex-col gap-1 text-xs leading-relaxed text-fg-muted`,children:[W,G,K,q]}),t[26]=W,t[27]=G,t[28]=K,t[29]=q,t[30]=J):J=t[30];let Y;t[31]===s?Y=t[32]:(Y=s?(0,M.jsx)(`div`,{className:`rounded-lg border border-red-500/30 bg-red-500/10 px-3 py-2 text-sm text-red-700 dark:text-red-300`,children:s}):null,t[31]=s,t[32]=Y);let X;t[33]!==a||t[34]!==m||t[35]!==d||t[36]!==o||t[37]!==k||t[38]!==_||t[39]!==v||t[40]!==O.credentialsNothingToSave||t[41]!==O.credentialsSaved||t[42]!==O.discardCredentials||t[43]!==O.saveCredentials||t[44]!==O.savingCredentials?(X=k?null:(0,M.jsxs)(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[d?(0,M.jsx)(`span`,{className:`text-sm text-fg-muted`,children:O.credentialsSaved}):null,m?(0,M.jsx)(`span`,{className:`text-sm text-fg-muted`,children:O.credentialsNothingToSave}):null,(0,M.jsx)(b,{type:`button`,variant:`secondary`,onClick:_,disabled:!a||o,children:O.discardCredentials}),(0,M.jsx)(b,{type:`button`,variant:`primary`,onClick:v,disabled:!a||o,children:o?(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(p,{className:`size-3.5 animate-spin`}),(0,M.jsx)(`span`,{className:`ml-1.5`,children:O.savingCredentials})]}):(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(c,{className:`size-3.5`}),(0,M.jsx)(`span`,{className:`ml-1.5`,children:O.saveCredentials})]})})]}),t[33]=a,t[34]=m,t[35]=d,t[36]=o,t[37]=k,t[38]=_,t[39]=v,t[40]=O.credentialsNothingToSave,t[41]=O.credentialsSaved,t[42]=O.discardCredentials,t[43]=O.saveCredentials,t[44]=O.savingCredentials,t[45]=X):X=t[45];let Z;if(t[46]!==D||t[47]!==i||t[48]!==r||t[49]!==x||t[50]!==V||t[51]!==E||t[52]!==S||t[53]!==n||t[54]!==O||t[55]!==U||t[56]!==h){let e;t[58]!==D||t[59]!==i||t[60]!==r||t[61]!==x||t[62]!==V||t[63]!==E||t[64]!==S||t[65]!==O||t[66]!==U||t[67]!==h?(e=e=>{let t=r[e.id]??T(),n=e.ui,a=S&&x.has(e.id)?`/settings/ext/${encodeURIComponent(e.id)}`:null,o=le(t,i[e.id]??T()),s=V(e.id),c=e.label??e.id,d=ue(O,e.models.length);return(0,M.jsxs)(`section`,{className:g(`overflow-hidden rounded-xl border bg-surface-panel shadow-sm transition-colors dark:shadow-none`,o?`border-accent/50`:`border-edge`),children:[(0,M.jsxs)(`button`,{type:`button`,className:`flex w-full items-start justify-between gap-3 px-4 py-3 text-left hover:bg-surface-hover/70`,"aria-expanded":s,"aria-controls":`img-provider-credentials-${e.id}`,onClick:()=>U(e.id),children:[(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-2`,children:[(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-2`,children:[(0,M.jsx)(`span`,{className:`truncate text-sm font-semibold text-fg`,children:c}),(0,M.jsx)(`span`,{className:`rounded-full bg-surface-subtle px-2 py-0.5 text-[11px] font-medium text-fg-muted`,children:e.id}),o?(0,M.jsx)(`span`,{className:`rounded-full bg-accent-soft px-2 py-0.5 text-[11px] font-medium text-accent-fg`,children:O.unsavedChanges}):null,e.configured?(0,M.jsx)(`span`,{className:`rounded-full bg-accent-soft px-2 py-0.5 text-[11px] font-medium text-accent-fg`,children:O.configured}):(0,M.jsx)(`span`,{className:`rounded-full border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-[11px] font-medium text-amber-700 dark:text-amber-300`,children:O.missingKey})]}),(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1 text-xs text-fg-subtle`,children:[(0,M.jsx)(`span`,{children:d}),e.defaultModel?(0,M.jsxs)(`span`,{className:`min-w-0 truncate`,children:[(0,M.jsxs)(`span`,{className:`text-fg-muted`,children:[O.defaultModel,`:`]}),` `,e.id,`/`,e.defaultModel]}):null]})]}),(0,M.jsx)(f,{className:g(`mt-0.5 size-4 shrink-0 text-fg-subtle transition-transform`,s?`rotate-180`:`rotate-0`),"aria-hidden":`true`}),(0,M.jsx)(`span`,{className:`sr-only`,children:s?O.collapseProvider:O.expandProvider})]}),s?(0,M.jsxs)(`div`,{id:`img-provider-credentials-${e.id}`,className:`border-t border-edge px-4 py-4`,children:[a?(0,M.jsxs)(u,{to:a,className:`mb-3 inline-flex items-center gap-1 text-xs font-medium text-accent hover:underline`,title:O.extensionSettingsLinkTitle,children:[(0,M.jsx)(y,{className:`size-3`}),O.openExtensionSettings]}):null,e.models.length>0?(0,M.jsxs)(`p`,{className:`mb-3 text-xs leading-relaxed text-fg-subtle`,children:[(0,M.jsxs)(`span`,{className:`text-fg-muted`,children:[O.modelsLabel,`:`]}),` `,e.models.map(t=>`${e.id}/${t}`).join(`, `)]}):null,(0,M.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,M.jsx)(ne,{providerId:e.id,value:t.apiKey,onChange:t=>h(e.id,{apiKey:t}),apiKeyLinks:l(e.id,E),apiKeyLinkLabels:D,labels:{apiKeyLabel:O.apiKeyLabel,optionalPlaceholder:O.optionalPlaceholder,maskedHelp:O.apiKeyMaskedHelp,copy:O.apiKeyCopy,copied:O.apiKeyCopied,show:O.apiKeyShow,hide:O.apiKeyHide,notInConfigFile:O.apiKeyNotInConfigFile,loadFailed:O.apiKeyRevealFailed}}),n?.regions?.length?(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1 sm:col-span-2`,children:[(0,M.jsx)(`label`,{className:`text-xs font-medium text-fg-muted`,htmlFor:`img-cred-region-preset-${e.id}`,children:O.regionLabel}),(0,M.jsxs)(`select`,{id:`img-cred-region-preset-${e.id}`,className:re(),value:ie(t,n.regions),onChange:t=>{let r=t.target.value;if(r===``){h(e.id,{region:``,imageBaseUrl:``});return}if(r===F){h(e.id,{region:``,imageBaseUrl:``});return}let i=n.regions.find(e=>e.value===r);i&&h(e.id,{region:i.value,imageBaseUrl:i.imageBaseUrl})},children:[(0,M.jsx)(`option`,{value:``,children:O.regionPresetDefault}),n.regions.map(e=>(0,M.jsx)(`option`,{value:e.value,children:oe(O,e.value,e.label)},e.value)),(0,M.jsx)(`option`,{value:F,children:O.regionPresetCustom})]}),ie(t,n.regions)===F?(0,M.jsxs)(`div`,{className:`mt-2 grid gap-2 sm:grid-cols-2`,children:[(0,M.jsx)(`input`,{type:`text`,className:P(),value:t.region,placeholder:`region`,onChange:t=>h(e.id,{region:t.target.value})}),(0,M.jsx)(`input`,{type:`url`,className:P(),value:t.imageBaseUrl,placeholder:O.imageBaseUrlLabel,onChange:t=>h(e.id,{imageBaseUrl:t.target.value})})]}):null]}):null,n?.baseUrlPresets?.length?(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1 sm:col-span-2`,children:[(0,M.jsx)(`label`,{className:`text-xs font-medium text-fg-muted`,htmlFor:`img-cred-base-preset-${e.id}`,children:se(O,n.baseUrlPresetKind)}),ce(O,n.baseUrlPresetKind)?(0,M.jsx)(`p`,{className:`text-[11px] text-fg-subtle`,children:ce(O,n.baseUrlPresetKind)}):null,(0,M.jsxs)(`select`,{id:`img-cred-base-preset-${e.id}`,className:re(),value:ae(t,n.baseUrlPresets),onChange:t=>{let n=t.target.value;if(n===``){h(e.id,{baseUrl:``});return}if(n===F){h(e.id,{baseUrl:``});return}h(e.id,{baseUrl:n.replace(/\/+$/,``)})},children:[(0,M.jsx)(`option`,{value:``,children:O.baseUrlPresetDefault}),n.baseUrlPresets.map(de),(0,M.jsx)(`option`,{value:F,children:O.baseUrlPresetCustom})]}),ae(t,n.baseUrlPresets)===F?(0,M.jsx)(`input`,{type:`url`,className:g(P(),`mt-2`),value:t.baseUrl,placeholder:`https://…`,onChange:t=>h(e.id,{baseUrl:t.target.value})}):null]}):null,n?.regions?.length&&ie(t,n.regions)!==F?(0,M.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1 sm:col-span-2`,children:[(0,M.jsx)(`label`,{className:`text-xs font-medium text-fg-muted`,htmlFor:`img-cred-imgbase-ro-${e.id}`,children:O.imageBaseUrlLabel}),(0,M.jsx)(`input`,{id:`img-cred-imgbase-ro-${e.id}`,type:`url`,readOnly:!0,className:g(P(),`cursor-not-allowed opacity-90`),value:t.imageBaseUrl,title:O.imageBaseUrlPresetHint}),(0,M.jsx)(`p`,{className:`text-[11px] text-fg-subtle`,children:O.imageBaseUrlPresetHint})]}):null]})]}):null]},e.id)},t[58]=D,t[59]=i,t[60]=r,t[61]=x,t[62]=V,t[63]=E,t[64]=S,t[65]=O,t[66]=U,t[67]=h,t[68]=e):e=t[68],Z=n.map(e),t[46]=D,t[47]=i,t[48]=r,t[49]=x,t[50]=V,t[51]=E,t[52]=S,t[53]=n,t[54]=O,t[55]=U,t[56]=h,t[57]=Z}else Z=t[57];let Q;t[69]===Z?Q=t[70]:(Q=(0,M.jsx)(`div`,{className:`flex flex-col gap-4`,children:Z}),t[69]=Z,t[70]=Q);let $;return t[71]!==J||t[72]!==Y||t[73]!==X||t[74]!==Q?($=(0,M.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[J,Y,X,Q]}),t[71]=J,t[72]=Y,t[73]=X,t[74]=Q,t[75]=$):$=t[75],$}function de(e){return(0,M.jsx)(`option`,{value:e.value,children:e.label},e.value)}function fe(){return new Set}function pe(){return new Set}function me(e){return(e.ui?.baseUrlPresets?.length??0)>0}function he(e){return(e.ui?.regions?.length??0)>0}function ge(e){let t=_(o(e=>!!e.token)),n=t.data,r=(0,w.useMemo)(()=>e.map(e=>e.id),[e]),s=(0,w.useRef)(!1),[c,l]=(0,w.useState)(null),[u,d]=(0,w.useState)(!1),[f,p]=(0,w.useState)(null),[m,h]=(0,w.useState)(!1),[g,v]=(0,w.useState)(!1),y=(0,w.useMemo)(()=>E(n?.payload?.config,r),[n?.payload?.config,r]),b=c??y,x=y;return{gwSwr:t,credDraft:b,credBaseline:x,credDirty:(0,w.useMemo)(()=>JSON.stringify(b)!==JSON.stringify(x),[b,x]),credSaving:u,credError:f,credSavedFlash:m,credNoopFlash:g,updateCredRow:(0,w.useCallback)((e,t)=>{s.current=!0,l(n=>{let r=n??y,i=r[e]??T();return{...r,[e]:{...i,...t}}})},[y]),onDiscardCredentials:(0,w.useCallback)(()=>{s.current=!1,l(null),p(null),h(!1),v(!1)},[]),saveCredentials:(0,w.useCallback)(async e=>{let n=k(r,b,x);if(Object.keys(n).length===0){v(!0),window.setTimeout(()=>v(!1),2200);return}d(!0),p(null),h(!1);try{await j(n),await t.mutate?.(),a(i(S)),s.current=!1,l(null),h(!0),window.setTimeout(()=>h(!1),2e3)}catch(t){p(t instanceof Error?t.message:e)}finally{d(!1)}},[r,b,x,t])}}function _e(){return{enabled:!1,provider:`alibaba`,alibaba:{model:`paraformer-v2`},openai:{model:`whisper-1`},fallback:{enabled:!0,order:[`alibaba`,`openai`]}}}function ve(){return{enabled:!1,provider:`openai`,trigger:`always`,maxTextLength:512,timeoutMs:6e4,alibaba:{model:`qwen-tts`,voice:`Cherry`},openai:{model:`tts-1`,voice:`alloy`},edge:{voice:`en-US-MichelleNeural`},minimax:{model:`speech-2.8-hd`,voice:`male-qn-qingse`},"tts-local-cli":{command:``,outputFormat:`wav`}}}function L(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function R(e){return typeof e==`string`&&e.trim().length>0?e.trim():`alibaba`}function z(e,t,n){let r=L(e.providers)?e.providers:void 0,i=r&&L(r[t])?r[t]:void 0;return{...n,...i??{}}}function B(e){let t=_e();if(!L(e))return t;let n=R(e.provider),r=z(e,`alibaba`,t.alibaba??{}),i=z(e,`openai`,t.openai??{}),a=t.fallback??{enabled:!0,order:[`alibaba`,`openai`]};if(L(e.fallback)){let t=Array.isArray(e.fallback.order)?e.fallback.order.filter(e=>typeof e==`string`&&e.trim().length>0):a.order;a={enabled:typeof e.fallback.enabled==`boolean`?e.fallback.enabled:a.enabled,order:t.length?t:a.order}}let o=L(e.providers)?Object.fromEntries(Object.entries(e.providers).map(([e,t])=>[e,L(t)?{...t}:{}])):void 0;return{enabled:!!e.enabled,provider:n,alibaba:r,openai:i,...o?{providers:o}:{},fallback:a}}function V(e){return typeof e==`string`&&e.trim().length>0?e.trim():`openai`}function H(e){let t=ve();if(!L(e))return t;let n=V(e.provider),r=e.trigger===`off`||e.trigger===`always`||e.trigger===`inbound`||e.trigger===`tagged`?e.trigger:`always`,i=t[`tts-local-cli`]??{},a=L(e.providers)?Object.fromEntries(Object.entries(e.providers).map(([e,t])=>[e,L(t)?{...t}:{}])):void 0;return{enabled:!!e.enabled,provider:n,trigger:r,maxTextLength:typeof e.maxTextLength==`number`&&Number.isFinite(e.maxTextLength)?e.maxTextLength:t.maxTextLength,timeoutMs:typeof e.timeoutMs==`number`&&Number.isFinite(e.timeoutMs)?e.timeoutMs:t.timeoutMs,...a?{providers:a}:{},alibaba:z(e,`alibaba`,t.alibaba??{}),openai:z(e,`openai`,t.openai??{}),edge:z(e,`edge`,t.edge??{}),minimax:z(e,`minimax`,t.minimax??{}),"tts-local-cli":z(e,`tts-local-cli`,i)}}function U(e){let{alibaba:t,openai:n,providers:r,...i}=e,a={...r??{}};return t&&(a.alibaba={...a.alibaba??{},...t}),n&&(a.openai={...a.openai??{},...n}),{...i,...Object.keys(a).length>0?{providers:a}:{}}}function W(e){let{alibaba:t,openai:n,edge:r,minimax:i,"tts-local-cli":a,providers:o,...s}=e,c={...o??{}};return t&&(c.alibaba={...c.alibaba??{},...t}),n&&(c.openai={...c.openai??{},...n}),r&&(c.edge={...c.edge??{},...r}),i&&(c.minimax={...c.minimax??{},...i}),a&&(c[`tts-local-cli`]={...c[`tts-local-cli`]??{},...a}),{...s,...Object.keys(c).length>0?{providers:c}:{}}}function G(e){let t=L(e)?e:{};return{stt:B(t.stt),tts:H(t.tts)}}async function K(){return G((await s(i(`/api/config`))).payload?.config??{})}async function q(e){await s(i(`/api/config`),{method:`PATCH`,body:JSON.stringify({stt:U(e.stt),tts:W(e.tts)})}),x()}async function J(){let e=await s(i(`/api/voice/models`));if(!e.payload?.models)throw Error(`Missing voice models payload`);return e.payload.models}async function Y(){let e=await s(i(`/api/voice/providers`));if(!e.payload?.providers)throw Error(`Missing voice providers payload`);return e.payload}async function X(){let e=await s(i(`/api/voice/stt-providers`));if(!e.payload?.providers)throw Error(`Missing STT providers payload`);return e.payload}async function Z(e){let t=await s(i(`/api/voice/reveal-api-key`),{method:`POST`,body:JSON.stringify(e)});if(!t.payload)throw Error(`Missing reveal payload`);return t.payload}function Q(e){let t=(0,ee.c)(15),{kind:n,providerId:r,fieldId:i,value:a,onChange:o,labels:s,placeholder:c,className:l}=e,u=c===void 0?`sk-...`:c,d;t[0]!==n||t[1]!==r?(d=()=>Z({kind:n,provider:r}).then($),t[0]=n,t[1]=r,t[2]=d):d=t[2];let f=d,p;t[3]===l?p=t[4]:(p=g(`flex min-w-0 flex-col gap-1.5`,l),t[3]=l,t[4]=p);let m;t[5]!==i||t[6]!==s||t[7]!==o||t[8]!==u||t[9]!==f||t[10]!==a?(m=(0,M.jsx)(h,{id:i,value:a,onChange:o,placeholder:u,labels:s,reveal:f,loadFailedLabel:s.loadFailed,maskedHelp:s.maskedHelp,notInConfigFile:s.notInConfigFile,inputClassName:`text-xs`}),t[5]=i,t[6]=s,t[7]=o,t[8]=u,t[9]=f,t[10]=a,t[11]=m):m=t[11];let _;return t[12]!==p||t[13]!==m?(_=(0,M.jsx)(`div`,{className:p,children:m}),t[12]=p,t[13]=m,t[14]=_):_=t[14],_}function $(e){return e.apiKey??null}export{X as a,ge as c,S as d,K as i,I as l,J as n,G as o,Y as r,q as s,Q as t,C as u};
@@ -1 +1 @@
1
- import{Qn as e,c as t,s as n}from"./index-DKgHC1Ta.js";function r(e){return e===`zh`?`zh`:`en`}function i(e,t){let n=r(t),i=n===`en`?void 0:e.metadata.i18n?.[n],a=i?.examplePrompts&&i.examplePrompts.length>0?i.examplePrompts:e.metadata.examplePrompts??[];return{description:o(i?.description,e.description),whenToUse:s(i?.whenToUse,e.metadata.whenToUse),examplePrompts:a}}function a(e){return[e.name,e.title,e.description,e.metadata.whenToUse??``,...(e.metadata.examplePrompts??[]).map(e=>e.text),...Object.values(e.metadata.i18n??{}).flatMap(e=>[e.description??``,e.whenToUse??``,...(e.examplePrompts??[]).map(e=>e.text)]),...e.metadata.tags].join(` `).toLowerCase()}function o(e,t){return e?.trim()||t}function s(e,t){return e?.trim()||t?.trim()||void 0}function c(e,t,n){if(e.field===`goal`){t(e.text);return}n(t=>({...t,[e.field]:e.text}))}function l(e,t){return e.replace(/\{\{(\w+)\}\}/g,(e,n)=>String(t[n]??``))}function u(e,t){return e?new Intl.DateTimeFormat(t,{month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`}).format(new Date(e)):`—`}function d(e){if(!e||!Number.isFinite(e))return`—`;let t=Math.max(0,Math.floor(e/1e3));if(t<60)return`${t}s`;let n=Math.floor(t/60),r=t%60;if(n<60)return r?`${n}m ${r}s`:`${n}m`;let i=Math.floor(n/60),a=n%60;return a?`${i}h ${a}m`:`${i}h`}function f(e){return e===`succeeded`?`bg-emerald-500/15 text-emerald-700 dark:text-emerald-300`:e===`failed`||e===`timeout`?`bg-red-500/15 text-red-700 dark:text-red-300`:e===`cancelled`?`bg-amber-500/15 text-amber-700 dark:text-amber-300`:`bg-accent-soft text-accent-fg`}function p(e){let r=e.metadata.tags.map(e=>e.toLowerCase());for(let e of n)if(t[e].some(e=>r.includes(e)))return e;return null}function m(e,n){if(n===`all`)return!0;let r=e.metadata.tags.map(e=>e.toLowerCase());return t[n].some(e=>r.includes(e))}function h(e){let t=new Map;for(let n of e){let e=p(n)??`uncategorized`,r=t.get(e)??[];r.push(n),t.set(e,r)}let r=[];for(let e of n){let n=t.get(e);n?.length&&r.push({category:e,items:n})}let i=t.get(`uncategorized`);return i?.length&&r.push({category:`uncategorized`,items:i}),r}function g(e,t){return t===`all`?!0:t===`builtin`?e.metadata.builtIn:e.metadata.source===`user`}function _(e,t,n,r){let i=t.trim().toLowerCase();return e.filter(e=>!m(e,n)||!g(e,r)?!1:i?a(e).includes(i):!0)}function v(e){if(e==null)return``;if(typeof e==`string`)return e;try{return JSON.stringify(e,null,2)}catch{return String(e)}}function y(e){if(e==null)return e;if(typeof e==`object`&&e&&`raw`in e){let t=e.raw;return t===void 0?e:t}return e}function b(t){let n=t.run.metadata?.sessionKey?.trim();return n&&e(n)?n:null}function x(e){return`/chat/${encodeURIComponent(e)}`}function S(e){let t=e.source;return t&&typeof t==`object`&&`kind`in t&&typeof t.kind==`string`?t.kind:e.metadata?.triggerSource?.trim()||`unknown`}function C(e,t){let n=t.trim();return!n||n===`all`?!0:S(e)===n}function w(e){let t={};for(let[n,r]of Object.entries(e)){let e=r.trim();e&&(t[n]=e)}return Object.keys(t).length>0?t:void 0}export{h as a,b as c,v as d,x as f,u as i,C as l,i as m,_ as n,l as o,c as p,d as r,y as s,w as t,f as u};
1
+ import{Qn as e,c as t,s as n}from"./index-0HmunJW9.js";function r(e){return e===`zh`?`zh`:`en`}function i(e,t){let n=r(t),i=n===`en`?void 0:e.metadata.i18n?.[n],a=i?.examplePrompts&&i.examplePrompts.length>0?i.examplePrompts:e.metadata.examplePrompts??[];return{description:o(i?.description,e.description),whenToUse:s(i?.whenToUse,e.metadata.whenToUse),examplePrompts:a}}function a(e){return[e.name,e.title,e.description,e.metadata.whenToUse??``,...(e.metadata.examplePrompts??[]).map(e=>e.text),...Object.values(e.metadata.i18n??{}).flatMap(e=>[e.description??``,e.whenToUse??``,...(e.examplePrompts??[]).map(e=>e.text)]),...e.metadata.tags].join(` `).toLowerCase()}function o(e,t){return e?.trim()||t}function s(e,t){return e?.trim()||t?.trim()||void 0}function c(e,t,n){if(e.field===`goal`){t(e.text);return}n(t=>({...t,[e.field]:e.text}))}function l(e,t){return e.replace(/\{\{(\w+)\}\}/g,(e,n)=>String(t[n]??``))}function u(e,t){return e?new Intl.DateTimeFormat(t,{month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`}).format(new Date(e)):`—`}function d(e){if(!e||!Number.isFinite(e))return`—`;let t=Math.max(0,Math.floor(e/1e3));if(t<60)return`${t}s`;let n=Math.floor(t/60),r=t%60;if(n<60)return r?`${n}m ${r}s`:`${n}m`;let i=Math.floor(n/60),a=n%60;return a?`${i}h ${a}m`:`${i}h`}function f(e){return e===`succeeded`?`bg-emerald-500/15 text-emerald-700 dark:text-emerald-300`:e===`failed`||e===`timeout`?`bg-red-500/15 text-red-700 dark:text-red-300`:e===`cancelled`?`bg-amber-500/15 text-amber-700 dark:text-amber-300`:`bg-accent-soft text-accent-fg`}function p(e){let r=e.metadata.tags.map(e=>e.toLowerCase());for(let e of n)if(t[e].some(e=>r.includes(e)))return e;return null}function m(e,n){if(n===`all`)return!0;let r=e.metadata.tags.map(e=>e.toLowerCase());return t[n].some(e=>r.includes(e))}function h(e){let t=new Map;for(let n of e){let e=p(n)??`uncategorized`,r=t.get(e)??[];r.push(n),t.set(e,r)}let r=[];for(let e of n){let n=t.get(e);n?.length&&r.push({category:e,items:n})}let i=t.get(`uncategorized`);return i?.length&&r.push({category:`uncategorized`,items:i}),r}function g(e,t){return t===`all`?!0:t===`builtin`?e.metadata.builtIn:e.metadata.source===`user`}function _(e,t,n,r){let i=t.trim().toLowerCase();return e.filter(e=>!m(e,n)||!g(e,r)?!1:i?a(e).includes(i):!0)}function v(e){if(e==null)return``;if(typeof e==`string`)return e;try{return JSON.stringify(e,null,2)}catch{return String(e)}}function y(e){if(e==null)return e;if(typeof e==`object`&&e&&`raw`in e){let t=e.raw;return t===void 0?e:t}return e}function b(t){let n=t.run.metadata?.sessionKey?.trim();return n&&e(n)?n:null}function x(e){return`/chat/${encodeURIComponent(e)}`}function S(e){let t=e.source;return t&&typeof t==`object`&&`kind`in t&&typeof t.kind==`string`?t.kind:e.metadata?.triggerSource?.trim()||`unknown`}function C(e,t){let n=t.trim();return!n||n===`all`?!0:S(e)===n}function w(e){let t={};for(let[n,r]of Object.entries(e)){let e=r.trim();e&&(t[n]=e)}return Object.keys(t).length>0?t:void 0}export{h as a,b as c,v as d,x as f,u as i,C as l,i as m,_ as n,l as o,c as p,d as r,y as s,w as t,f as u};
@@ -1,4 +1,4 @@
1
- import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{a as t,n,t as r}from"./vendor-react-BOUWij0V.js";import{i,o as a}from"./url-q28QhI7l.js";import{i as o}from"./vendor-swr-BIWyz7Rc.js";import{t as s}from"./copy-Dv6d4Dvw.js";import{a as c}from"./fetch-drJUxxKP.js";import{$o as l,Ba as u,Bi as d,C as f,Ca as p,Ci as m,Cr as h,D as g,Dr as _,E as v,Er as y,Mo as b,No as x,Or as S,Qr as C,Ri as w,S as T,T as E,To as D,Tr as O,Yi as k,Zo as A,_ as ee,_a as te,a as j,b as M,d as N,di as P,eo as F,f as ne,fo as I,g as re,h as ie,i as ae,ki as L,kr as R,l as z,la as oe,m as se,na as B,ni as ce,o as V,p as H,pi as U,r as W,sa as G,ta as K,u as le,ui as q,uo as ue,v as J,vi as de,w as fe,wr as pe,y as me,zr as he}from"./index-DKgHC1Ta.js";import{a as Y,c as ge,d as _e,f as ve,i as ye,l as be,m as xe,n as Se,o as X,p as Ce,r as we,s as Te,t as Ee,u as De}from"./workflow-page.utils-g57BRfEd.js";var Z=e(t(),1),Q=n(),Oe=[`queued`,`running`,`succeeded`,`attention`],ke=10080*60*1e3,Ae=new Set([`failed`,`timeout`,`cancelled`]);function je(e){return e.metadata?.sessionKey?.trim()||null}function Me(e,t){return e.length<=t?e:`${e.slice(0,t-1)}…`}function Ne(e,t){if(!e||typeof e!=`object`)return null;let n=e;for(let e of t){let t=n[e];if(typeof t==`string`&&t.trim())return t.trim()}return null}function Pe(e,t=90){let n=e.metadata?.input?.goal?.trim()||(typeof e.metadata?.input?.payload==`string`?e.metadata.input.payload.trim():null)||Ne(e.metadata?.input?.payload,[`query`,`goal`,`prompt`,`input`,`message`])||Ne(e.metadata?.input?.variables,[`query`,`goal`,`prompt`,`input`,`message`]);return n?Me(n,t):null}function Fe(e,t=90){return Pe(e,t)??Me(e.title?.trim()||e.definitionId,t)}function Ie(e,t=44){return Me(e.title?.trim()||e.definitionId,t)}function Le(e,t){let n=t.trim().toLowerCase();return n?[Pe(e,500),e.title,e.definitionId,e.id].filter(Boolean).join(` `).toLowerCase().includes(n):!0}function Re(e,t){let n=t.workflowFilterId.trim();return e.filter(e=>n&&e.definitionId!==n||!be(e,t.triggerFilter??`all`)?!1:Le(e,t.searchQuery))}function ze(e){return e.completedAtMs??e.createdAtMs}function Be(e,t){return t-ze(e)<=ke}function Ve(e,t){return e.status===`queued`?`queued`:e.status===`running`?`running`:e.status===`succeeded`?Be(e,t)?`succeeded`:null:Ae.has(e.status)?`attention`:null}function He(e,t){let n=[...t];return e===`queued`?n.sort((e,t)=>e.createdAtMs-t.createdAtMs):e===`running`?n.sort((e,t)=>(t.startedAtMs??t.createdAtMs)-(e.startedAtMs??e.createdAtMs)):n.sort((e,t)=>ze(t)-ze(e))}function Ue(e,t){let n={queued:[],running:[],succeeded:[],attention:[]};for(let r of e){let e=Ve(r,t);e&&n[e].push(r)}let r=He(`succeeded`,n.succeeded),i=r.length,a=r.slice(0,20),o=Math.max(0,i-20);return Oe.map(e=>e===`succeeded`?{id:e,runs:a,totalInWindow:i,hiddenByCap:o}:{id:e,runs:He(e,n[e])})}var We=new Map;function Ge(e){let t=We.get(e);return t||(t=new Intl.RelativeTimeFormat(e,{numeric:`auto`}),We.set(e,t)),t}function Ke(e,t,n){let r=Math.round((t-e)/1e3),i=Ge(n);if(r<60)return i.format(-r,`second`);let a=Math.round(r/60);if(a<60)return i.format(-a,`minute`);let o=Math.round(a/60);if(o<48)return i.format(-o,`hour`);let s=Math.round(o/24);return i.format(-s,`day`)}function qe(e){return e.status===`queued`||e.status===`running`}function Je(e){return e.status===`failed`||e.status===`timeout`||e.status===`cancelled`}var $=r(),Ye=(0,Z.memo)(function(e){let t=(0,Q.c)(65),{run:n,language:r,localeTag:i,nowMs:o,selected:s,onOpen:c,onOpenChat:l,onCancel:u,onRetry:d}=e,f=a(r).workflows,[p,h]=(0,Z.useState)(!1),g;t[0]===n?g=t[1]:(g=je(n),t[0]=n,t[1]=g);let _=!g,v;t[2]===n?v=t[3]:(v=qe(n),t[2]=n,t[3]=v);let y=v,b=n.status===`running`||n.status===`queued`,x;t[4]!==n.metrics.agentCount||t[5]!==n.metrics.doneAgentCount?(x=n.metrics.agentCount>0?Math.round(n.metrics.doneAgentCount/n.metrics.agentCount*100):0,t[4]=n.metrics.agentCount,t[5]=n.metrics.doneAgentCount,t[6]=x):x=t[6];let S=x,C=n.metrics.errorAgentCount>0,w=n.startedAtMs??n.createdAtMs,T=we(y?o-w:n.metrics.durationMs),E=X(f.taskArtifacts,{count:n.metrics.artifactCount}),D;t[7]===n?D=t[8]:(D=Fe(n),t[7]=n,t[8]=D);let O=D,k;t[9]===n?k=t[10]:(k=Ie(n),t[9]=n,t[10]=k);let A=k,ee;t[11]!==c||t[12]!==n?(ee=()=>{c(n)},t[11]=c,t[12]=n,t[13]=ee):ee=t[13];let te=ee,j;t[14]!==_||t[15]!==l||t[16]!==n?(j=()=>{_||l(n)},t[14]=_,t[15]=l,t[16]=n,t[17]=j):j=t[17];let M=j,N=s?`border-accent/70 ring-1 ring-accent/30`:`border-edge`,F;t[18]===N?F=t[19]:(F=P(`group relative overflow-hidden rounded-xl border bg-surface-panel p-3.5 transition-colors`,N,`hover:border-edge-strong hover:bg-surface-hover/50`),t[18]=N,t[19]=F);let ne;t[20]===Symbol.for(`react.memo_cache_sentinel`)?(ne=P(`w-full text-left`,ce.focusRingPanel),t[20]=ne):ne=t[20];let I;t[21]===O?I=t[22]:(I=(0,$.jsx)(`div`,{className:`line-clamp-2 text-sm font-semibold leading-5 text-fg`,children:O}),t[21]=O,t[22]=I);let re;t[23]===A?re=t[24]:(re=(0,$.jsx)(`div`,{className:`mt-1 truncate text-[11px] font-medium text-fg-muted`,children:A}),t[23]=A,t[24]=re);let ie;t[25]!==I||t[26]!==re?(ie=(0,$.jsxs)(`div`,{className:`min-w-0`,children:[I,re]}),t[25]=I,t[26]=re,t[27]=ie):ie=t[27];let ae;t[28]===n.status?ae=t[29]:(ae=P(`shrink-0 rounded-full px-2 py-0.5 text-[10px] font-semibold shadow-sm`,De(n.status)),t[28]=n.status,t[29]=ae);let L;t[30]!==i||t[31]!==o||t[32]!==w?(L=Ke(w,o,i),t[30]=i,t[31]=o,t[32]=w,t[33]=L):L=t[33];let R;t[34]===L?R=t[35]:(R=(0,$.jsx)(`span`,{children:L}),t[34]=L,t[35]=R);let z=T===`—`?null:(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{"aria-hidden":!0,children:`·`}),(0,$.jsx)(`span`,{children:X(f.taskElapsed,{duration:T})})]}),oe;t[36]!==R||t[37]!==z?(oe=(0,$.jsxs)(`div`,{className:`mt-2 flex flex-wrap items-center gap-1.5 text-[11px] text-fg-subtle`,children:[R,z]}),t[36]=R,t[37]=z,t[38]=oe):oe=t[38];let se=n.metrics.artifactCount>0?(0,$.jsx)(`span`,{className:`rounded-full bg-surface-hover px-2 py-0.5 font-medium text-fg-muted`,children:E}):null,B=s?(0,$.jsx)(`span`,{className:`font-medium text-accent-fg`,children:f.taskOpenDetails}):null,V;t[39]!==se||t[40]!==B?(V=(0,$.jsxs)(`div`,{className:`mt-3 flex flex-wrap items-center gap-2 text-[11px] text-fg-subtle`,children:[se,B]}),t[39]=se,t[40]=B,t[41]=V):V=t[41];let H;t[42]===h?H=t[43]:(H=()=>h(Ze),t[42]=h,t[43]=H);let U;t[44]===Symbol.for(`react.memo_cache_sentinel`)?(U=(0,$.jsx)(ue,{className:`size-4`,"aria-hidden":!0}),t[44]=U):U=t[44];let W;t[45]!==f.taskActionsAria||t[46]!==p||t[47]!==H?(W=(0,$.jsx)(q,{variant:`ghost`,className:`size-7 p-0 opacity-0 group-hover:opacity-100 group-focus-within:opacity-100`,"aria-label":f.taskActionsAria,"aria-expanded":p,onClick:H,children:U}),t[45]=f.taskActionsAria,t[46]=p,t[47]=H,t[48]=W):W=t[48];let G;t[49]!==y||t[50]!==_||t[51]!==M||t[52]!==f.cancel||t[53]!==f.continueInChat||t[54]!==f.rerun||t[55]!==f.taskCloseMenu||t[56]!==p||t[57]!==u||t[58]!==d||t[59]!==n||t[60]!==h?(G=p?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`button`,{type:`button`,className:`fixed inset-0 z-10 cursor-default`,"aria-label":f.taskCloseMenu,onClick:()=>h(!1)}),(0,$.jsxs)(`div`,{className:`absolute right-0 z-20 mt-1 min-w-36 rounded-lg border border-edge bg-surface-panel py-1 shadow-surface`,children:[(0,$.jsx)(Xe,{label:f.continueInChat,disabled:_,onClick:()=>{h(!1),M()}}),y?(0,$.jsx)(Xe,{label:f.cancel,tone:`danger`,onClick:()=>{h(!1),u(n.id)}}):null,Je(n)?(0,$.jsx)(Xe,{label:f.rerun,onClick:()=>{h(!1),d(n.id)}}):null]})]}):null,t[49]=y,t[50]=_,t[51]=M,t[52]=f.cancel,t[53]=f.continueInChat,t[54]=f.rerun,t[55]=f.taskCloseMenu,t[56]=p,t[57]=u,t[58]=d,t[59]=n,t[60]=h,t[61]=G):G=t[61];let K;return t[62]!==W||t[63]!==G?(K=(0,$.jsxs)(`div`,{className:`absolute right-2 top-2`,children:[W,G]}),t[62]=W,t[63]=G,t[64]=K):K=t[64],(0,$.jsxs)(`div`,{className:F,children:[(0,$.jsxs)(`button`,{type:`button`,onClick:te,"aria-label":`${f.taskOpenDetails}: ${O}`,"aria-current":s?`true`:void 0,className:ne,children:[(0,$.jsxs)(`div`,{className:`pr-7`,children:[(0,$.jsxs)(`div`,{className:`flex min-w-0 items-start justify-between gap-2`,children:[ie,(0,$.jsx)(`span`,{className:ae,children:f.status[n.status]??n.status})]}),oe]}),b?(0,$.jsxs)(`div`,{className:`mt-2.5`,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-2 text-[11px] text-fg-muted`,children:[(0,$.jsx)(`span`,{children:X(f.agentProgress,{done:n.metrics.doneAgentCount,total:n.metrics.agentCount})}),(0,$.jsxs)(`span`,{children:[S,`%`]})]}),(0,$.jsx)(`div`,{className:`mt-1.5 h-1.5 overflow-hidden rounded-full bg-surface-hover`,children:(0,$.jsx)(`div`,{className:`h-full rounded-full bg-accent transition-all`,style:{width:`${S}%`}})})]}):null,V,C?(0,$.jsxs)(`div`,{className:`mt-2 flex items-center gap-1 text-[11px] text-amber-700 dark:text-amber-300`,children:[(0,$.jsx)(m,{className:`size-3 shrink-0`,"aria-hidden":!0}),X(f.runRowErrorSummary,{count:n.metrics.errorAgentCount})]}):null]}),K]})});function Xe(e){let t=(0,Q.c)(8),{label:n,disabled:r,tone:i,onClick:a}=e,o=r?`cursor-not-allowed text-fg-subtle`:`text-fg hover:bg-surface-hover`,s=i===`danger`&&!r&&`text-red-600 dark:text-red-300`,c;t[0]!==o||t[1]!==s?(c=P(`block w-full px-3 py-1.5 text-left text-xs`,o,s),t[0]=o,t[1]=s,t[2]=c):c=t[2];let l;return t[3]!==r||t[4]!==n||t[5]!==a||t[6]!==c?(l=(0,$.jsx)(`button`,{type:`button`,disabled:r,onClick:a,className:c,children:n}),t[3]=r,t[4]=n,t[5]=a,t[6]=c,t[7]=l):l=t[7],l}function Ze(e){return!e}function Qe(e,t){return t.boardColumns[e]}var $e=(0,Z.memo)(function(e){let t=(0,Q.c)(14),{column:n,language:r,localeTag:i,nowMs:o,selectedRunId:s,onOpenRun:c,onOpenRunChat:l,onCancelRun:u,onRetryRun:d}=e,f=a(r).workflows,[p,m]=(0,Z.useState)(!1),h=n.id===`succeeded`,g=h?5:n.runs.length,_;t[0]!==g||t[1]!==n.runs||t[2]!==p||t[3]!==h?(_=h&&!p?n.runs.slice(0,g):n.runs,t[0]=g,t[1]=n.runs,t[2]=p,t[3]=h,t[4]=_):_=t[4];let v=_,y=h&&n.runs.length>5&&!p,b=h&&p,x;t[5]===Symbol.for(`react.memo_cache_sentinel`)?(x=P(`flex min-h-112 w-73 shrink-0 snap-center flex-col rounded-2xl border border-edge bg-surface-panel/40`),t[5]=x):x=t[5];let S;t[6]===Symbol.for(`react.memo_cache_sentinel`)?(S=(0,$.jsx)(`span`,{className:`size-2 rounded-full bg-accent`,"aria-hidden":!0}),t[6]=S):S=t[6];let C;t[7]===n.runs.length?C=t[8]:(C=(0,$.jsx)(`span`,{className:`rounded-full bg-surface-hover px-2.5 py-1 text-xs font-semibold tabular-nums text-fg-muted`,children:n.runs.length}),t[7]=n.runs.length,t[8]=C);let w=v.length===0?(0,$.jsx)(`div`,{className:`flex min-h-32 items-center justify-center rounded-xl border border-dashed border-edge bg-surface-panel/40 px-4 py-6 text-center text-xs text-fg-subtle`,children:f.boardColumnEmpty}):v.map(e=>(0,$.jsx)(Ye,{run:e,language:r,localeTag:i,nowMs:o,selected:e.id===s,onOpen:c,onOpenChat:l,onCancel:u,onRetry:d},e.id)),T=y?(0,$.jsx)(q,{variant:`ghost`,className:`h-8 w-full text-xs`,onClick:()=>m(!0),children:X(f.boardExpandSucceeded,{count:Math.min(n.runs.length,n.totalInWindow??n.runs.length)})}):null,E=b?(0,$.jsx)(q,{variant:`ghost`,className:`h-8 w-full text-xs`,onClick:()=>m(!1),children:f.boardCollapseSucceeded}):null,D=h&&(n.hiddenByCap??0)>0?(0,$.jsx)(`p`,{className:`px-1 text-center text-[11px] text-fg-subtle`,children:X(f.boardSucceededCapHint,{count:n.hiddenByCap??0})}):null,O;return t[9]!==w||t[10]!==T||t[11]!==E||t[12]!==D?(O=(0,$.jsxs)(`div`,{className:`flex flex-1 flex-col gap-3 p-2.5`,children:[w,T,E,D]}),t[9]=w,t[10]=T,t[11]=E,t[12]=D,t[13]=O):O=t[13],(0,$.jsxs)(`section`,{className:x,"aria-label":Qe(n.id,f),children:[(0,$.jsxs)(`header`,{className:`sticky top-0 z-10 flex items-center justify-between gap-2 rounded-t-2xl border-b border-edge-subtle bg-surface-panel/90 px-3.5 py-3 backdrop-blur`,children:[(0,$.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[S,(0,$.jsx)(`h2`,{className:`truncate text-sm font-semibold text-fg`,children:Qe(n.id,f)})]}),C]}),O]})}),et=(0,Z.memo)(function(e){let t=(0,Q.c)(45),{runs:n,language:r,localeTag:i,labels:a,searchQuery:o,workflowFilterId:s,triggerFilter:c,selectedRunId:l,loading:u,onOpenRun:d,onOpenRunChat:f,onCancelRun:p,onRetryRun:m,onStart:h}=e,g;t[0]===n?g=t[1]:(g=n.some(tt),t[0]=n,t[1]=g);let _=g,[v,y]=(0,Z.useState)(nt),b,x;t[2]===_?(b=t[3],x=t[4]):(b=()=>{if(!_)return;let e=window.setInterval(()=>y(Date.now()),1e3);return()=>window.clearInterval(e)},x=[_],t[2]=_,t[3]=b,t[4]=x),(0,Z.useEffect)(b,x);let S;t[5]!==v||t[6]!==n||t[7]!==o||t[8]!==c||t[9]!==s?(S=Ue(Re(n,{searchQuery:o,workflowFilterId:s,triggerFilter:c}),v),t[5]=v,t[6]=n,t[7]=o,t[8]=c,t[9]=s,t[10]=S):S=t[10];let C=S,w=C.reduce(rt,0);if(u&&w===0){let e;return t[11]===a.loading?e=t[12]:(e=(0,$.jsx)(`p`,{className:`text-sm text-fg-muted`,children:a.loading}),t[11]=a.loading,t[12]=e),e}if(!u&&w===0){let e;t[13]===a.boardEmptyTitle?e=t[14]:(e=(0,$.jsx)(`p`,{className:`text-sm font-medium text-fg`,children:a.boardEmptyTitle}),t[13]=a.boardEmptyTitle,t[14]=e);let n;t[15]===a.boardEmptyHint?n=t[16]:(n=(0,$.jsx)(`p`,{className:`mx-auto mt-2 max-w-md text-sm leading-6 text-fg-muted`,children:a.boardEmptyHint}),t[15]=a.boardEmptyHint,t[16]=n);let r;t[17]!==a.boardStart||t[18]!==h?(r=(0,$.jsx)(`div`,{className:`mt-4 flex justify-center`,children:(0,$.jsx)(q,{variant:`primary`,onClick:h,children:a.boardStart})}),t[17]=a.boardStart,t[18]=h,t[19]=r):r=t[19];let i;return t[20]!==e||t[21]!==n||t[22]!==r?(i=(0,$.jsxs)(`div`,{className:`rounded-2xl border border-dashed border-edge bg-surface-panel/40 px-6 py-12 text-center`,children:[e,n,r]}),t[20]=e,t[21]=n,t[22]=r,t[23]=i):i=t[23],i}let T;if(t[24]!==C||t[25]!==r||t[26]!==i||t[27]!==v||t[28]!==p||t[29]!==d||t[30]!==f||t[31]!==m||t[32]!==l){let e;t[34]!==r||t[35]!==i||t[36]!==v||t[37]!==p||t[38]!==d||t[39]!==f||t[40]!==m||t[41]!==l?(e=e=>(0,$.jsx)($e,{column:e,language:r,localeTag:i,nowMs:v,selectedRunId:l,onOpenRun:d,onOpenRunChat:f,onCancelRun:p,onRetryRun:m},e.id),t[34]=r,t[35]=i,t[36]=v,t[37]=p,t[38]=d,t[39]=f,t[40]=m,t[41]=l,t[42]=e):e=t[42],T=C.map(e),t[24]=C,t[25]=r,t[26]=i,t[27]=v,t[28]=p,t[29]=d,t[30]=f,t[31]=m,t[32]=l,t[33]=T}else T=t[33];let E;return t[43]===T?E=t[44]:(E=(0,$.jsx)(`div`,{className:`-mx-1 flex min-w-0 snap-x snap-mandatory gap-3 overflow-x-auto px-1 pb-2`,children:T}),t[43]=T,t[44]=E),E});function tt(e){return e.status===`queued`||e.status===`running`}function nt(){return Date.now()}function rt(e,t){return e+t.runs.length}function it(e){let t=(0,Q.c)(45),{open:n,definition:r,language:i,onClose:o,onRun:s}=e,c;t[0]===i?c=t[1]:(c=a(i),t[0]=i,t[1]=c);let l=c.workflows;if(!r)return null;let u;t[2]!==r||t[3]!==i?(u=xe(r,i),t[2]=r,t[3]=i,t[4]=u):u=t[4];let d=u,f=r.runtime?.source??``,p;t[5]===o?p=t[6]:(p=e=>!e&&o(),t[5]=o,t[6]=p);let m;t[7]===Symbol.for(`react.memo_cache_sentinel`)?(m=(0,$.jsx)(y,{className:`xopc-dialog-overlay fixed inset-0 z-65 bg-scrim backdrop-blur-[1px]`}),t[7]=m):m=t[7];let h;t[8]===r.title?h=t[9]:(h=(0,$.jsx)(R,{className:`text-base font-semibold text-fg`,children:r.title}),t[8]=r.title,t[9]=h);let g;t[10]===d.description?g=t[11]:(g=(0,$.jsx)(O,{className:`mt-1 text-sm text-fg-muted`,children:d.description}),t[10]=d.description,t[11]=g);let v;t[12]!==h||t[13]!==g?(v=(0,$.jsxs)(`div`,{className:`border-b border-edge px-5 py-4`,children:[h,g]}),t[12]=h,t[13]=g,t[14]=v):v=t[14];let b;t[15]!==l.whenToUseHeading||t[16]!==d.whenToUse?(b=d.whenToUse?(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h3`,{className:`text-xs font-semibold uppercase tracking-wide text-fg-subtle`,children:l.whenToUseHeading}),(0,$.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-fg-muted`,children:d.whenToUse})]}):null,t[15]=l.whenToUseHeading,t[16]=d.whenToUse,t[17]=b):b=t[17];let x;t[18]!==r.phases||t[19]!==l.phasesHeading?(x=r.phases.length>0?(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h3`,{className:`text-xs font-semibold uppercase tracking-wide text-fg-subtle`,children:l.phasesHeading}),(0,$.jsx)(`ol`,{className:`mt-2 space-y-2`,children:r.phases.map(at)})]}):null,t[18]=r.phases,t[19]=l.phasesHeading,t[20]=x):x=t[20];let C;t[21]!==l.scriptHeading||t[22]!==f?(C=f?(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h3`,{className:`text-xs font-semibold uppercase tracking-wide text-fg-subtle`,children:l.scriptHeading}),(0,$.jsx)(`pre`,{className:`mt-2 max-h-64 overflow-auto rounded-xl border border-edge bg-surface-base/50 p-3 font-mono text-xs leading-5 text-fg-muted`,children:f})]}):null,t[21]=l.scriptHeading,t[22]=f,t[23]=C):C=t[23];let w;t[24]!==C||t[25]!==b||t[26]!==x?(w=(0,$.jsxs)(`div`,{className:`min-h-0 flex-1 space-y-4 overflow-auto px-5 py-4`,children:[b,x,C]}),t[24]=C,t[25]=b,t[26]=x,t[27]=w):w=t[27];let T;t[28]!==l.closeResult||t[29]!==o?(T=(0,$.jsx)(q,{variant:`secondary`,onClick:o,children:l.closeResult}),t[28]=l.closeResult,t[29]=o,t[30]=T):T=t[30];let E;t[31]!==l.runWorkflow||t[32]!==s?(E=(0,$.jsx)(q,{variant:`primary`,onClick:s,children:l.runWorkflow}),t[31]=l.runWorkflow,t[32]=s,t[33]=E):E=t[33];let D;t[34]!==T||t[35]!==E?(D=(0,$.jsxs)(`div`,{className:`flex justify-end gap-2 border-t border-edge px-5 py-4`,children:[T,E]}),t[34]=T,t[35]=E,t[36]=D):D=t[36];let k;t[37]!==w||t[38]!==D||t[39]!==v?(k=(0,$.jsxs)(_,{children:[m,(0,$.jsxs)(pe,{className:`fixed left-1/2 top-1/2 z-66 flex max-h-[min(85vh,44rem)] w-[min(100%-2rem,48rem)] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-2xl border border-edge bg-surface-panel shadow-popover outline-none`,children:[v,w,D]})]}),t[37]=w,t[38]=D,t[39]=v,t[40]=k):k=t[40];let A;return t[41]!==n||t[42]!==k||t[43]!==p?(A=(0,$.jsx)(S,{open:n,onOpenChange:p,children:k}),t[41]=n,t[42]=k,t[43]=p,t[44]=A):A=t[44],A}function at(e,t){return(0,$.jsxs)(`li`,{className:`rounded-xl border border-edge bg-surface-base/40 px-3 py-2`,children:[(0,$.jsxs)(`div`,{className:`text-sm font-medium text-fg`,children:[t+1,`. `,e.title]}),e.description?(0,$.jsx)(`p`,{className:`mt-1 text-xs leading-5 text-fg-muted`,children:e.description}):null]},e.id)}function ot({open:e,language:t,saving:n,onClose:r,onSave:i}){let o=a(t).workflows,[s,c]=(0,Z.useState)(``),[l,u]=(0,Z.useState)(``),[d,f]=(0,Z.useState)(!1),[p,m]=(0,Z.useState)(!1),[h,g]=(0,Z.useState)(null),[v,b]=(0,Z.useState)(null);(0,Z.useEffect)(()=>{e&&(c(``),f(!1),m(!1),g(null),b(null),u(`export const meta = {
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{a as t,n,t as r}from"./vendor-react-BOUWij0V.js";import{i,o as a}from"./url-F3_D_6zZ.js";import{i as o}from"./vendor-swr-BIWyz7Rc.js";import{t as s}from"./copy-Dv6d4Dvw.js";import{a as c}from"./fetch-CMoWY2Si.js";import{$o as l,Ba as u,Bi as d,C as f,Ca as p,Ci as m,Cr as h,D as g,Dr as _,E as v,Er as y,Mo as b,No as x,Or as S,Qr as C,Ri as w,S as T,T as E,To as D,Tr as O,Yi as k,Zo as A,_ as ee,_a as te,a as j,b as M,d as N,di as P,eo as F,f as ne,fo as I,g as re,h as ie,i as ae,ki as L,kr as R,l as z,la as oe,m as se,na as B,ni as ce,o as V,p as H,pi as U,r as W,sa as G,ta as K,u as le,ui as q,uo as ue,v as J,vi as de,w as fe,wr as pe,y as me,zr as he}from"./index-0HmunJW9.js";import{a as Y,c as ge,d as _e,f as ve,i as ye,l as be,m as xe,n as Se,o as X,p as Ce,r as we,s as Te,t as Ee,u as De}from"./workflow-page.utils-CeBkAjP7.js";var Z=e(t(),1),Q=n(),Oe=[`queued`,`running`,`succeeded`,`attention`],ke=10080*60*1e3,Ae=new Set([`failed`,`timeout`,`cancelled`]);function je(e){return e.metadata?.sessionKey?.trim()||null}function Me(e,t){return e.length<=t?e:`${e.slice(0,t-1)}…`}function Ne(e,t){if(!e||typeof e!=`object`)return null;let n=e;for(let e of t){let t=n[e];if(typeof t==`string`&&t.trim())return t.trim()}return null}function Pe(e,t=90){let n=e.metadata?.input?.goal?.trim()||(typeof e.metadata?.input?.payload==`string`?e.metadata.input.payload.trim():null)||Ne(e.metadata?.input?.payload,[`query`,`goal`,`prompt`,`input`,`message`])||Ne(e.metadata?.input?.variables,[`query`,`goal`,`prompt`,`input`,`message`]);return n?Me(n,t):null}function Fe(e,t=90){return Pe(e,t)??Me(e.title?.trim()||e.definitionId,t)}function Ie(e,t=44){return Me(e.title?.trim()||e.definitionId,t)}function Le(e,t){let n=t.trim().toLowerCase();return n?[Pe(e,500),e.title,e.definitionId,e.id].filter(Boolean).join(` `).toLowerCase().includes(n):!0}function Re(e,t){let n=t.workflowFilterId.trim();return e.filter(e=>n&&e.definitionId!==n||!be(e,t.triggerFilter??`all`)?!1:Le(e,t.searchQuery))}function ze(e){return e.completedAtMs??e.createdAtMs}function Be(e,t){return t-ze(e)<=ke}function Ve(e,t){return e.status===`queued`?`queued`:e.status===`running`?`running`:e.status===`succeeded`?Be(e,t)?`succeeded`:null:Ae.has(e.status)?`attention`:null}function He(e,t){let n=[...t];return e===`queued`?n.sort((e,t)=>e.createdAtMs-t.createdAtMs):e===`running`?n.sort((e,t)=>(t.startedAtMs??t.createdAtMs)-(e.startedAtMs??e.createdAtMs)):n.sort((e,t)=>ze(t)-ze(e))}function Ue(e,t){let n={queued:[],running:[],succeeded:[],attention:[]};for(let r of e){let e=Ve(r,t);e&&n[e].push(r)}let r=He(`succeeded`,n.succeeded),i=r.length,a=r.slice(0,20),o=Math.max(0,i-20);return Oe.map(e=>e===`succeeded`?{id:e,runs:a,totalInWindow:i,hiddenByCap:o}:{id:e,runs:He(e,n[e])})}var We=new Map;function Ge(e){let t=We.get(e);return t||(t=new Intl.RelativeTimeFormat(e,{numeric:`auto`}),We.set(e,t)),t}function Ke(e,t,n){let r=Math.round((t-e)/1e3),i=Ge(n);if(r<60)return i.format(-r,`second`);let a=Math.round(r/60);if(a<60)return i.format(-a,`minute`);let o=Math.round(a/60);if(o<48)return i.format(-o,`hour`);let s=Math.round(o/24);return i.format(-s,`day`)}function qe(e){return e.status===`queued`||e.status===`running`}function Je(e){return e.status===`failed`||e.status===`timeout`||e.status===`cancelled`}var $=r(),Ye=(0,Z.memo)(function(e){let t=(0,Q.c)(65),{run:n,language:r,localeTag:i,nowMs:o,selected:s,onOpen:c,onOpenChat:l,onCancel:u,onRetry:d}=e,f=a(r).workflows,[p,h]=(0,Z.useState)(!1),g;t[0]===n?g=t[1]:(g=je(n),t[0]=n,t[1]=g);let _=!g,v;t[2]===n?v=t[3]:(v=qe(n),t[2]=n,t[3]=v);let y=v,b=n.status===`running`||n.status===`queued`,x;t[4]!==n.metrics.agentCount||t[5]!==n.metrics.doneAgentCount?(x=n.metrics.agentCount>0?Math.round(n.metrics.doneAgentCount/n.metrics.agentCount*100):0,t[4]=n.metrics.agentCount,t[5]=n.metrics.doneAgentCount,t[6]=x):x=t[6];let S=x,C=n.metrics.errorAgentCount>0,w=n.startedAtMs??n.createdAtMs,T=we(y?o-w:n.metrics.durationMs),E=X(f.taskArtifacts,{count:n.metrics.artifactCount}),D;t[7]===n?D=t[8]:(D=Fe(n),t[7]=n,t[8]=D);let O=D,k;t[9]===n?k=t[10]:(k=Ie(n),t[9]=n,t[10]=k);let A=k,ee;t[11]!==c||t[12]!==n?(ee=()=>{c(n)},t[11]=c,t[12]=n,t[13]=ee):ee=t[13];let te=ee,j;t[14]!==_||t[15]!==l||t[16]!==n?(j=()=>{_||l(n)},t[14]=_,t[15]=l,t[16]=n,t[17]=j):j=t[17];let M=j,N=s?`border-accent/70 ring-1 ring-accent/30`:`border-edge`,F;t[18]===N?F=t[19]:(F=P(`group relative overflow-hidden rounded-xl border bg-surface-panel p-3.5 transition-colors`,N,`hover:border-edge-strong hover:bg-surface-hover/50`),t[18]=N,t[19]=F);let ne;t[20]===Symbol.for(`react.memo_cache_sentinel`)?(ne=P(`w-full text-left`,ce.focusRingPanel),t[20]=ne):ne=t[20];let I;t[21]===O?I=t[22]:(I=(0,$.jsx)(`div`,{className:`line-clamp-2 text-sm font-semibold leading-5 text-fg`,children:O}),t[21]=O,t[22]=I);let re;t[23]===A?re=t[24]:(re=(0,$.jsx)(`div`,{className:`mt-1 truncate text-[11px] font-medium text-fg-muted`,children:A}),t[23]=A,t[24]=re);let ie;t[25]!==I||t[26]!==re?(ie=(0,$.jsxs)(`div`,{className:`min-w-0`,children:[I,re]}),t[25]=I,t[26]=re,t[27]=ie):ie=t[27];let ae;t[28]===n.status?ae=t[29]:(ae=P(`shrink-0 rounded-full px-2 py-0.5 text-[10px] font-semibold shadow-sm`,De(n.status)),t[28]=n.status,t[29]=ae);let L;t[30]!==i||t[31]!==o||t[32]!==w?(L=Ke(w,o,i),t[30]=i,t[31]=o,t[32]=w,t[33]=L):L=t[33];let R;t[34]===L?R=t[35]:(R=(0,$.jsx)(`span`,{children:L}),t[34]=L,t[35]=R);let z=T===`—`?null:(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{"aria-hidden":!0,children:`·`}),(0,$.jsx)(`span`,{children:X(f.taskElapsed,{duration:T})})]}),oe;t[36]!==R||t[37]!==z?(oe=(0,$.jsxs)(`div`,{className:`mt-2 flex flex-wrap items-center gap-1.5 text-[11px] text-fg-subtle`,children:[R,z]}),t[36]=R,t[37]=z,t[38]=oe):oe=t[38];let se=n.metrics.artifactCount>0?(0,$.jsx)(`span`,{className:`rounded-full bg-surface-hover px-2 py-0.5 font-medium text-fg-muted`,children:E}):null,B=s?(0,$.jsx)(`span`,{className:`font-medium text-accent-fg`,children:f.taskOpenDetails}):null,V;t[39]!==se||t[40]!==B?(V=(0,$.jsxs)(`div`,{className:`mt-3 flex flex-wrap items-center gap-2 text-[11px] text-fg-subtle`,children:[se,B]}),t[39]=se,t[40]=B,t[41]=V):V=t[41];let H;t[42]===h?H=t[43]:(H=()=>h(Ze),t[42]=h,t[43]=H);let U;t[44]===Symbol.for(`react.memo_cache_sentinel`)?(U=(0,$.jsx)(ue,{className:`size-4`,"aria-hidden":!0}),t[44]=U):U=t[44];let W;t[45]!==f.taskActionsAria||t[46]!==p||t[47]!==H?(W=(0,$.jsx)(q,{variant:`ghost`,className:`size-7 p-0 opacity-0 group-hover:opacity-100 group-focus-within:opacity-100`,"aria-label":f.taskActionsAria,"aria-expanded":p,onClick:H,children:U}),t[45]=f.taskActionsAria,t[46]=p,t[47]=H,t[48]=W):W=t[48];let G;t[49]!==y||t[50]!==_||t[51]!==M||t[52]!==f.cancel||t[53]!==f.continueInChat||t[54]!==f.rerun||t[55]!==f.taskCloseMenu||t[56]!==p||t[57]!==u||t[58]!==d||t[59]!==n||t[60]!==h?(G=p?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`button`,{type:`button`,className:`fixed inset-0 z-10 cursor-default`,"aria-label":f.taskCloseMenu,onClick:()=>h(!1)}),(0,$.jsxs)(`div`,{className:`absolute right-0 z-20 mt-1 min-w-36 rounded-lg border border-edge bg-surface-panel py-1 shadow-surface`,children:[(0,$.jsx)(Xe,{label:f.continueInChat,disabled:_,onClick:()=>{h(!1),M()}}),y?(0,$.jsx)(Xe,{label:f.cancel,tone:`danger`,onClick:()=>{h(!1),u(n.id)}}):null,Je(n)?(0,$.jsx)(Xe,{label:f.rerun,onClick:()=>{h(!1),d(n.id)}}):null]})]}):null,t[49]=y,t[50]=_,t[51]=M,t[52]=f.cancel,t[53]=f.continueInChat,t[54]=f.rerun,t[55]=f.taskCloseMenu,t[56]=p,t[57]=u,t[58]=d,t[59]=n,t[60]=h,t[61]=G):G=t[61];let K;return t[62]!==W||t[63]!==G?(K=(0,$.jsxs)(`div`,{className:`absolute right-2 top-2`,children:[W,G]}),t[62]=W,t[63]=G,t[64]=K):K=t[64],(0,$.jsxs)(`div`,{className:F,children:[(0,$.jsxs)(`button`,{type:`button`,onClick:te,"aria-label":`${f.taskOpenDetails}: ${O}`,"aria-current":s?`true`:void 0,className:ne,children:[(0,$.jsxs)(`div`,{className:`pr-7`,children:[(0,$.jsxs)(`div`,{className:`flex min-w-0 items-start justify-between gap-2`,children:[ie,(0,$.jsx)(`span`,{className:ae,children:f.status[n.status]??n.status})]}),oe]}),b?(0,$.jsxs)(`div`,{className:`mt-2.5`,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-2 text-[11px] text-fg-muted`,children:[(0,$.jsx)(`span`,{children:X(f.agentProgress,{done:n.metrics.doneAgentCount,total:n.metrics.agentCount})}),(0,$.jsxs)(`span`,{children:[S,`%`]})]}),(0,$.jsx)(`div`,{className:`mt-1.5 h-1.5 overflow-hidden rounded-full bg-surface-hover`,children:(0,$.jsx)(`div`,{className:`h-full rounded-full bg-accent transition-all`,style:{width:`${S}%`}})})]}):null,V,C?(0,$.jsxs)(`div`,{className:`mt-2 flex items-center gap-1 text-[11px] text-amber-700 dark:text-amber-300`,children:[(0,$.jsx)(m,{className:`size-3 shrink-0`,"aria-hidden":!0}),X(f.runRowErrorSummary,{count:n.metrics.errorAgentCount})]}):null]}),K]})});function Xe(e){let t=(0,Q.c)(8),{label:n,disabled:r,tone:i,onClick:a}=e,o=r?`cursor-not-allowed text-fg-subtle`:`text-fg hover:bg-surface-hover`,s=i===`danger`&&!r&&`text-red-600 dark:text-red-300`,c;t[0]!==o||t[1]!==s?(c=P(`block w-full px-3 py-1.5 text-left text-xs`,o,s),t[0]=o,t[1]=s,t[2]=c):c=t[2];let l;return t[3]!==r||t[4]!==n||t[5]!==a||t[6]!==c?(l=(0,$.jsx)(`button`,{type:`button`,disabled:r,onClick:a,className:c,children:n}),t[3]=r,t[4]=n,t[5]=a,t[6]=c,t[7]=l):l=t[7],l}function Ze(e){return!e}function Qe(e,t){return t.boardColumns[e]}var $e=(0,Z.memo)(function(e){let t=(0,Q.c)(14),{column:n,language:r,localeTag:i,nowMs:o,selectedRunId:s,onOpenRun:c,onOpenRunChat:l,onCancelRun:u,onRetryRun:d}=e,f=a(r).workflows,[p,m]=(0,Z.useState)(!1),h=n.id===`succeeded`,g=h?5:n.runs.length,_;t[0]!==g||t[1]!==n.runs||t[2]!==p||t[3]!==h?(_=h&&!p?n.runs.slice(0,g):n.runs,t[0]=g,t[1]=n.runs,t[2]=p,t[3]=h,t[4]=_):_=t[4];let v=_,y=h&&n.runs.length>5&&!p,b=h&&p,x;t[5]===Symbol.for(`react.memo_cache_sentinel`)?(x=P(`flex min-h-112 w-73 shrink-0 snap-center flex-col rounded-2xl border border-edge bg-surface-panel/40`),t[5]=x):x=t[5];let S;t[6]===Symbol.for(`react.memo_cache_sentinel`)?(S=(0,$.jsx)(`span`,{className:`size-2 rounded-full bg-accent`,"aria-hidden":!0}),t[6]=S):S=t[6];let C;t[7]===n.runs.length?C=t[8]:(C=(0,$.jsx)(`span`,{className:`rounded-full bg-surface-hover px-2.5 py-1 text-xs font-semibold tabular-nums text-fg-muted`,children:n.runs.length}),t[7]=n.runs.length,t[8]=C);let w=v.length===0?(0,$.jsx)(`div`,{className:`flex min-h-32 items-center justify-center rounded-xl border border-dashed border-edge bg-surface-panel/40 px-4 py-6 text-center text-xs text-fg-subtle`,children:f.boardColumnEmpty}):v.map(e=>(0,$.jsx)(Ye,{run:e,language:r,localeTag:i,nowMs:o,selected:e.id===s,onOpen:c,onOpenChat:l,onCancel:u,onRetry:d},e.id)),T=y?(0,$.jsx)(q,{variant:`ghost`,className:`h-8 w-full text-xs`,onClick:()=>m(!0),children:X(f.boardExpandSucceeded,{count:Math.min(n.runs.length,n.totalInWindow??n.runs.length)})}):null,E=b?(0,$.jsx)(q,{variant:`ghost`,className:`h-8 w-full text-xs`,onClick:()=>m(!1),children:f.boardCollapseSucceeded}):null,D=h&&(n.hiddenByCap??0)>0?(0,$.jsx)(`p`,{className:`px-1 text-center text-[11px] text-fg-subtle`,children:X(f.boardSucceededCapHint,{count:n.hiddenByCap??0})}):null,O;return t[9]!==w||t[10]!==T||t[11]!==E||t[12]!==D?(O=(0,$.jsxs)(`div`,{className:`flex flex-1 flex-col gap-3 p-2.5`,children:[w,T,E,D]}),t[9]=w,t[10]=T,t[11]=E,t[12]=D,t[13]=O):O=t[13],(0,$.jsxs)(`section`,{className:x,"aria-label":Qe(n.id,f),children:[(0,$.jsxs)(`header`,{className:`sticky top-0 z-10 flex items-center justify-between gap-2 rounded-t-2xl border-b border-edge-subtle bg-surface-panel/90 px-3.5 py-3 backdrop-blur`,children:[(0,$.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[S,(0,$.jsx)(`h2`,{className:`truncate text-sm font-semibold text-fg`,children:Qe(n.id,f)})]}),C]}),O]})}),et=(0,Z.memo)(function(e){let t=(0,Q.c)(45),{runs:n,language:r,localeTag:i,labels:a,searchQuery:o,workflowFilterId:s,triggerFilter:c,selectedRunId:l,loading:u,onOpenRun:d,onOpenRunChat:f,onCancelRun:p,onRetryRun:m,onStart:h}=e,g;t[0]===n?g=t[1]:(g=n.some(tt),t[0]=n,t[1]=g);let _=g,[v,y]=(0,Z.useState)(nt),b,x;t[2]===_?(b=t[3],x=t[4]):(b=()=>{if(!_)return;let e=window.setInterval(()=>y(Date.now()),1e3);return()=>window.clearInterval(e)},x=[_],t[2]=_,t[3]=b,t[4]=x),(0,Z.useEffect)(b,x);let S;t[5]!==v||t[6]!==n||t[7]!==o||t[8]!==c||t[9]!==s?(S=Ue(Re(n,{searchQuery:o,workflowFilterId:s,triggerFilter:c}),v),t[5]=v,t[6]=n,t[7]=o,t[8]=c,t[9]=s,t[10]=S):S=t[10];let C=S,w=C.reduce(rt,0);if(u&&w===0){let e;return t[11]===a.loading?e=t[12]:(e=(0,$.jsx)(`p`,{className:`text-sm text-fg-muted`,children:a.loading}),t[11]=a.loading,t[12]=e),e}if(!u&&w===0){let e;t[13]===a.boardEmptyTitle?e=t[14]:(e=(0,$.jsx)(`p`,{className:`text-sm font-medium text-fg`,children:a.boardEmptyTitle}),t[13]=a.boardEmptyTitle,t[14]=e);let n;t[15]===a.boardEmptyHint?n=t[16]:(n=(0,$.jsx)(`p`,{className:`mx-auto mt-2 max-w-md text-sm leading-6 text-fg-muted`,children:a.boardEmptyHint}),t[15]=a.boardEmptyHint,t[16]=n);let r;t[17]!==a.boardStart||t[18]!==h?(r=(0,$.jsx)(`div`,{className:`mt-4 flex justify-center`,children:(0,$.jsx)(q,{variant:`primary`,onClick:h,children:a.boardStart})}),t[17]=a.boardStart,t[18]=h,t[19]=r):r=t[19];let i;return t[20]!==e||t[21]!==n||t[22]!==r?(i=(0,$.jsxs)(`div`,{className:`rounded-2xl border border-dashed border-edge bg-surface-panel/40 px-6 py-12 text-center`,children:[e,n,r]}),t[20]=e,t[21]=n,t[22]=r,t[23]=i):i=t[23],i}let T;if(t[24]!==C||t[25]!==r||t[26]!==i||t[27]!==v||t[28]!==p||t[29]!==d||t[30]!==f||t[31]!==m||t[32]!==l){let e;t[34]!==r||t[35]!==i||t[36]!==v||t[37]!==p||t[38]!==d||t[39]!==f||t[40]!==m||t[41]!==l?(e=e=>(0,$.jsx)($e,{column:e,language:r,localeTag:i,nowMs:v,selectedRunId:l,onOpenRun:d,onOpenRunChat:f,onCancelRun:p,onRetryRun:m},e.id),t[34]=r,t[35]=i,t[36]=v,t[37]=p,t[38]=d,t[39]=f,t[40]=m,t[41]=l,t[42]=e):e=t[42],T=C.map(e),t[24]=C,t[25]=r,t[26]=i,t[27]=v,t[28]=p,t[29]=d,t[30]=f,t[31]=m,t[32]=l,t[33]=T}else T=t[33];let E;return t[43]===T?E=t[44]:(E=(0,$.jsx)(`div`,{className:`-mx-1 flex min-w-0 snap-x snap-mandatory gap-3 overflow-x-auto px-1 pb-2`,children:T}),t[43]=T,t[44]=E),E});function tt(e){return e.status===`queued`||e.status===`running`}function nt(){return Date.now()}function rt(e,t){return e+t.runs.length}function it(e){let t=(0,Q.c)(45),{open:n,definition:r,language:i,onClose:o,onRun:s}=e,c;t[0]===i?c=t[1]:(c=a(i),t[0]=i,t[1]=c);let l=c.workflows;if(!r)return null;let u;t[2]!==r||t[3]!==i?(u=xe(r,i),t[2]=r,t[3]=i,t[4]=u):u=t[4];let d=u,f=r.runtime?.source??``,p;t[5]===o?p=t[6]:(p=e=>!e&&o(),t[5]=o,t[6]=p);let m;t[7]===Symbol.for(`react.memo_cache_sentinel`)?(m=(0,$.jsx)(y,{className:`xopc-dialog-overlay fixed inset-0 z-65 bg-scrim backdrop-blur-[1px]`}),t[7]=m):m=t[7];let h;t[8]===r.title?h=t[9]:(h=(0,$.jsx)(R,{className:`text-base font-semibold text-fg`,children:r.title}),t[8]=r.title,t[9]=h);let g;t[10]===d.description?g=t[11]:(g=(0,$.jsx)(O,{className:`mt-1 text-sm text-fg-muted`,children:d.description}),t[10]=d.description,t[11]=g);let v;t[12]!==h||t[13]!==g?(v=(0,$.jsxs)(`div`,{className:`border-b border-edge px-5 py-4`,children:[h,g]}),t[12]=h,t[13]=g,t[14]=v):v=t[14];let b;t[15]!==l.whenToUseHeading||t[16]!==d.whenToUse?(b=d.whenToUse?(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h3`,{className:`text-xs font-semibold uppercase tracking-wide text-fg-subtle`,children:l.whenToUseHeading}),(0,$.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-fg-muted`,children:d.whenToUse})]}):null,t[15]=l.whenToUseHeading,t[16]=d.whenToUse,t[17]=b):b=t[17];let x;t[18]!==r.phases||t[19]!==l.phasesHeading?(x=r.phases.length>0?(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h3`,{className:`text-xs font-semibold uppercase tracking-wide text-fg-subtle`,children:l.phasesHeading}),(0,$.jsx)(`ol`,{className:`mt-2 space-y-2`,children:r.phases.map(at)})]}):null,t[18]=r.phases,t[19]=l.phasesHeading,t[20]=x):x=t[20];let C;t[21]!==l.scriptHeading||t[22]!==f?(C=f?(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h3`,{className:`text-xs font-semibold uppercase tracking-wide text-fg-subtle`,children:l.scriptHeading}),(0,$.jsx)(`pre`,{className:`mt-2 max-h-64 overflow-auto rounded-xl border border-edge bg-surface-base/50 p-3 font-mono text-xs leading-5 text-fg-muted`,children:f})]}):null,t[21]=l.scriptHeading,t[22]=f,t[23]=C):C=t[23];let w;t[24]!==C||t[25]!==b||t[26]!==x?(w=(0,$.jsxs)(`div`,{className:`min-h-0 flex-1 space-y-4 overflow-auto px-5 py-4`,children:[b,x,C]}),t[24]=C,t[25]=b,t[26]=x,t[27]=w):w=t[27];let T;t[28]!==l.closeResult||t[29]!==o?(T=(0,$.jsx)(q,{variant:`secondary`,onClick:o,children:l.closeResult}),t[28]=l.closeResult,t[29]=o,t[30]=T):T=t[30];let E;t[31]!==l.runWorkflow||t[32]!==s?(E=(0,$.jsx)(q,{variant:`primary`,onClick:s,children:l.runWorkflow}),t[31]=l.runWorkflow,t[32]=s,t[33]=E):E=t[33];let D;t[34]!==T||t[35]!==E?(D=(0,$.jsxs)(`div`,{className:`flex justify-end gap-2 border-t border-edge px-5 py-4`,children:[T,E]}),t[34]=T,t[35]=E,t[36]=D):D=t[36];let k;t[37]!==w||t[38]!==D||t[39]!==v?(k=(0,$.jsxs)(_,{children:[m,(0,$.jsxs)(pe,{className:`fixed left-1/2 top-1/2 z-66 flex max-h-[min(85vh,44rem)] w-[min(100%-2rem,48rem)] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-2xl border border-edge bg-surface-panel shadow-popover outline-none`,children:[v,w,D]})]}),t[37]=w,t[38]=D,t[39]=v,t[40]=k):k=t[40];let A;return t[41]!==n||t[42]!==k||t[43]!==p?(A=(0,$.jsx)(S,{open:n,onOpenChange:p,children:k}),t[41]=n,t[42]=k,t[43]=p,t[44]=A):A=t[44],A}function at(e,t){return(0,$.jsxs)(`li`,{className:`rounded-xl border border-edge bg-surface-base/40 px-3 py-2`,children:[(0,$.jsxs)(`div`,{className:`text-sm font-medium text-fg`,children:[t+1,`. `,e.title]}),e.description?(0,$.jsx)(`p`,{className:`mt-1 text-xs leading-5 text-fg-muted`,children:e.description}):null]},e.id)}function ot({open:e,language:t,saving:n,onClose:r,onSave:i}){let o=a(t).workflows,[s,c]=(0,Z.useState)(``),[l,u]=(0,Z.useState)(``),[d,f]=(0,Z.useState)(!1),[p,m]=(0,Z.useState)(!1),[h,g]=(0,Z.useState)(null),[v,b]=(0,Z.useState)(null);(0,Z.useEffect)(()=>{e&&(c(``),f(!1),m(!1),g(null),b(null),u(`export const meta = {
2
2
  name: 'my_workflow',
3
3
  description: 'Describe what this workflow does.',
4
4
  whenToUse: 'When the user asks for …',
@@ -9,21 +9,21 @@
9
9
  <link rel="icon" type="image/svg+xml" href="/logo.svg" />
10
10
  <link rel="apple-touch-icon" href="/logo.svg" />
11
11
  <title>xopc</title>
12
- <script type="module" crossorigin src="/assets/index-DKgHC1Ta.js"></script>
12
+ <script type="module" crossorigin src="/assets/index-0HmunJW9.js"></script>
13
13
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-aKtaBQYM.js">
14
14
  <link rel="modulepreload" crossorigin href="/assets/preload-helper-zJ_50EbN.js">
15
15
  <link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-DYoKfS8f.js">
16
16
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-BOUWij0V.js">
17
17
  <link rel="modulepreload" crossorigin href="/assets/Combination-HAlzriaz.js">
18
18
  <link rel="modulepreload" crossorigin href="/assets/vendor-swr-BIWyz7Rc.js">
19
- <link rel="modulepreload" crossorigin href="/assets/url-q28QhI7l.js">
19
+ <link rel="modulepreload" crossorigin href="/assets/url-F3_D_6zZ.js">
20
20
  <link rel="modulepreload" crossorigin href="/assets/createLucideIcon-DPHK1VkS.js">
21
21
  <link rel="modulepreload" crossorigin href="/assets/circle-check-C23XjkUj.js">
22
22
  <link rel="modulepreload" crossorigin href="/assets/copy-Dv6d4Dvw.js">
23
- <link rel="modulepreload" crossorigin href="/assets/theme-store-B6KXPHgK.js">
24
- <link rel="modulepreload" crossorigin href="/assets/fetch-drJUxxKP.js">
23
+ <link rel="modulepreload" crossorigin href="/assets/theme-store-HTvJlFLL.js">
24
+ <link rel="modulepreload" crossorigin href="/assets/fetch-CMoWY2Si.js">
25
25
  <link rel="modulepreload" crossorigin href="/assets/toast-z0toXu32.js">
26
- <link rel="stylesheet" crossorigin href="/assets/index-DjNDHzwG.css">
26
+ <link rel="stylesheet" crossorigin href="/assets/index-Bk75Phrd.css">
27
27
  </head>
28
28
  <body>
29
29
  <div id="root"></div>
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.0.102";
2
+ var version = "0.0.103";
3
3
  //#endregion
4
4
  export { version };
5
5
 
@@ -49,7 +49,7 @@ async function readImageBase64FromRef(ref) {
49
49
  const loaded = await readMediaReferenceBase64(ref.uri, VISION_INLINE_MAX_BYTES);
50
50
  return {
51
51
  data: loaded.data,
52
- mimeType: ref.mimeType?.startsWith("image/") ? ref.mimeType : loaded.mimeType
52
+ mimeType: ref.mimeType || loaded.mimeType
53
53
  };
54
54
  }
55
55
  function appendMediaAttachedLines(textParts, media) {
@@ -80,7 +80,7 @@ async function buildTranscriptUserMessage(opts) {
80
80
  const textParts = [];
81
81
  if (expandedText) textParts.push(expandedText);
82
82
  const strategy = resolveImageHandlingStrategy(opts.modelRef);
83
- if (strategy !== "native") appendMediaAttachedLines(textParts, prepared.filter((m) => !isImageInboundAttachment(m)));
83
+ appendMediaAttachedLines(textParts, prepared.filter((m) => !isImageInboundAttachment(m)));
84
84
  if (imageRefs.length > 0 && strategy !== "native") {
85
85
  const images = await Promise.all(imageRefs.map((ref) => readImageBase64FromRef(ref)));
86
86
  const parts = await resolveInboundImageContentParts({
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-pipeline.js","names":[],"sources":["../../../../src/agent/inbound/attachment-pipeline.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { ImageContent } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport {\n isImageInboundAttachment,\n type MediaRef,\n} from '../../channels/attachments/inbound-persist.js';\nimport { readMediaReferenceBase64 } from '../../media/media-reference.js';\nimport { expandAtFileMentionsInPlainText } from '../context/expand-at-file-mentions.js';\nimport { readAgentMessageContent } from '../memory/agent-message-access.js';\nimport { resolveInboundImageContentParts } from '../image/inbound-image-handling.js';\nimport { resolveImageHandlingStrategy } from '../image/vision-detection.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\n\nexport type TranscriptUserMessage = AgentMessage & {\n media?: MediaRef[];\n MediaPath?: string;\n MediaPaths?: string[];\n MediaTypes?: string[];\n};\n\nexport type LlmUserTurn = {\n text: string;\n images: ImageContent[];\n};\n\nconst VISION_INLINE_MAX_BYTES = 2 * 1024 * 1024;\n\nfunction textBlocksFromContent(content: unknown): string[] {\n if (typeof content === 'string') {\n return content.trim() ? [content] : [];\n }\n if (!Array.isArray(content)) {\n return [];\n }\n const out: string[] = [];\n for (const block of content) {\n if (block && typeof block === 'object' && (block as { type?: string }).type === 'text') {\n const t = (block as { text?: string }).text;\n if (typeof t === 'string' && t.trim()) {\n out.push(t);\n }\n }\n }\n return out;\n}\n\nfunction joinTextBlocks(parts: string[]): string {\n return parts.join('\\n').trim();\n}\n\nfunction buildMediaPathFields(media: MediaRef[]): Pick<TranscriptUserMessage, 'MediaPath' | 'MediaPaths' | 'MediaTypes'> {\n if (!media.length) return {};\n return {\n MediaPath: media[0]!.path,\n MediaPaths: media.map((m) => m.path),\n MediaTypes: media.map((m) => m.mimeType),\n };\n}\n\nfunction assertUserContentHasNoInlineMedia(content: unknown): void {\n if (!Array.isArray(content)) {\n return;\n }\n for (const block of content) {\n if (!block || typeof block !== 'object') {\n continue;\n }\n const type = (block as { type?: string }).type;\n if (type === 'image') {\n throw new Error('User transcript content must not contain image blocks');\n }\n }\n}\n\nexport function assertTranscriptUserMessage(message: AgentMessage): void {\n if ((message as { role?: string }).role !== 'user') {\n return;\n }\n assertUserContentHasNoInlineMedia((message as { content?: unknown }).content);\n const media = (message as TranscriptUserMessage).media;\n if (!media?.length) {\n return;\n }\n for (const ref of media) {\n if (!ref.uri?.trim()) {\n throw new Error('User transcript media ref missing uri');\n }\n if ('data' in ref && typeof (ref as { data?: unknown }).data === 'string') {\n throw new Error('User transcript media ref must not include data');\n }\n }\n}\n\nasync function readImageBase64FromRef(ref: MediaRef): Promise<{ data: string; mimeType: string }> {\n const loaded = await readMediaReferenceBase64(ref.uri, VISION_INLINE_MAX_BYTES);\n return {\n data: loaded.data,\n mimeType: ref.mimeType?.startsWith('image/') ? ref.mimeType : loaded.mimeType,\n };\n}\n\nfunction appendMediaAttachedLines(textParts: string[], media: MediaRef[]): void {\n for (const ref of media) {\n if (!isImageInboundAttachment(ref)) {\n textParts.push(\n [\n `[media attached: ${ref.name} (${ref.mimeType}, ${ref.size} bytes)]`,\n `xopc-media-uri:${ref.uri}`,\n `xopc-media-path:${ref.path}`,\n 'Use the read_media tool with the xopc-media-uri value when you need to inspect this attachment.',\n ].join('\\n'),\n );\n }\n }\n}\n\nasync function expandUserText(\n text: string,\n sessionKey: string,\n agentManager: AgentInstanceGateway,\n): Promise<string> {\n if (!text.trim()) {\n return '';\n }\n let out = text;\n if (/@file:/.test(out)) {\n const wsKey = sessionKey || 'agent:main:main';\n const root = agentManager.getResolvedWorkspaceForSession(wsKey);\n out = await expandAtFileMentionsInPlainText(out, root);\n }\n return out.trim();\n}\n\n/**\n * Build the transcript row for a user turn (text + media metadata only).\n */\nexport async function buildTranscriptUserMessage(opts: {\n text: string;\n prepared: MediaRef[] | undefined;\n sessionKey: string;\n modelRef: string;\n config: Config | undefined;\n agentManager: AgentInstanceGateway;\n}): Promise<TranscriptUserMessage> {\n const expandedText = await expandUserText(opts.text, opts.sessionKey, opts.agentManager);\n const prepared = opts.prepared ?? [];\n const imageRefs = prepared.filter(isImageInboundAttachment);\n\n const textParts: string[] = [];\n if (expandedText) {\n textParts.push(expandedText);\n }\n\n const strategy = resolveImageHandlingStrategy(opts.modelRef);\n\n if (strategy !== 'native') {\n appendMediaAttachedLines(textParts, prepared.filter((m) => !isImageInboundAttachment(m)));\n }\n\n if (imageRefs.length > 0 && strategy !== 'native') {\n const images = await Promise.all(imageRefs.map((ref) => readImageBase64FromRef(ref)));\n const parts = await resolveInboundImageContentParts({\n modelRef: opts.modelRef,\n cfg: opts.config,\n userTextForContext: expandedText,\n images,\n });\n for (const part of parts) {\n if (part.type === 'text' && part.text.trim()) {\n textParts.push(part.text.trim());\n }\n }\n }\n\n if (textParts.length === 0 && prepared.length > 0) {\n textParts.push('Please analyze the attachment(s) I sent.');\n }\n\n const content = joinTextBlocks(textParts);\n const message: TranscriptUserMessage = {\n role: 'user',\n content,\n timestamp: Date.now(),\n ...(prepared.length > 0 ? { media: prepared, ...buildMediaPathFields(prepared) } : {}),\n };\n assertTranscriptUserMessage(message);\n return message;\n}\n\n/** Hydrate images from media store for the current LLM prompt. */\nexport async function hydrateUserTurnForLlm(opts: {\n message: TranscriptUserMessage;\n modelRef: string;\n}): Promise<LlmUserTurn> {\n const text = joinTextBlocks(textBlocksFromContent(readAgentMessageContent(opts.message)));\n const media = opts.message.media ?? [];\n const images: ImageContent[] = [];\n\n if (resolveImageHandlingStrategy(opts.modelRef) === 'native') {\n for (const ref of media.filter(isImageInboundAttachment)) {\n const loaded = await readImageBase64FromRef(ref);\n images.push({ type: 'image', data: loaded.data, mimeType: loaded.mimeType });\n }\n }\n\n return { text, images };\n}\n\nconst pendingTranscriptBySession = new Map<string, TranscriptUserMessage>();\n\nfunction messageTextForPendingCompare(message: AgentMessage): string {\n return joinTextBlocks(textBlocksFromContent(readAgentMessageContent(message)));\n}\n\nfunction pendingMatchesMessage(pending: TranscriptUserMessage, message: AgentMessage): boolean {\n const pendingText = messageTextForPendingCompare(pending);\n const actualText = messageTextForPendingCompare(message);\n if (!pendingText) {\n return true;\n }\n if (!actualText) {\n return false;\n }\n return actualText.includes(pendingText) || pendingText.includes(actualText);\n}\n\nexport function setPendingTranscriptUserMessage(sessionKey: string, message: TranscriptUserMessage): void {\n assertTranscriptUserMessage(message);\n pendingTranscriptBySession.set(sessionKey, message);\n}\n\nexport function takePendingTranscriptUserMessage(sessionKey: string): TranscriptUserMessage | undefined {\n const msg = pendingTranscriptBySession.get(sessionKey);\n pendingTranscriptBySession.delete(sessionKey);\n return msg;\n}\n\nexport function clearPendingTranscriptUserMessage(sessionKey: string, message?: TranscriptUserMessage): void {\n const existing = pendingTranscriptBySession.get(sessionKey);\n if (!existing) {\n return;\n }\n if (message && existing !== message) {\n return;\n }\n pendingTranscriptBySession.delete(sessionKey);\n}\n\nexport function pendingTranscriptReferencesMediaUri(sessionKey: string, uri: string): boolean {\n const pending = pendingTranscriptBySession.get(sessionKey);\n return pending?.media?.some((ref) => ref.uri === uri.trim()) === true;\n}\n\nexport function transformUserMessageForPersistence(\n sessionKey: string | undefined,\n message: AgentMessage,\n): AgentMessage {\n if ((message as { role?: string }).role !== 'user') {\n return message;\n }\n if (sessionKey) {\n const pending = pendingTranscriptBySession.get(sessionKey);\n if (pending && pendingMatchesMessage(pending, message)) {\n pendingTranscriptBySession.delete(sessionKey);\n return pending;\n }\n }\n assertTranscriptUserMessage(message);\n return message;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"attachment-pipeline.js","names":[],"sources":["../../../../src/agent/inbound/attachment-pipeline.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { ImageContent } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport {\n isImageInboundAttachment,\n type MediaRef,\n} from '../../channels/attachments/inbound-persist.js';\nimport { readMediaReferenceBase64 } from '../../media/media-reference.js';\nimport { expandAtFileMentionsInPlainText } from '../context/expand-at-file-mentions.js';\nimport { readAgentMessageContent } from '../memory/agent-message-access.js';\nimport { resolveInboundImageContentParts } from '../image/inbound-image-handling.js';\nimport { resolveImageHandlingStrategy } from '../image/vision-detection.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\n\nexport type TranscriptUserMessage = AgentMessage & {\n media?: MediaRef[];\n MediaPath?: string;\n MediaPaths?: string[];\n MediaTypes?: string[];\n};\n\nexport type LlmUserTurn = {\n text: string;\n images: ImageContent[];\n};\n\nconst VISION_INLINE_MAX_BYTES = 2 * 1024 * 1024;\n\nfunction textBlocksFromContent(content: unknown): string[] {\n if (typeof content === 'string') {\n return content.trim() ? [content] : [];\n }\n if (!Array.isArray(content)) {\n return [];\n }\n const out: string[] = [];\n for (const block of content) {\n if (block && typeof block === 'object' && (block as { type?: string }).type === 'text') {\n const t = (block as { text?: string }).text;\n if (typeof t === 'string' && t.trim()) {\n out.push(t);\n }\n }\n }\n return out;\n}\n\nfunction joinTextBlocks(parts: string[]): string {\n return parts.join('\\n').trim();\n}\n\nfunction buildMediaPathFields(media: MediaRef[]): Pick<TranscriptUserMessage, 'MediaPath' | 'MediaPaths' | 'MediaTypes'> {\n if (!media.length) return {};\n return {\n MediaPath: media[0]!.path,\n MediaPaths: media.map((m) => m.path),\n MediaTypes: media.map((m) => m.mimeType),\n };\n}\n\nfunction assertUserContentHasNoInlineMedia(content: unknown): void {\n if (!Array.isArray(content)) {\n return;\n }\n for (const block of content) {\n if (!block || typeof block !== 'object') {\n continue;\n }\n const type = (block as { type?: string }).type;\n if (type === 'image') {\n throw new Error('User transcript content must not contain image blocks');\n }\n }\n}\n\nexport function assertTranscriptUserMessage(message: AgentMessage): void {\n if ((message as { role?: string }).role !== 'user') {\n return;\n }\n assertUserContentHasNoInlineMedia((message as { content?: unknown }).content);\n const media = (message as TranscriptUserMessage).media;\n if (!media?.length) {\n return;\n }\n for (const ref of media) {\n if (!ref.uri?.trim()) {\n throw new Error('User transcript media ref missing uri');\n }\n if ('data' in ref && typeof (ref as { data?: unknown }).data === 'string') {\n throw new Error('User transcript media ref must not include data');\n }\n }\n}\n\nasync function readImageBase64FromRef(ref: MediaRef): Promise<{ data: string; mimeType: string }> {\n const loaded = await readMediaReferenceBase64(ref.uri, VISION_INLINE_MAX_BYTES);\n return {\n data: loaded.data,\n mimeType: ref.mimeType || loaded.mimeType,\n };\n}\n\nfunction appendMediaAttachedLines(textParts: string[], media: MediaRef[]): void {\n for (const ref of media) {\n if (!isImageInboundAttachment(ref)) {\n textParts.push(\n [\n `[media attached: ${ref.name} (${ref.mimeType}, ${ref.size} bytes)]`,\n `xopc-media-uri:${ref.uri}`,\n `xopc-media-path:${ref.path}`,\n 'Use the read_media tool with the xopc-media-uri value when you need to inspect this attachment.',\n ].join('\\n'),\n );\n }\n }\n}\n\nasync function expandUserText(\n text: string,\n sessionKey: string,\n agentManager: AgentInstanceGateway,\n): Promise<string> {\n if (!text.trim()) {\n return '';\n }\n let out = text;\n if (/@file:/.test(out)) {\n const wsKey = sessionKey || 'agent:main:main';\n const root = agentManager.getResolvedWorkspaceForSession(wsKey);\n out = await expandAtFileMentionsInPlainText(out, root);\n }\n return out.trim();\n}\n\n/**\n * Build the transcript row for a user turn (text + media metadata only).\n */\nexport async function buildTranscriptUserMessage(opts: {\n text: string;\n prepared: MediaRef[] | undefined;\n sessionKey: string;\n modelRef: string;\n config: Config | undefined;\n agentManager: AgentInstanceGateway;\n}): Promise<TranscriptUserMessage> {\n const expandedText = await expandUserText(opts.text, opts.sessionKey, opts.agentManager);\n const prepared = opts.prepared ?? [];\n const imageRefs = prepared.filter(isImageInboundAttachment);\n\n const textParts: string[] = [];\n if (expandedText) {\n textParts.push(expandedText);\n }\n\n const strategy = resolveImageHandlingStrategy(opts.modelRef);\n\n appendMediaAttachedLines(textParts, prepared.filter((m) => !isImageInboundAttachment(m)));\n\n if (imageRefs.length > 0 && strategy !== 'native') {\n const images = await Promise.all(imageRefs.map((ref) => readImageBase64FromRef(ref)));\n const parts = await resolveInboundImageContentParts({\n modelRef: opts.modelRef,\n cfg: opts.config,\n userTextForContext: expandedText,\n images,\n });\n for (const part of parts) {\n if (part.type === 'text' && part.text.trim()) {\n textParts.push(part.text.trim());\n }\n }\n }\n\n if (textParts.length === 0 && prepared.length > 0) {\n textParts.push('Please analyze the attachment(s) I sent.');\n }\n\n const content = joinTextBlocks(textParts);\n const message: TranscriptUserMessage = {\n role: 'user',\n content,\n timestamp: Date.now(),\n ...(prepared.length > 0 ? { media: prepared, ...buildMediaPathFields(prepared) } : {}),\n };\n assertTranscriptUserMessage(message);\n return message;\n}\n\n/** Hydrate images from media store for the current LLM prompt. */\nexport async function hydrateUserTurnForLlm(opts: {\n message: TranscriptUserMessage;\n modelRef: string;\n}): Promise<LlmUserTurn> {\n const text = joinTextBlocks(textBlocksFromContent(readAgentMessageContent(opts.message)));\n const media = opts.message.media ?? [];\n const images: ImageContent[] = [];\n\n if (resolveImageHandlingStrategy(opts.modelRef) === 'native') {\n for (const ref of media.filter(isImageInboundAttachment)) {\n const loaded = await readImageBase64FromRef(ref);\n images.push({ type: 'image', data: loaded.data, mimeType: loaded.mimeType });\n }\n }\n\n return { text, images };\n}\n\nconst pendingTranscriptBySession = new Map<string, TranscriptUserMessage>();\n\nfunction messageTextForPendingCompare(message: AgentMessage): string {\n return joinTextBlocks(textBlocksFromContent(readAgentMessageContent(message)));\n}\n\nfunction pendingMatchesMessage(pending: TranscriptUserMessage, message: AgentMessage): boolean {\n const pendingText = messageTextForPendingCompare(pending);\n const actualText = messageTextForPendingCompare(message);\n if (!pendingText) {\n return true;\n }\n if (!actualText) {\n return false;\n }\n return actualText.includes(pendingText) || pendingText.includes(actualText);\n}\n\nexport function setPendingTranscriptUserMessage(sessionKey: string, message: TranscriptUserMessage): void {\n assertTranscriptUserMessage(message);\n pendingTranscriptBySession.set(sessionKey, message);\n}\n\nexport function takePendingTranscriptUserMessage(sessionKey: string): TranscriptUserMessage | undefined {\n const msg = pendingTranscriptBySession.get(sessionKey);\n pendingTranscriptBySession.delete(sessionKey);\n return msg;\n}\n\nexport function clearPendingTranscriptUserMessage(sessionKey: string, message?: TranscriptUserMessage): void {\n const existing = pendingTranscriptBySession.get(sessionKey);\n if (!existing) {\n return;\n }\n if (message && existing !== message) {\n return;\n }\n pendingTranscriptBySession.delete(sessionKey);\n}\n\nexport function pendingTranscriptReferencesMediaUri(sessionKey: string, uri: string): boolean {\n const pending = pendingTranscriptBySession.get(sessionKey);\n return pending?.media?.some((ref) => ref.uri === uri.trim()) === true;\n}\n\nexport function transformUserMessageForPersistence(\n sessionKey: string | undefined,\n message: AgentMessage,\n): AgentMessage {\n if ((message as { role?: string }).role !== 'user') {\n return message;\n }\n if (sessionKey) {\n const pending = pendingTranscriptBySession.get(sessionKey);\n if (pending && pendingMatchesMessage(pending, message)) {\n pendingTranscriptBySession.delete(sessionKey);\n return pending;\n }\n }\n assertTranscriptUserMessage(message);\n return message;\n}\n"],"mappings":"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"}
@@ -22,8 +22,7 @@ function detectMediaType(filePath) {
22
22
  "png",
23
23
  "gif",
24
24
  "webp",
25
- "bmp",
26
- "svg"
25
+ "bmp"
27
26
  ];
28
27
  const videoExts = [
29
28
  "mp4",
@@ -1 +1 @@
1
- {"version":3,"file":"send-media.js","names":[],"sources":["../../../../src/agent/tools/send-media.ts"],"sourcesContent":["// Send media tool - allows sending local files as media\nimport { Type } from '@sinclair/typebox';\nimport { readFile } from 'fs/promises';\nimport { basename } from 'node:path';\nimport { AgentTool, type AgentToolResult } from '@earendil-works/pi-agent-core';\nimport { checkFileSafety } from '../prompt/safety.js';\nimport { resolvePathUnderWorkspace } from './tool-paths.js';\nimport type { MessageBus, OutboundMessage } from '../../infra/bus/index.js';\n\nconst SendMediaSchema = Type.Object({\n filePath: Type.String({\n description:\n 'File to send. Relative paths are under the current agent workspace; absolute paths are used as given.',\n }),\n mediaType: Type.Optional(Type.Enum({\n photo: 'photo',\n video: 'video',\n audio: 'audio',\n document: 'document',\n }, { description: 'Type of media to send (auto-detected if not specified)' })),\n caption: Type.Optional(Type.String({ description: 'Caption for the media' })),\n});\n\ninterface MessageContext {\n channel: string;\n chatId: string;\n}\n\ntype SendMediaParams = {\n filePath: string;\n mediaType?: 'photo' | 'video' | 'audio' | 'document';\n caption?: string;\n};\n\n// Detect media type from file extension\nfunction detectMediaType(filePath: string): 'photo' | 'video' | 'audio' | 'document' {\n const ext = filePath.split('.').pop()?.toLowerCase();\n const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'];\n const videoExts = ['mp4', 'mov', 'avi', 'webm', 'mkv'];\n const audioExts = ['mp3', 'wav', 'ogg', 'm4a', 'flac'];\n\n if (imageExts.includes(ext || '')) return 'photo';\n if (videoExts.includes(ext || '')) return 'video';\n if (audioExts.includes(ext || '')) return 'audio';\n return 'document';\n}\n\n// Detect MIME type from file extension\nfunction detectMimeType(filePath: string): string {\n const ext = filePath.split('.').pop()?.toLowerCase();\n const mimeMap: Record<string, string> = {\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n bmp: 'image/bmp',\n svg: 'image/svg+xml',\n mp4: 'video/mp4',\n mov: 'video/quicktime',\n avi: 'video/x-msvideo',\n webm: 'video/webm',\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n ogg: 'audio/ogg',\n m4a: 'audio/mp4',\n flac: 'audio/flac',\n pdf: 'application/pdf',\n doc: 'application/msword',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n txt: 'text/plain',\n zip: 'application/zip',\n rar: 'application/x-rar-compressed',\n };\n return mimeMap[ext || ''] || 'application/octet-stream';\n}\n\nexport function createSendMediaTool(\n workspace: string,\n bus: MessageBus,\n getContext: () => MessageContext | null,\n): AgentTool {\n return {\n name: 'send_media',\n description:\n 'Send a media file (photo, video, audio, document) to the current conversation. Relative paths resolve to the current agent workspace (same as read_file).',\n parameters: SendMediaSchema,\n label: '📎 Send Media',\n\n async execute(\n _toolCallId: string,\n params: any,\n _signal?: AbortSignal,\n ): Promise<AgentToolResult<{}>> {\n const p = params as SendMediaParams;\n const ctx = getContext();\n if (!ctx) {\n return {\n content: [{ type: 'text', text: 'Error: No active conversation context' }],\n details: {},\n };\n }\n\n const resolved = resolvePathUnderWorkspace(p.filePath, workspace);\n const safety = checkFileSafety('read', resolved);\n if (!safety.allowed) {\n return {\n content: [{ type: 'text', text: `🚫 ${safety.message}` }],\n details: {},\n };\n }\n\n try {\n const fileBuffer = await readFile(resolved);\n const base64 = fileBuffer.toString('base64');\n const mimeType = detectMimeType(resolved);\n const mediaType = p.mediaType || detectMediaType(resolved);\n\n // Create data URL\n const dataUrl = `data:${mimeType};base64,${base64}`;\n\n const msg: OutboundMessage = {\n channel: ctx.channel,\n chat_id: ctx.chatId,\n content: p.caption || '',\n mediaUrl: dataUrl,\n mediaType,\n };\n\n await bus.publishOutbound(msg);\n\n const fileName = basename(resolved);\n return {\n content: [{ type: 'text', text: `✅ Media sent: ${fileName} (${mediaType})` }],\n details: { filePath: resolved, mediaType },\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: 'text', text: `Error sending media: ${errorMessage}` }],\n details: { error: errorMessage },\n };\n }\n },\n } as any;\n}\n"],"mappings":";;;;;;AASA,MAAM,kBAAkB,KAAK,OAAO;CAClC,UAAU,KAAK,OAAO,EACpB,aACE,yGACH,CAAC;CACF,WAAW,KAAK,SAAS,KAAK,KAAK;EACjC,OAAO;EACP,OAAO;EACP,OAAO;EACP,UAAU;EACX,EAAE,EAAE,aAAa,0DAA0D,CAAC,CAAC;CAC9E,SAAS,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,yBAAyB,CAAC,CAAC;CAC9E,CAAC;AAcF,SAAS,gBAAgB,UAA4D;CACnF,MAAM,MAAM,SAAS,MAAM,IAAI,CAAC,KAAK,EAAE,aAAa;CACpD,MAAM,YAAY;EAAC;EAAO;EAAQ;EAAO;EAAO;EAAQ;EAAO;EAAM;CACrE,MAAM,YAAY;EAAC;EAAO;EAAO;EAAO;EAAQ;EAAM;CACtD,MAAM,YAAY;EAAC;EAAO;EAAO;EAAO;EAAO;EAAO;AAEtD,KAAI,UAAU,SAAS,OAAO,GAAG,CAAE,QAAO;AAC1C,KAAI,UAAU,SAAS,OAAO,GAAG,CAAE,QAAO;AAC1C,KAAI,UAAU,SAAS,OAAO,GAAG,CAAE,QAAO;AAC1C,QAAO;;AAIT,SAAS,eAAe,UAA0B;AA0BhD,QAAO;EAvBL,KAAK;EACL,MAAM;EACN,KAAK;EACL,KAAK;EACL,MAAM;EACN,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,MAAM;EACN,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,MAAM;EACN,KAAK;EACL,KAAK;EACL,MAAM;EACN,KAAK;EACL,KAAK;EACL,KAAK;EAEO,CAzBF,SAAS,MAAM,IAAI,CAAC,KAAK,EAAE,aAAa,IAyB9B,OAAO;;AAG/B,SAAgB,oBACd,WACA,KACA,YACW;AACX,QAAO;EACL,MAAM;EACN,aACE;EACF,YAAY;EACZ,OAAO;EAEP,MAAM,QACJ,aACA,QACA,SAC8B;GAC9B,MAAM,IAAI;GACV,MAAM,MAAM,YAAY;AACxB,OAAI,CAAC,IACH,QAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAQ,MAAM;KAAyC,CAAC;IAC1E,SAAS,EAAE;IACZ;GAGH,MAAM,WAAW,0BAA0B,EAAE,UAAU,UAAU;GACjE,MAAM,SAAS,gBAAgB,QAAQ,SAAS;AAChD,OAAI,CAAC,OAAO,QACV,QAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAQ,MAAM,MAAM,OAAO;KAAW,CAAC;IACzD,SAAS,EAAE;IACZ;AAGH,OAAI;IAEF,MAAM,UAAS,MADU,SAAS,SAAS,EACjB,SAAS,SAAS;IAC5C,MAAM,WAAW,eAAe,SAAS;IACzC,MAAM,YAAY,EAAE,aAAa,gBAAgB,SAAS;IAG1D,MAAM,UAAU,QAAQ,SAAS,UAAU;IAE3C,MAAM,MAAuB;KAC3B,SAAS,IAAI;KACb,SAAS,IAAI;KACb,SAAS,EAAE,WAAW;KACtB,UAAU;KACV;KACD;AAED,UAAM,IAAI,gBAAgB,IAAI;AAG9B,WAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,iBAFjB,SAAS,SAEiC,CAAC,IAAI,UAAU;MAAI,CAAC;KAC7E,SAAS;MAAE,UAAU;MAAU;MAAW;KAC3C;YACM,OAAO;IACd,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,WAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,wBAAwB;MAAgB,CAAC;KACzE,SAAS,EAAE,OAAO,cAAc;KACjC;;;EAGN"}
1
+ {"version":3,"file":"send-media.js","names":[],"sources":["../../../../src/agent/tools/send-media.ts"],"sourcesContent":["// Send media tool - allows sending local files as media\nimport { Type } from '@sinclair/typebox';\nimport { readFile } from 'fs/promises';\nimport { basename } from 'node:path';\nimport { AgentTool, type AgentToolResult } from '@earendil-works/pi-agent-core';\nimport { checkFileSafety } from '../prompt/safety.js';\nimport { resolvePathUnderWorkspace } from './tool-paths.js';\nimport type { MessageBus, OutboundMessage } from '../../infra/bus/index.js';\n\nconst SendMediaSchema = Type.Object({\n filePath: Type.String({\n description:\n 'File to send. Relative paths are under the current agent workspace; absolute paths are used as given.',\n }),\n mediaType: Type.Optional(Type.Enum({\n photo: 'photo',\n video: 'video',\n audio: 'audio',\n document: 'document',\n }, { description: 'Type of media to send (auto-detected if not specified)' })),\n caption: Type.Optional(Type.String({ description: 'Caption for the media' })),\n});\n\ninterface MessageContext {\n channel: string;\n chatId: string;\n}\n\ntype SendMediaParams = {\n filePath: string;\n mediaType?: 'photo' | 'video' | 'audio' | 'document';\n caption?: string;\n};\n\n// Detect media type from file extension\nfunction detectMediaType(filePath: string): 'photo' | 'video' | 'audio' | 'document' {\n const ext = filePath.split('.').pop()?.toLowerCase();\n const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'];\n const videoExts = ['mp4', 'mov', 'avi', 'webm', 'mkv'];\n const audioExts = ['mp3', 'wav', 'ogg', 'm4a', 'flac'];\n\n if (imageExts.includes(ext || '')) return 'photo';\n if (videoExts.includes(ext || '')) return 'video';\n if (audioExts.includes(ext || '')) return 'audio';\n return 'document';\n}\n\n// Detect MIME type from file extension\nfunction detectMimeType(filePath: string): string {\n const ext = filePath.split('.').pop()?.toLowerCase();\n const mimeMap: Record<string, string> = {\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n bmp: 'image/bmp',\n svg: 'image/svg+xml',\n mp4: 'video/mp4',\n mov: 'video/quicktime',\n avi: 'video/x-msvideo',\n webm: 'video/webm',\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n ogg: 'audio/ogg',\n m4a: 'audio/mp4',\n flac: 'audio/flac',\n pdf: 'application/pdf',\n doc: 'application/msword',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n txt: 'text/plain',\n zip: 'application/zip',\n rar: 'application/x-rar-compressed',\n };\n return mimeMap[ext || ''] || 'application/octet-stream';\n}\n\nexport function createSendMediaTool(\n workspace: string,\n bus: MessageBus,\n getContext: () => MessageContext | null,\n): AgentTool {\n return {\n name: 'send_media',\n description:\n 'Send a media file (photo, video, audio, document) to the current conversation. Relative paths resolve to the current agent workspace (same as read_file).',\n parameters: SendMediaSchema,\n label: '📎 Send Media',\n\n async execute(\n _toolCallId: string,\n params: any,\n _signal?: AbortSignal,\n ): Promise<AgentToolResult<{}>> {\n const p = params as SendMediaParams;\n const ctx = getContext();\n if (!ctx) {\n return {\n content: [{ type: 'text', text: 'Error: No active conversation context' }],\n details: {},\n };\n }\n\n const resolved = resolvePathUnderWorkspace(p.filePath, workspace);\n const safety = checkFileSafety('read', resolved);\n if (!safety.allowed) {\n return {\n content: [{ type: 'text', text: `🚫 ${safety.message}` }],\n details: {},\n };\n }\n\n try {\n const fileBuffer = await readFile(resolved);\n const base64 = fileBuffer.toString('base64');\n const mimeType = detectMimeType(resolved);\n const mediaType = p.mediaType || detectMediaType(resolved);\n\n // Create data URL\n const dataUrl = `data:${mimeType};base64,${base64}`;\n\n const msg: OutboundMessage = {\n channel: ctx.channel,\n chat_id: ctx.chatId,\n content: p.caption || '',\n mediaUrl: dataUrl,\n mediaType,\n };\n\n await bus.publishOutbound(msg);\n\n const fileName = basename(resolved);\n return {\n content: [{ type: 'text', text: `✅ Media sent: ${fileName} (${mediaType})` }],\n details: { filePath: resolved, mediaType },\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: 'text', text: `Error sending media: ${errorMessage}` }],\n details: { error: errorMessage },\n };\n }\n },\n } as any;\n}\n"],"mappings":";;;;;;AASA,MAAM,kBAAkB,KAAK,OAAO;CAClC,UAAU,KAAK,OAAO,EACpB,aACE,yGACH,CAAC;CACF,WAAW,KAAK,SAAS,KAAK,KAAK;EACjC,OAAO;EACP,OAAO;EACP,OAAO;EACP,UAAU;EACX,EAAE,EAAE,aAAa,0DAA0D,CAAC,CAAC;CAC9E,SAAS,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,yBAAyB,CAAC,CAAC;CAC9E,CAAC;AAcF,SAAS,gBAAgB,UAA4D;CACnF,MAAM,MAAM,SAAS,MAAM,IAAI,CAAC,KAAK,EAAE,aAAa;CACpD,MAAM,YAAY;EAAC;EAAO;EAAQ;EAAO;EAAO;EAAQ;EAAM;CAC9D,MAAM,YAAY;EAAC;EAAO;EAAO;EAAO;EAAQ;EAAM;CACtD,MAAM,YAAY;EAAC;EAAO;EAAO;EAAO;EAAO;EAAO;AAEtD,KAAI,UAAU,SAAS,OAAO,GAAG,CAAE,QAAO;AAC1C,KAAI,UAAU,SAAS,OAAO,GAAG,CAAE,QAAO;AAC1C,KAAI,UAAU,SAAS,OAAO,GAAG,CAAE,QAAO;AAC1C,QAAO;;AAIT,SAAS,eAAe,UAA0B;AA0BhD,QAAO;EAvBL,KAAK;EACL,MAAM;EACN,KAAK;EACL,KAAK;EACL,MAAM;EACN,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,MAAM;EACN,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,MAAM;EACN,KAAK;EACL,KAAK;EACL,MAAM;EACN,KAAK;EACL,KAAK;EACL,KAAK;EAEO,CAzBF,SAAS,MAAM,IAAI,CAAC,KAAK,EAAE,aAAa,IAyB9B,OAAO;;AAG/B,SAAgB,oBACd,WACA,KACA,YACW;AACX,QAAO;EACL,MAAM;EACN,aACE;EACF,YAAY;EACZ,OAAO;EAEP,MAAM,QACJ,aACA,QACA,SAC8B;GAC9B,MAAM,IAAI;GACV,MAAM,MAAM,YAAY;AACxB,OAAI,CAAC,IACH,QAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAQ,MAAM;KAAyC,CAAC;IAC1E,SAAS,EAAE;IACZ;GAGH,MAAM,WAAW,0BAA0B,EAAE,UAAU,UAAU;GACjE,MAAM,SAAS,gBAAgB,QAAQ,SAAS;AAChD,OAAI,CAAC,OAAO,QACV,QAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAQ,MAAM,MAAM,OAAO;KAAW,CAAC;IACzD,SAAS,EAAE;IACZ;AAGH,OAAI;IAEF,MAAM,UAAS,MADU,SAAS,SAAS,EACjB,SAAS,SAAS;IAC5C,MAAM,WAAW,eAAe,SAAS;IACzC,MAAM,YAAY,EAAE,aAAa,gBAAgB,SAAS;IAG1D,MAAM,UAAU,QAAQ,SAAS,UAAU;IAE3C,MAAM,MAAuB;KAC3B,SAAS,IAAI;KACb,SAAS,IAAI;KACb,SAAS,EAAE,WAAW;KACtB,UAAU;KACV;KACD;AAED,UAAM,IAAI,gBAAgB,IAAI;AAG9B,WAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,iBAFjB,SAAS,SAEiC,CAAC,IAAI,UAAU;MAAI,CAAC;KAC7E,SAAS;MAAE,UAAU;MAAU;MAAW;KAC3C;YACM,OAAO;IACd,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,WAAO;KACL,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,wBAAwB;MAAgB,CAAC;KACzE,SAAS,EAAE,OAAO,cAAc;KACjC;;;EAGN"}
@@ -81,6 +81,13 @@ export declare class CredentialResolver {
81
81
  * Load the raw OAuth token record, including expired tokens for status UIs.
82
82
  */
83
83
  loadOAuthTokenRecord(provider: string): Promise<OAuthToken | null>;
84
+ /**
85
+ * List persisted OAuth tokens without exposing access/refresh values.
86
+ */
87
+ listOAuthTokens(): Promise<Array<Omit<OAuthToken, 'access' | 'refresh'> & {
88
+ hasAccess: boolean;
89
+ hasRefresh: boolean;
90
+ }>>;
84
91
  /**
85
92
  * Save OAuth token for a provider.
86
93
  */
@@ -4,7 +4,7 @@ import { createLogger } from "../utils/logger/index.js";
4
4
  import { init_logger } from "../utils/logger.js";
5
5
  import { getApiKeyFromEnv, init_env_keys } from "../providers/env-keys.js";
6
6
  import { init_paths, resolveAgentAuthProfilesPath, resolveAuthProfilesPath, resolveCredentialsDir, resolveOAuthPath } from "../config/paths.js";
7
- import { mkdir, readFile, rm } from "fs/promises";
7
+ import { mkdir, readFile, readdir, rm } from "fs/promises";
8
8
  import { dirname, join } from "path";
9
9
  //#region src/auth/credentials.ts
10
10
  function getCredentialResolver(options) {
@@ -186,6 +186,36 @@ var init_credentials = __esmMin((() => {
186
186
  }
187
187
  }
188
188
  /**
189
+ * List persisted OAuth tokens without exposing access/refresh values.
190
+ */
191
+ async listOAuthTokens() {
192
+ const oauthDir = join(this.credentialsDir, "oauth");
193
+ let files;
194
+ try {
195
+ files = await readdir(oauthDir);
196
+ } catch {
197
+ return [];
198
+ }
199
+ const tokens = [];
200
+ for (const file of files) {
201
+ if (!file.endsWith(".json")) continue;
202
+ try {
203
+ const content = await readFile(join(oauthDir, file), "utf-8");
204
+ const token = JSON.parse(content);
205
+ if (token.type !== "oauth" || !token.provider) continue;
206
+ const { access, refresh, ...safe } = token;
207
+ tokens.push({
208
+ ...safe,
209
+ hasAccess: Boolean(access?.trim()),
210
+ hasRefresh: Boolean(refresh?.trim())
211
+ });
212
+ } catch {
213
+ continue;
214
+ }
215
+ }
216
+ return tokens.sort((a, b) => a.provider.localeCompare(b.provider));
217
+ }
218
+ /**
189
219
  * Save OAuth token for a provider.
190
220
  */
191
221
  async saveOAuthToken(provider, token) {
@@ -214,7 +244,10 @@ var init_credentials = __esmMin((() => {
214
244
  */
215
245
  async deleteProviderCredential(provider) {
216
246
  const normalizedProvider = provider.toLowerCase();
217
- await this.deleteProfile(`${normalizedProvider}:default`);
247
+ const file = await this.loadAuthProfilesFile();
248
+ await mkdir(dirname(resolveAuthProfilesPath()), { recursive: true });
249
+ for (const [profileId, profile] of Object.entries(file.profiles)) if (profile.provider === normalizedProvider) delete file.profiles[profileId];
250
+ await writeTextAtomic(resolveAuthProfilesPath(), JSON.stringify(file, null, 2));
218
251
  await this.deleteOAuthToken(normalizedProvider);
219
252
  }
220
253
  async loadFromAgentCredentials(provider) {
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.js","names":[],"sources":["../../../src/auth/credentials.ts"],"sourcesContent":["import { readFile, mkdir, rm } from 'fs/promises';\nimport { writeTextAtomic } from '../infra/write-file-atomic.js';\nimport { join, dirname } from 'path';\nimport { createLogger } from '../utils/logger.js';\nimport { getApiKeyFromEnv } from '../providers/env-keys.js';\nimport {\n resolveCredentialsDir,\n resolveAuthProfilesPath,\n resolveAgentAuthProfilesPath,\n resolveOAuthPath,\n} from '../config/paths.js';\nimport type { Config } from '../config/schema.js';\n\nconst log = createLogger('Credentials');\n\n// ============================================\n// Types\n// ============================================\n\nexport type CredentialType = 'api_key' | 'oauth';\n\nexport interface ApiKeyProfile {\n type: 'api_key';\n provider: string;\n profileName?: string;\n envVar?: string | null;\n key: string | null;\n}\n\nexport interface OAuthToken {\n type: 'oauth';\n provider: string;\n access: string;\n refresh?: string;\n expiresAt?: number;\n scope?: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport type CredentialProfile = ApiKeyProfile;\n\nexport interface AuthProfilesFile {\n version: number;\n profiles: Record<string, ApiKeyProfile>;\n}\n\n// ============================================\n// Credential Resolver\n// ============================================\n\nexport interface CredentialResolverOptions {\n stateDir?: string;\n /** When set, per-agent auth profiles are read from `resolveAgentAuthProfilesPath(appConfig, agentId)`. */\n agentId?: string;\n /** Required when `agentId` is set. */\n appConfig?: Config;\n}\n\nexport class CredentialResolver {\n private readonly credentialsDir: string;\n private readonly agentId?: string;\n private readonly appConfig?: Config;\n\n constructor(options: CredentialResolverOptions = {}) {\n this.credentialsDir = options.stateDir\n ? join(options.stateDir, 'credentials')\n : resolveCredentialsDir();\n this.agentId = options.agentId;\n this.appConfig = options.appConfig;\n if (this.agentId && !this.appConfig) {\n throw new Error('CredentialResolver: appConfig is required when agentId is set');\n }\n }\n\n /**\n * Resolve API key for a provider\n * Priority: Agent private > Global > OAuth > Environment\n */\n async resolveApiKey(provider: string): Promise<string | null> {\n const normalizedProvider = provider.toLowerCase();\n\n // 1. Try agent private credentials\n if (this.agentId) {\n const agentKey = await this.loadFromAgentCredentials(normalizedProvider);\n if (agentKey) {\n log.debug({ provider, source: 'agent' }, 'Resolved API key from agent credentials');\n return agentKey;\n }\n }\n\n // 2. Try global credentials\n const globalKey = await this.loadFromGlobalCredentials(normalizedProvider);\n if (globalKey) {\n log.debug({ provider, source: 'global' }, 'Resolved API key from global credentials');\n return globalKey;\n }\n\n // 3. Try OAuth token (convert to Bearer)\n const oauthToken = await this.loadOAuthToken(normalizedProvider);\n if (oauthToken) {\n log.debug({ provider, source: 'oauth' }, 'Resolved API key from OAuth token');\n return oauthToken.access;\n }\n\n // 4. Environment variables (see `src/providers/env-keys.ts`)\n const envKey = getApiKeyFromEnv(normalizedProvider);\n if (envKey) {\n log.debug({ provider, source: 'env' }, 'Resolved API key from environment');\n return envKey;\n }\n\n return null;\n }\n\n /**\n * Check if a provider has credentials configured\n */\n async hasCredentials(provider: string): Promise<boolean> {\n const key = await this.resolveApiKey(provider);\n return key !== null;\n }\n\n /**\n * Which step in {@link resolveApiKey} would supply the key (no secret material).\n */\n async resolveApiKeySource(\n provider: string,\n ): Promise<'agent' | 'global' | 'oauth' | 'env' | null> {\n const normalizedProvider = provider.toLowerCase();\n\n if (this.agentId) {\n const agentKey = await this.loadFromAgentCredentials(normalizedProvider);\n if (agentKey) return 'agent';\n }\n\n const globalKey = await this.loadFromGlobalCredentials(normalizedProvider);\n if (globalKey) return 'global';\n\n const oauthToken = await this.loadOAuthToken(normalizedProvider);\n if (oauthToken) return 'oauth';\n\n if (getApiKeyFromEnv(normalizedProvider)) return 'env';\n\n return null;\n }\n\n /**\n * List all available credential profiles\n */\n async listProfiles(): Promise<Array<ApiKeyProfile & { id: string; source: 'agent' | 'global' }>> {\n const profiles: Array<ApiKeyProfile & { id: string; source: 'agent' | 'global' }> = [];\n\n // Global profiles\n const globalProfiles = await this.loadAuthProfilesFile();\n for (const [id, profile] of Object.entries(globalProfiles.profiles)) {\n profiles.push({ ...profile, id, source: 'global' });\n }\n\n // Agent private profiles\n if (this.agentId) {\n const agentProfiles = await this.loadAgentAuthProfilesFile();\n for (const [id, profile] of Object.entries(agentProfiles.profiles)) {\n profiles.push({ ...profile, id, source: 'agent' });\n }\n }\n\n return profiles;\n }\n\n /**\n * Plaintext API key from global auth profiles only (no env/oauth fallback).\n * Used by the gateway console reveal endpoint.\n */\n async revealGatewayStoredApiKey(provider: string): Promise<string | null> {\n const normalizedProvider = provider.toLowerCase();\n const profiles = await this.loadAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, normalizedProvider);\n const key = profile?.key?.trim();\n return key || null;\n }\n\n /**\n * Save an API key profile\n */\n async saveApiKey(\n provider: string,\n key: string,\n options: {\n profileName?: string;\n envVar?: string | null;\n agentPrivate?: boolean;\n } = {}\n ): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const profileId = options.profileName\n ? `${normalizedProvider}:${options.profileName}`\n : `${normalizedProvider}:default`;\n\n const profile: ApiKeyProfile = {\n type: 'api_key',\n provider: normalizedProvider,\n profileName: options.profileName,\n envVar: options.envVar ?? null,\n key,\n };\n\n if (options.agentPrivate && this.agentId) {\n await this.saveAgentAuthProfile(profileId, profile);\n } else {\n await this.saveGlobalAuthProfile(profileId, profile);\n }\n\n log.info({ provider, profileId, agentPrivate: options.agentPrivate }, 'Saved API key');\n }\n\n /**\n * Delete a credential profile\n */\n async deleteProfile(profileId: string, options: { agentPrivate?: boolean } = {}): Promise<void> {\n if (options.agentPrivate && this.agentId) {\n await this.deleteAgentAuthProfile(profileId);\n } else {\n await this.deleteGlobalAuthProfile(profileId);\n }\n\n log.info({ profileId, agentPrivate: options.agentPrivate }, 'Deleted credential profile');\n }\n\n /**\n * Load OAuth token for a provider.\n */\n async loadOAuthToken(provider: string): Promise<OAuthToken | null> {\n const token = await this.loadOAuthTokenRecord(provider);\n if (!token) return null;\n\n if (token.expiresAt && token.expiresAt < Date.now()) {\n log.warn({ provider, expiresAt: token.expiresAt }, 'OAuth token is expired');\n return null;\n }\n\n return token;\n }\n\n /**\n * Load the raw OAuth token record, including expired tokens for status UIs.\n */\n async loadOAuthTokenRecord(provider: string): Promise<OAuthToken | null> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n\n try {\n const content = await readFile(oauthPath, 'utf-8');\n const token = JSON.parse(content) as OAuthToken;\n return token.provider === normalizedProvider ? token : null;\n } catch {\n return null;\n }\n }\n\n /**\n * Save OAuth token for a provider.\n */\n async saveOAuthToken(provider: string, token: Omit<OAuthToken, 'type' | 'provider' | 'updatedAt'>): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n\n await mkdir(dirname(oauthPath), { recursive: true });\n\n const fullToken: OAuthToken = {\n ...token,\n type: 'oauth',\n provider: normalizedProvider,\n updatedAt: new Date().toISOString(),\n };\n\n await writeTextAtomic(oauthPath, JSON.stringify(fullToken, null, 2));\n log.info({ provider: normalizedProvider }, 'Saved OAuth token');\n }\n\n /**\n * Delete the OAuth token persisted for a provider.\n */\n async deleteOAuthToken(provider: string): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n await rm(oauthPath, { force: true });\n log.info({ provider: normalizedProvider }, 'Deleted OAuth token');\n }\n\n /**\n * Disconnect the default credential for a provider from local storage.\n */\n async deleteProviderCredential(provider: string): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n await this.deleteProfile(`${normalizedProvider}:default`);\n await this.deleteOAuthToken(normalizedProvider);\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private async loadFromAgentCredentials(provider: string): Promise<string | null> {\n if (!this.agentId) return null;\n\n const profiles = await this.loadAgentAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, provider);\n\n if (!profile) return null;\n if (profile.envVar) return this.loadFromEnv(profile.envVar) ?? profile.key;\n return profile.key;\n }\n\n private async loadFromGlobalCredentials(provider: string): Promise<string | null> {\n const profiles = await this.loadAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, provider);\n\n if (!profile) return null;\n if (profile.envVar) return this.loadFromEnv(profile.envVar) ?? profile.key;\n return profile.key;\n }\n\n private loadFromEnv(envVarName: string): string | null {\n return process.env[envVarName] || null;\n }\n\n private findProfileForProvider(\n file: AuthProfilesFile,\n provider: string\n ): ApiKeyProfile | null {\n const normalizedProvider = provider.toLowerCase();\n\n // Look for exact match first\n for (const [, profile] of Object.entries(file.profiles)) {\n if (profile.provider === normalizedProvider) {\n return profile;\n }\n }\n\n return null;\n }\n\n private async loadAuthProfilesFile(): Promise<AuthProfilesFile> {\n const path = resolveAuthProfilesPath();\n\n try {\n const content = await readFile(path, 'utf-8');\n const data = JSON.parse(content);\n return {\n version: data.version || 1,\n profiles: data.profiles || {},\n };\n } catch {\n return { version: 2, profiles: {} };\n }\n }\n\n private async loadAgentAuthProfilesFile(): Promise<AuthProfilesFile> {\n if (!this.agentId || !this.appConfig) return { version: 2, profiles: {} };\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n\n try {\n const content = await readFile(path, 'utf-8');\n const data = JSON.parse(content);\n return {\n version: data.version || 1,\n profiles: data.profiles || {},\n };\n } catch {\n return { version: 2, profiles: {} };\n }\n }\n\n private async saveGlobalAuthProfile(profileId: string, profile: ApiKeyProfile): Promise<void> {\n const path = resolveAuthProfilesPath();\n await mkdir(dirname(path), { recursive: true });\n\n const file = await this.loadAuthProfilesFile();\n file.profiles[profileId] = profile;\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async saveAgentAuthProfile(profileId: string, profile: ApiKeyProfile): Promise<void> {\n if (!this.agentId || !this.appConfig) throw new Error('Agent ID and appConfig required for agent-private profiles');\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n await mkdir(dirname(path), { recursive: true });\n\n const file = await this.loadAgentAuthProfilesFile();\n file.profiles[profileId] = profile;\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async deleteGlobalAuthProfile(profileId: string): Promise<void> {\n const path = resolveAuthProfilesPath();\n const file = await this.loadAuthProfilesFile();\n\n delete file.profiles[profileId];\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async deleteAgentAuthProfile(profileId: string): Promise<void> {\n if (!this.agentId || !this.appConfig) throw new Error('Agent ID and appConfig required for agent-private profiles');\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n const file = await this.loadAgentAuthProfilesFile();\n\n delete file.profiles[profileId];\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\nlet defaultResolver: CredentialResolver | null = null;\n\nexport function getCredentialResolver(options?: CredentialResolverOptions): CredentialResolver {\n if (!defaultResolver || options) {\n return new CredentialResolver(options);\n }\n return defaultResolver;\n}\n\nexport async function resolveApiKey(provider: string, options?: CredentialResolverOptions): Promise<string | null> {\n const resolver = getCredentialResolver(options);\n return resolver.resolveApiKey(provider);\n}\n\nexport async function hasCredentials(provider: string, options?: CredentialResolverOptions): Promise<boolean> {\n const resolver = getCredentialResolver(options);\n return resolver.hasCredentials(provider);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"credentials.js","names":[],"sources":["../../../src/auth/credentials.ts"],"sourcesContent":["import { readFile, mkdir, rm, readdir } from 'fs/promises';\nimport { writeTextAtomic } from '../infra/write-file-atomic.js';\nimport { join, dirname } from 'path';\nimport { createLogger } from '../utils/logger.js';\nimport { getApiKeyFromEnv } from '../providers/env-keys.js';\nimport {\n resolveCredentialsDir,\n resolveAuthProfilesPath,\n resolveAgentAuthProfilesPath,\n resolveOAuthPath,\n} from '../config/paths.js';\nimport type { Config } from '../config/schema.js';\n\nconst log = createLogger('Credentials');\n\n// ============================================\n// Types\n// ============================================\n\nexport type CredentialType = 'api_key' | 'oauth';\n\nexport interface ApiKeyProfile {\n type: 'api_key';\n provider: string;\n profileName?: string;\n envVar?: string | null;\n key: string | null;\n}\n\nexport interface OAuthToken {\n type: 'oauth';\n provider: string;\n access: string;\n refresh?: string;\n expiresAt?: number;\n scope?: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport type CredentialProfile = ApiKeyProfile;\n\nexport interface AuthProfilesFile {\n version: number;\n profiles: Record<string, ApiKeyProfile>;\n}\n\n// ============================================\n// Credential Resolver\n// ============================================\n\nexport interface CredentialResolverOptions {\n stateDir?: string;\n /** When set, per-agent auth profiles are read from `resolveAgentAuthProfilesPath(appConfig, agentId)`. */\n agentId?: string;\n /** Required when `agentId` is set. */\n appConfig?: Config;\n}\n\nexport class CredentialResolver {\n private readonly credentialsDir: string;\n private readonly agentId?: string;\n private readonly appConfig?: Config;\n\n constructor(options: CredentialResolverOptions = {}) {\n this.credentialsDir = options.stateDir\n ? join(options.stateDir, 'credentials')\n : resolveCredentialsDir();\n this.agentId = options.agentId;\n this.appConfig = options.appConfig;\n if (this.agentId && !this.appConfig) {\n throw new Error('CredentialResolver: appConfig is required when agentId is set');\n }\n }\n\n /**\n * Resolve API key for a provider\n * Priority: Agent private > Global > OAuth > Environment\n */\n async resolveApiKey(provider: string): Promise<string | null> {\n const normalizedProvider = provider.toLowerCase();\n\n // 1. Try agent private credentials\n if (this.agentId) {\n const agentKey = await this.loadFromAgentCredentials(normalizedProvider);\n if (agentKey) {\n log.debug({ provider, source: 'agent' }, 'Resolved API key from agent credentials');\n return agentKey;\n }\n }\n\n // 2. Try global credentials\n const globalKey = await this.loadFromGlobalCredentials(normalizedProvider);\n if (globalKey) {\n log.debug({ provider, source: 'global' }, 'Resolved API key from global credentials');\n return globalKey;\n }\n\n // 3. Try OAuth token (convert to Bearer)\n const oauthToken = await this.loadOAuthToken(normalizedProvider);\n if (oauthToken) {\n log.debug({ provider, source: 'oauth' }, 'Resolved API key from OAuth token');\n return oauthToken.access;\n }\n\n // 4. Environment variables (see `src/providers/env-keys.ts`)\n const envKey = getApiKeyFromEnv(normalizedProvider);\n if (envKey) {\n log.debug({ provider, source: 'env' }, 'Resolved API key from environment');\n return envKey;\n }\n\n return null;\n }\n\n /**\n * Check if a provider has credentials configured\n */\n async hasCredentials(provider: string): Promise<boolean> {\n const key = await this.resolveApiKey(provider);\n return key !== null;\n }\n\n /**\n * Which step in {@link resolveApiKey} would supply the key (no secret material).\n */\n async resolveApiKeySource(\n provider: string,\n ): Promise<'agent' | 'global' | 'oauth' | 'env' | null> {\n const normalizedProvider = provider.toLowerCase();\n\n if (this.agentId) {\n const agentKey = await this.loadFromAgentCredentials(normalizedProvider);\n if (agentKey) return 'agent';\n }\n\n const globalKey = await this.loadFromGlobalCredentials(normalizedProvider);\n if (globalKey) return 'global';\n\n const oauthToken = await this.loadOAuthToken(normalizedProvider);\n if (oauthToken) return 'oauth';\n\n if (getApiKeyFromEnv(normalizedProvider)) return 'env';\n\n return null;\n }\n\n /**\n * List all available credential profiles\n */\n async listProfiles(): Promise<Array<ApiKeyProfile & { id: string; source: 'agent' | 'global' }>> {\n const profiles: Array<ApiKeyProfile & { id: string; source: 'agent' | 'global' }> = [];\n\n // Global profiles\n const globalProfiles = await this.loadAuthProfilesFile();\n for (const [id, profile] of Object.entries(globalProfiles.profiles)) {\n profiles.push({ ...profile, id, source: 'global' });\n }\n\n // Agent private profiles\n if (this.agentId) {\n const agentProfiles = await this.loadAgentAuthProfilesFile();\n for (const [id, profile] of Object.entries(agentProfiles.profiles)) {\n profiles.push({ ...profile, id, source: 'agent' });\n }\n }\n\n return profiles;\n }\n\n /**\n * Plaintext API key from global auth profiles only (no env/oauth fallback).\n * Used by the gateway console reveal endpoint.\n */\n async revealGatewayStoredApiKey(provider: string): Promise<string | null> {\n const normalizedProvider = provider.toLowerCase();\n const profiles = await this.loadAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, normalizedProvider);\n const key = profile?.key?.trim();\n return key || null;\n }\n\n /**\n * Save an API key profile\n */\n async saveApiKey(\n provider: string,\n key: string,\n options: {\n profileName?: string;\n envVar?: string | null;\n agentPrivate?: boolean;\n } = {}\n ): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const profileId = options.profileName\n ? `${normalizedProvider}:${options.profileName}`\n : `${normalizedProvider}:default`;\n\n const profile: ApiKeyProfile = {\n type: 'api_key',\n provider: normalizedProvider,\n profileName: options.profileName,\n envVar: options.envVar ?? null,\n key,\n };\n\n if (options.agentPrivate && this.agentId) {\n await this.saveAgentAuthProfile(profileId, profile);\n } else {\n await this.saveGlobalAuthProfile(profileId, profile);\n }\n\n log.info({ provider, profileId, agentPrivate: options.agentPrivate }, 'Saved API key');\n }\n\n /**\n * Delete a credential profile\n */\n async deleteProfile(profileId: string, options: { agentPrivate?: boolean } = {}): Promise<void> {\n if (options.agentPrivate && this.agentId) {\n await this.deleteAgentAuthProfile(profileId);\n } else {\n await this.deleteGlobalAuthProfile(profileId);\n }\n\n log.info({ profileId, agentPrivate: options.agentPrivate }, 'Deleted credential profile');\n }\n\n /**\n * Load OAuth token for a provider.\n */\n async loadOAuthToken(provider: string): Promise<OAuthToken | null> {\n const token = await this.loadOAuthTokenRecord(provider);\n if (!token) return null;\n\n if (token.expiresAt && token.expiresAt < Date.now()) {\n log.warn({ provider, expiresAt: token.expiresAt }, 'OAuth token is expired');\n return null;\n }\n\n return token;\n }\n\n /**\n * Load the raw OAuth token record, including expired tokens for status UIs.\n */\n async loadOAuthTokenRecord(provider: string): Promise<OAuthToken | null> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n\n try {\n const content = await readFile(oauthPath, 'utf-8');\n const token = JSON.parse(content) as OAuthToken;\n return token.provider === normalizedProvider ? token : null;\n } catch {\n return null;\n }\n }\n\n /**\n * List persisted OAuth tokens without exposing access/refresh values.\n */\n async listOAuthTokens(): Promise<Array<Omit<OAuthToken, 'access' | 'refresh'> & { hasAccess: boolean; hasRefresh: boolean }>> {\n const oauthDir = join(this.credentialsDir, 'oauth');\n let files: string[];\n try {\n files = await readdir(oauthDir);\n } catch {\n return [];\n }\n\n const tokens: Array<Omit<OAuthToken, 'access' | 'refresh'> & { hasAccess: boolean; hasRefresh: boolean }> = [];\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n try {\n const content = await readFile(join(oauthDir, file), 'utf-8');\n const token = JSON.parse(content) as OAuthToken;\n if (token.type !== 'oauth' || !token.provider) continue;\n const { access, refresh, ...safe } = token;\n tokens.push({ ...safe, hasAccess: Boolean(access?.trim()), hasRefresh: Boolean(refresh?.trim()) });\n } catch {\n continue;\n }\n }\n return tokens.sort((a, b) => a.provider.localeCompare(b.provider));\n }\n\n /**\n * Save OAuth token for a provider.\n */\n async saveOAuthToken(provider: string, token: Omit<OAuthToken, 'type' | 'provider' | 'updatedAt'>): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n\n await mkdir(dirname(oauthPath), { recursive: true });\n\n const fullToken: OAuthToken = {\n ...token,\n type: 'oauth',\n provider: normalizedProvider,\n updatedAt: new Date().toISOString(),\n };\n\n await writeTextAtomic(oauthPath, JSON.stringify(fullToken, null, 2));\n log.info({ provider: normalizedProvider }, 'Saved OAuth token');\n }\n\n /**\n * Delete the OAuth token persisted for a provider.\n */\n async deleteOAuthToken(provider: string): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n await rm(oauthPath, { force: true });\n log.info({ provider: normalizedProvider }, 'Deleted OAuth token');\n }\n\n /**\n * Disconnect the default credential for a provider from local storage.\n */\n async deleteProviderCredential(provider: string): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const file = await this.loadAuthProfilesFile();\n await mkdir(dirname(resolveAuthProfilesPath()), { recursive: true });\n for (const [profileId, profile] of Object.entries(file.profiles)) {\n if (profile.provider === normalizedProvider) {\n delete file.profiles[profileId];\n }\n }\n await writeTextAtomic(resolveAuthProfilesPath(), JSON.stringify(file, null, 2));\n await this.deleteOAuthToken(normalizedProvider);\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private async loadFromAgentCredentials(provider: string): Promise<string | null> {\n if (!this.agentId) return null;\n\n const profiles = await this.loadAgentAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, provider);\n\n if (!profile) return null;\n if (profile.envVar) return this.loadFromEnv(profile.envVar) ?? profile.key;\n return profile.key;\n }\n\n private async loadFromGlobalCredentials(provider: string): Promise<string | null> {\n const profiles = await this.loadAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, provider);\n\n if (!profile) return null;\n if (profile.envVar) return this.loadFromEnv(profile.envVar) ?? profile.key;\n return profile.key;\n }\n\n private loadFromEnv(envVarName: string): string | null {\n return process.env[envVarName] || null;\n }\n\n private findProfileForProvider(\n file: AuthProfilesFile,\n provider: string\n ): ApiKeyProfile | null {\n const normalizedProvider = provider.toLowerCase();\n\n // Look for exact match first\n for (const [, profile] of Object.entries(file.profiles)) {\n if (profile.provider === normalizedProvider) {\n return profile;\n }\n }\n\n return null;\n }\n\n private async loadAuthProfilesFile(): Promise<AuthProfilesFile> {\n const path = resolveAuthProfilesPath();\n\n try {\n const content = await readFile(path, 'utf-8');\n const data = JSON.parse(content);\n return {\n version: data.version || 1,\n profiles: data.profiles || {},\n };\n } catch {\n return { version: 2, profiles: {} };\n }\n }\n\n private async loadAgentAuthProfilesFile(): Promise<AuthProfilesFile> {\n if (!this.agentId || !this.appConfig) return { version: 2, profiles: {} };\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n\n try {\n const content = await readFile(path, 'utf-8');\n const data = JSON.parse(content);\n return {\n version: data.version || 1,\n profiles: data.profiles || {},\n };\n } catch {\n return { version: 2, profiles: {} };\n }\n }\n\n private async saveGlobalAuthProfile(profileId: string, profile: ApiKeyProfile): Promise<void> {\n const path = resolveAuthProfilesPath();\n await mkdir(dirname(path), { recursive: true });\n\n const file = await this.loadAuthProfilesFile();\n file.profiles[profileId] = profile;\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async saveAgentAuthProfile(profileId: string, profile: ApiKeyProfile): Promise<void> {\n if (!this.agentId || !this.appConfig) throw new Error('Agent ID and appConfig required for agent-private profiles');\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n await mkdir(dirname(path), { recursive: true });\n\n const file = await this.loadAgentAuthProfilesFile();\n file.profiles[profileId] = profile;\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async deleteGlobalAuthProfile(profileId: string): Promise<void> {\n const path = resolveAuthProfilesPath();\n const file = await this.loadAuthProfilesFile();\n\n delete file.profiles[profileId];\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async deleteAgentAuthProfile(profileId: string): Promise<void> {\n if (!this.agentId || !this.appConfig) throw new Error('Agent ID and appConfig required for agent-private profiles');\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n const file = await this.loadAgentAuthProfilesFile();\n\n delete file.profiles[profileId];\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\nlet defaultResolver: CredentialResolver | null = null;\n\nexport function getCredentialResolver(options?: CredentialResolverOptions): CredentialResolver {\n if (!defaultResolver || options) {\n return new CredentialResolver(options);\n }\n return defaultResolver;\n}\n\nexport async function resolveApiKey(provider: string, options?: CredentialResolverOptions): Promise<string | null> {\n const resolver = getCredentialResolver(options);\n return resolver.resolveApiKey(provider);\n}\n\nexport async function hasCredentials(provider: string, options?: CredentialResolverOptions): Promise<boolean> {\n const resolver = getCredentialResolver(options);\n return resolver.hasCredentials(provider);\n}\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  export * from './credentials.js';
2
2
  export { anthropicOAuthProvider } from './oauth/anthropic.js';
3
- export type { OAuthLoginCallbacks } from './oauth/types.js';
3
+ export type { OAuthCredentials, OAuthLoginCallbacks, OAuthProviderInterface } from './oauth/types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/auth/index.ts"],"sourcesContent":["export * from './credentials.js';\nexport { anthropicOAuthProvider } from './oauth/anthropic.js';\nexport type { OAuthLoginCallbacks } from './oauth/types.js';\n"],"mappings":""}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/auth/index.ts"],"sourcesContent":["export * from './credentials.js';\nexport { anthropicOAuthProvider } from './oauth/anthropic.js';\nexport type { OAuthCredentials, OAuthLoginCallbacks, OAuthProviderInterface } from './oauth/types.js';\n"],"mappings":""}
@@ -1,4 +1,4 @@
1
1
  /**
2
- * GitHub Copilot OAuth — delegated to @earendil-works/pi-ai (device code flow).
2
+ * GitHub Copilot OAuth device code flow.
3
3
  */
4
4
  export { githubCopilotOAuthProvider, getGitHubCopilotBaseUrl, loginGitHubCopilot, normalizeDomain, refreshGitHubCopilotToken, } from '@earendil-works/pi-ai/oauth';
@@ -1,6 +1,4 @@
1
1
  /**
2
2
  * Google Antigravity OAuth.
3
- * Implementation is vendored under `vendor-pi-google/` — upstream removed these exports from
4
- * `@earendil-works/pi-ai/oauth` while keeping the same OAuth credential shape.
5
3
  */
6
- export { antigravityOAuthProvider as googleAntigravityOAuthProvider, loginAntigravity, refreshAntigravityToken, } from './vendor-pi-google/google-antigravity.js';
4
+ export { antigravityOAuthProvider as googleAntigravityOAuthProvider, loginAntigravity, refreshAntigravityToken, } from './google-oauth/google-antigravity.js';
@@ -1,2 +1,2 @@
1
- import { antigravityOAuthProvider, loginAntigravity, refreshAntigravityToken } from "./vendor-pi-google/google-antigravity.js";
1
+ import { antigravityOAuthProvider, loginAntigravity, refreshAntigravityToken } from "./google-oauth/google-antigravity.js";
2
2
  export { antigravityOAuthProvider as googleAntigravityOAuthProvider, loginAntigravity, refreshAntigravityToken };