agent-relay-server 0.99.1 → 0.101.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/openapi.json +1 -1
- package/package.json +5 -2
- package/public/assets/{MessageBubble-DiorZXyB.js → MessageBubble-BEjK1-bi.js} +3 -3
- package/public/assets/{MessageBubble-DiorZXyB.js.map → MessageBubble-BEjK1-bi.js.map} +1 -1
- package/public/assets/{PlanGraphPanel-DY1p8v4p.js → PlanGraphPanel-AqFEg7Yg.js} +2 -2
- package/public/assets/{PlanGraphPanel-DY1p8v4p.js.map → PlanGraphPanel-AqFEg7Yg.js.map} +1 -1
- package/public/assets/{activity-rIxqUtFC.js → activity-D5EZw4bj.js} +2 -2
- package/public/assets/{activity-rIxqUtFC.js.map → activity-D5EZw4bj.js.map} +1 -1
- package/public/assets/agent-profiles-CSISRm_L.js +2 -0
- package/public/assets/agent-profiles-CSISRm_L.js.map +1 -0
- package/public/assets/agents-szyYnkgD.js +2 -0
- package/public/assets/agents-szyYnkgD.js.map +1 -0
- package/public/assets/{analytics-CUJbpoA7.js → analytics-KzLQfGMO.js} +2 -2
- package/public/assets/{analytics-CUJbpoA7.js.map → analytics-KzLQfGMO.js.map} +1 -1
- package/public/assets/{automation-B0cyCT5l.js → automation-DVSq4A1b.js} +2 -2
- package/public/assets/{automation-B0cyCT5l.js.map → automation-DVSq4A1b.js.map} +1 -1
- package/public/assets/branch-state-badge-DgwkJ2rN.js +2 -0
- package/public/assets/branch-state-badge-DgwkJ2rN.js.map +1 -0
- package/public/assets/{channels-Tg8l4n5J.js → channels-Dh_r7SnM.js} +2 -2
- package/public/assets/{channels-Tg8l4n5J.js.map → channels-Dh_r7SnM.js.map} +1 -1
- package/public/assets/chat-patMKjsi.js +2 -0
- package/public/assets/chat-patMKjsi.js.map +1 -0
- package/public/assets/{connectors-B5wbjyUd.js → connectors-DVKBHNRV.js} +2 -2
- package/public/assets/{connectors-B5wbjyUd.js.map → connectors-DVKBHNRV.js.map} +1 -1
- package/public/assets/{formatted-body-impl-ZwgTH3jh.js → formatted-body-impl-Csr2DuEk.js} +2 -2
- package/public/assets/{formatted-body-impl-ZwgTH3jh.js.map → formatted-body-impl-Csr2DuEk.js.map} +1 -1
- package/public/assets/index-D3woTUwp.js +23 -0
- package/public/assets/index-D3woTUwp.js.map +1 -0
- package/public/assets/{insights-C3mlXZdd.js → insights-D2_Qry06.js} +2 -2
- package/public/assets/{insights-C3mlXZdd.js.map → insights-D2_Qry06.js.map} +1 -1
- package/public/assets/{integrations-sYKtupOq.js → integrations-AW8b4h7T.js} +2 -2
- package/public/assets/{integrations-sYKtupOq.js.map → integrations-AW8b4h7T.js.map} +1 -1
- package/public/assets/maintenance-Dm56u8F9.js +2 -0
- package/public/assets/{maintenance-DL1lnqmG.js.map → maintenance-Dm56u8F9.js.map} +1 -1
- package/public/assets/{managed-agents-7A6WH4Rn.js → managed-agents-DpX-cHsm.js} +2 -2
- package/public/assets/{managed-agents-7A6WH4Rn.js.map → managed-agents-DpX-cHsm.js.map} +1 -1
- package/public/assets/{markdown-preview-impl-THat8xv0.js → markdown-preview-impl-Df6EWwbg.js} +2 -2
- package/public/assets/{markdown-preview-impl-THat8xv0.js.map → markdown-preview-impl-Df6EWwbg.js.map} +1 -1
- package/public/assets/{memory-C349UJe9.js → memory-b2AgvV7H.js} +2 -2
- package/public/assets/{memory-C349UJe9.js.map → memory-b2AgvV7H.js.map} +1 -1
- package/public/assets/{messages-DXoLFj2P.js → messages-C5yDD_oq.js} +2 -2
- package/public/assets/{messages-DXoLFj2P.js.map → messages-C5yDD_oq.js.map} +1 -1
- package/public/assets/{orchestrators-CTXu4jAn.js → orchestrators-D3LecmEw.js} +2 -2
- package/public/assets/{orchestrators-CTXu4jAn.js.map → orchestrators-D3LecmEw.js.map} +1 -1
- package/public/assets/{overview-dWiN6TyN.js → overview-CnGkrBNe.js} +2 -2
- package/public/assets/{overview-dWiN6TyN.js.map → overview-CnGkrBNe.js.map} +1 -1
- package/public/assets/{pairs-KIXektDv.js → pairs-DXUdZOqn.js} +2 -2
- package/public/assets/{pairs-KIXektDv.js.map → pairs-DXUdZOqn.js.map} +1 -1
- package/public/assets/{projects-BPI8z55X.js → projects-1h41atqJ.js} +2 -2
- package/public/assets/{projects-BPI8z55X.js.map → projects-1h41atqJ.js.map} +1 -1
- package/public/assets/{registry-C-Y41yGB.js → registry-BeGP37ot.js} +2 -2
- package/public/assets/{registry-C-Y41yGB.js.map → registry-BeGP37ot.js.map} +1 -1
- package/public/assets/{security-BUymkwuj.js → security-BMh_y43L.js} +2 -2
- package/public/assets/{security-BUymkwuj.js.map → security-BMh_y43L.js.map} +1 -1
- package/public/assets/{select-DV25WRP5.js → select-Cvi5OHz0.js} +2 -2
- package/public/assets/{select-DV25WRP5.js.map → select-Cvi5OHz0.js.map} +1 -1
- package/public/assets/settings-DKSEwIVG.js +6 -0
- package/public/assets/{settings-C1En58bx.js.map → settings-DKSEwIVG.js.map} +1 -1
- package/public/assets/store-Ch-QzxPq.js +9 -0
- package/public/assets/store-Ch-QzxPq.js.map +1 -0
- package/public/assets/{tasks-BkpnKA63.js → tasks-BybIAX-y.js} +2 -2
- package/public/assets/{tasks-BkpnKA63.js.map → tasks-BybIAX-y.js.map} +1 -1
- package/public/assets/{teams-D-UYp7yH.js → teams-CMteOToR.js} +2 -2
- package/public/assets/{teams-D-UYp7yH.js.map → teams-CMteOToR.js.map} +1 -1
- package/public/assets/{terminal-viewer-impl-Bif-tkvD.js → terminal-viewer-impl-DanOi7lh.js} +2 -2
- package/public/assets/{terminal-viewer-impl-Bif-tkvD.js.map → terminal-viewer-impl-DanOi7lh.js.map} +1 -1
- package/public/assets/{user-avatar--czLv_AJ.js → user-avatar-DG629icI.js} +2 -2
- package/public/assets/{user-avatar--czLv_AJ.js.map → user-avatar-DG629icI.js.map} +1 -1
- package/public/assets/{work-queue-DN4oTe7w.js → work-queue-DqW80DIy.js} +2 -2
- package/public/assets/{work-queue-DN4oTe7w.js.map → work-queue-DqW80DIy.js.map} +1 -1
- package/public/assets/{workspaces-BolccWZy.js → workspaces-CccVI6lA.js} +2 -2
- package/public/assets/{workspaces-BolccWZy.js.map → workspaces-CccVI6lA.js.map} +1 -1
- package/public/index.html +2 -2
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/plugins/claude/hooks/kill-guard.sh +300 -0
- package/runner/plugins/claude/hooks/read-only-bash-guard.sh +38 -140
- package/runner/src/adapter.ts +2 -2
- package/src/agent-death-diagnosis.ts +12 -3
- package/src/bus.ts +6 -45
- package/src/config-store.ts +13 -9
- package/src/db/provider-quota-burn.ts +79 -6
- package/src/issue-tracker/adapter.ts +11 -1
- package/src/issue-tracker/github.ts +83 -2
- package/src/issue-tracker/index.ts +1 -0
- package/src/lifecycle-manager.ts +9 -22
- package/src/provider-state.ts +9 -18
- package/src/provider-timeline-event.ts +70 -0
- package/src/quota-advisory.ts +4 -7
- package/src/quota-band-transition.ts +101 -11
- package/src/routes/agent-sessions.ts +4 -2
- package/src/services/issue-lifecycle.ts +54 -8
- package/src/services/provider-state-audit.ts +3 -3
- package/src/services/rate-limit-resume.ts +6 -4
- package/src/services/register-agent.ts +2 -1
- package/src/settings/registry.ts +34 -0
- package/src/spawn-targets.ts +80 -10
- package/src/sse.ts +5 -4
- package/public/assets/agent-profiles-Cu-VkJm4.js +0 -2
- package/public/assets/agent-profiles-Cu-VkJm4.js.map +0 -1
- package/public/assets/agents-dRHOBDUe.js +0 -2
- package/public/assets/agents-dRHOBDUe.js.map +0 -1
- package/public/assets/branch-state-badge-CNko2_BL.js +0 -2
- package/public/assets/branch-state-badge-CNko2_BL.js.map +0 -1
- package/public/assets/chat-jit-e6S_.js +0 -2
- package/public/assets/chat-jit-e6S_.js.map +0 -1
- package/public/assets/index-GoC6YrKn.js +0 -23
- package/public/assets/index-GoC6YrKn.js.map +0 -1
- package/public/assets/maintenance-DL1lnqmG.js +0 -2
- package/public/assets/settings-C1En58bx.js +0 -6
- package/public/assets/store-pKbf_WYd.js +0 -9
- package/public/assets/store-pKbf_WYd.js.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{H as e,M as t,Qn as n,R as r,v as i,y as a,z as o}from"./lucide-react-BYZuAhQs.js";import{t as s}from"./store-
|
|
2
|
-
//# sourceMappingURL=connectors-
|
|
1
|
+
import{H as e,M as t,Qn as n,R as r,v as i,y as a,z as o}from"./lucide-react-BYZuAhQs.js";import{t as s}from"./store-Ch-QzxPq.js";import{J as c,Y as l,l as u}from"./display-DRiGi1zj.js";import{t as d}from"./badge-BLar6FjP.js";import{t as f}from"./button-BrIB69qd.js";import{a as p,o as m,r as h,t as g}from"./card-lhnFnBoz.js";var _=n();function v({connector:n}){let v=s(e=>e.runConnectorAction),y=s(e=>e.openConfirm),b=s(e=>e.showNotification),x=u(n),S=n.runtime,C=n.manifest?.commands||{},w=S.installed,T=!!C.start&&w&&!S.running,E=!!C.stop&&S.running,D=!!C.restart&&w,O=!!C.doctor&&w,k=n.displayName||n.id,A=async e=>{try{await v(n.id,e),b(`${e.charAt(0).toUpperCase()+e.slice(1)} completed for ${k}`)}catch{}};return(0,_.jsxs)(g,{className:`hover:border-zinc-600 transition-colors`,children:[(0,_.jsx)(p,{className:`pb-2 pt-4 px-4`,children:(0,_.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,_.jsx)(`div`,{className:`p-1.5 rounded-md ${S.running?`bg-emerald-500/10`:`bg-zinc-800`}`,children:(0,_.jsx)(o,{className:`w-4 h-4 ${S.running?`text-emerald-400`:`text-zinc-500`}`})}),(0,_.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,_.jsx)(m,{className:`text-sm font-medium truncate`,children:n.displayName||n.id}),(0,_.jsx)(`div`,{className:`text-xs text-muted-foreground mt-0.5`,children:n.kind})]}),(0,_.jsx)(d,{className:`text-[10px] shrink-0 ${c(x.tone)}`,children:x.label})]})}),(0,_.jsxs)(h,{className:`px-4 pb-4 space-y-2.5`,children:[n.description&&(0,_.jsx)(`p`,{className:`text-xs text-muted-foreground leading-relaxed line-clamp-2`,children:n.description}),S.detail&&(0,_.jsx)(`div`,{className:`text-xs px-2 py-1 rounded ${S.status===`error`?`bg-red-500/10 text-red-400`:S.status===`warn`?`bg-yellow-500/10 text-yellow-400`:`bg-zinc-800 text-muted-foreground`}`,children:S.detail}),l(n.capabilities).length>0&&(0,_.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:l(n.capabilities).map(e=>(0,_.jsx)(d,{variant:`secondary`,className:`text-[9px] px-1 py-0 h-4`,children:e},e))}),n.version&&(0,_.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[`v`,n.version]}),(0,_.jsxs)(`div`,{className:`flex flex-wrap gap-1.5 pt-0.5`,children:[T&&(0,_.jsxs)(f,{size:`sm`,variant:`outline`,className:`h-7 text-xs gap-1 text-emerald-400 border-emerald-500/30 hover:text-emerald-300`,onClick:()=>A(`start`),children:[(0,_.jsx)(e,{className:`w-3 h-3`}),`Start`]}),E&&(0,_.jsxs)(f,{size:`sm`,variant:`outline`,className:`h-7 text-xs gap-1 text-red-400 border-red-500/30 hover:text-red-300`,onClick:()=>y(`Stop Connector`,`Stop ${n.displayName||n.id}?`,()=>A(`stop`)),children:[(0,_.jsx)(a,{className:`w-3 h-3`}),`Stop`]}),D&&(0,_.jsxs)(f,{size:`sm`,variant:`outline`,className:`h-7 text-xs gap-1`,onClick:()=>y(`Restart Connector`,`Restart ${n.displayName||n.id}?`,()=>A(`restart`)),children:[(0,_.jsx)(t,{className:`w-3 h-3`}),`Restart`]}),O&&(0,_.jsxs)(f,{size:`sm`,variant:`ghost`,className:`h-7 text-xs gap-1 text-muted-foreground`,onClick:()=>A(`doctor`),children:[(0,_.jsx)(i,{className:`w-3 h-3`}),`Doctor`]}),!w&&C.install&&(0,_.jsxs)(f,{size:`sm`,variant:`outline`,className:`h-7 text-xs gap-1`,onClick:()=>A(`install`),children:[(0,_.jsx)(r,{className:`w-3 h-3`}),`Install`]}),w&&C.uninstall&&(0,_.jsx)(f,{size:`sm`,variant:`ghost`,className:`h-7 text-xs text-muted-foreground hover:text-red-400`,onClick:()=>y(`Uninstall Connector`,`Uninstall ${n.displayName||n.id}? This will remove the systemd service.`,()=>A(`uninstall`)),children:`Uninstall`})]})]})]})}function y(){let e=s(e=>e.connectors),t=e.filter(e=>e.runtime.running).length;return(0,_.jsxs)(`div`,{className:`space-y-4`,children:[(0,_.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,_.jsxs)(`div`,{children:[(0,_.jsx)(`h2`,{className:`text-base font-semibold`,children:`Connectors`}),(0,_.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Installed service connectors and integrations`})]}),(0,_.jsxs)(`div`,{className:`flex items-center gap-2 ml-auto`,children:[(0,_.jsxs)(d,{variant:`outline`,className:`text-xs`,children:[e.length,` total`]}),t>0&&(0,_.jsxs)(d,{className:`text-xs bg-emerald-500/15 text-emerald-400 border-emerald-500/30`,children:[t,` running`]})]})]}),e.length===0?(0,_.jsx)(`div`,{className:`text-center py-16 text-muted-foreground text-sm`,children:`No connectors registered.`}):(0,_.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4`,children:e.map(e=>(0,_.jsx)(v,{connector:e},e.id))})]})}export{y as ConnectorsView};
|
|
2
|
+
//# sourceMappingURL=connectors-DVKBHNRV.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectors-B5wbjyUd.js","names":[],"sources":["../../dashboard/src/components/views/connectors.tsx"],"sourcesContent":["import { useRelayStore } from '@/store'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { connectorPresence, toneToColor, userFacingCapabilities } from '@/lib/display'\nimport { Plug, Play, Square, RotateCw, Stethoscope, Power } from 'lucide-react'\nimport type { ConnectorSummary } from '@/types'\n\nfunction ConnectorCard({ connector }: { connector: ConnectorSummary }) {\n const runConnectorAction = useRelayStore((s) => s.runConnectorAction)\n const openConfirm = useRelayStore((s) => s.openConfirm)\n const showNotification = useRelayStore((s) => s.showNotification)\n\n const presence = connectorPresence(connector)\n const runtime = connector.runtime\n const commands = connector.manifest?.commands || {}\n const installed = runtime.installed\n\n const canStart = Boolean(commands.start) && installed && !runtime.running\n const canStop = Boolean(commands.stop) && runtime.running\n const canRestart = Boolean(commands.restart) && installed\n const canDoctor = Boolean(commands.doctor) && installed\n\n const name = connector.displayName || connector.id\n const run = async (action: string) => {\n try {\n await runConnectorAction(connector.id, action)\n showNotification(`${action.charAt(0).toUpperCase() + action.slice(1)} completed for ${name}`)\n } catch { /* error modal already shown by store */ }\n }\n\n return (\n <Card className=\"hover:border-zinc-600 transition-colors\">\n <CardHeader className=\"pb-2 pt-4 px-4\">\n <div className=\"flex items-start gap-2\">\n <div className={`p-1.5 rounded-md ${runtime.running ? 'bg-emerald-500/10' : 'bg-zinc-800'}`}>\n <Plug className={`w-4 h-4 ${runtime.running ? 'text-emerald-400' : 'text-zinc-500'}`} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <CardTitle className=\"text-sm font-medium truncate\">{connector.displayName || connector.id}</CardTitle>\n <div className=\"text-xs text-muted-foreground mt-0.5\">{connector.kind}</div>\n </div>\n <Badge className={`text-[10px] shrink-0 ${toneToColor(presence.tone)}`}>\n {presence.label}\n </Badge>\n </div>\n </CardHeader>\n\n <CardContent className=\"px-4 pb-4 space-y-2.5\">\n {/* Description */}\n {connector.description && (\n <p className=\"text-xs text-muted-foreground leading-relaxed line-clamp-2\">{connector.description}</p>\n )}\n\n {/* Runtime status detail */}\n {runtime.detail && (\n <div className={`text-xs px-2 py-1 rounded ${runtime.status === 'error' ? 'bg-red-500/10 text-red-400' : runtime.status === 'warn' ? 'bg-yellow-500/10 text-yellow-400' : 'bg-zinc-800 text-muted-foreground'}`}>\n {runtime.detail}\n </div>\n )}\n\n {/* Capabilities */}\n {userFacingCapabilities(connector.capabilities).length > 0 && (\n <div className=\"flex flex-wrap gap-1\">\n {userFacingCapabilities(connector.capabilities).map((c) => (\n <Badge key={c} variant=\"secondary\" className=\"text-[9px] px-1 py-0 h-4\">{c}</Badge>\n ))}\n </div>\n )}\n\n {/* Version */}\n {connector.version && (\n <div className=\"text-xs text-muted-foreground\">v{connector.version}</div>\n )}\n\n {/* Action buttons */}\n <div className=\"flex flex-wrap gap-1.5 pt-0.5\">\n {canStart && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1 text-emerald-400 border-emerald-500/30 hover:text-emerald-300\"\n onClick={() => run('start')}\n >\n <Play className=\"w-3 h-3\" />\n Start\n </Button>\n )}\n {canStop && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1 text-red-400 border-red-500/30 hover:text-red-300\"\n onClick={() => openConfirm('Stop Connector', `Stop ${connector.displayName || connector.id}?`, () => run('stop'))}\n >\n <Square className=\"w-3 h-3\" />\n Stop\n </Button>\n )}\n {canRestart && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1\"\n onClick={() => openConfirm('Restart Connector', `Restart ${connector.displayName || connector.id}?`, () => run('restart'))}\n >\n <RotateCw className=\"w-3 h-3\" />\n Restart\n </Button>\n )}\n {canDoctor && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-7 text-xs gap-1 text-muted-foreground\"\n onClick={() => run('doctor')}\n >\n <Stethoscope className=\"w-3 h-3\" />\n Doctor\n </Button>\n )}\n {!installed && commands.install && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1\"\n onClick={() => run('install')}\n >\n <Power className=\"w-3 h-3\" />\n Install\n </Button>\n )}\n {installed && commands.uninstall && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-7 text-xs text-muted-foreground hover:text-red-400\"\n onClick={() => openConfirm('Uninstall Connector', `Uninstall ${connector.displayName || connector.id}? This will remove the systemd service.`, () => run('uninstall'))}\n >\n Uninstall\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n )\n}\n\nexport function ConnectorsView() {\n const connectors = useRelayStore((s) => s.connectors)\n\n const runningCount = connectors.filter((c) => c.runtime.running).length\n\n return (\n <div className=\"space-y-4\">\n {/* Header */}\n <div className=\"flex items-center gap-3\">\n <div>\n <h2 className=\"text-base font-semibold\">Connectors</h2>\n <p className=\"text-xs text-muted-foreground\">Installed service connectors and integrations</p>\n </div>\n <div className=\"flex items-center gap-2 ml-auto\">\n <Badge variant=\"outline\" className=\"text-xs\">\n {connectors.length} total\n </Badge>\n {runningCount > 0 && (\n <Badge className=\"text-xs bg-emerald-500/15 text-emerald-400 border-emerald-500/30\">\n {runningCount} running\n </Badge>\n )}\n </div>\n </div>\n\n {/* Cards */}\n {connectors.length === 0 ? (\n <div className=\"text-center py-16 text-muted-foreground text-sm\">\n No connectors registered.\n </div>\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4\">\n {connectors.map((connector) => (\n <ConnectorCard key={connector.id} connector={connector} />\n ))}\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"connectors-DVKBHNRV.js","names":[],"sources":["../../dashboard/src/components/views/connectors.tsx"],"sourcesContent":["import { useRelayStore } from '@/store'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { connectorPresence, toneToColor, userFacingCapabilities } from '@/lib/display'\nimport { Plug, Play, Square, RotateCw, Stethoscope, Power } from 'lucide-react'\nimport type { ConnectorSummary } from '@/types'\n\nfunction ConnectorCard({ connector }: { connector: ConnectorSummary }) {\n const runConnectorAction = useRelayStore((s) => s.runConnectorAction)\n const openConfirm = useRelayStore((s) => s.openConfirm)\n const showNotification = useRelayStore((s) => s.showNotification)\n\n const presence = connectorPresence(connector)\n const runtime = connector.runtime\n const commands = connector.manifest?.commands || {}\n const installed = runtime.installed\n\n const canStart = Boolean(commands.start) && installed && !runtime.running\n const canStop = Boolean(commands.stop) && runtime.running\n const canRestart = Boolean(commands.restart) && installed\n const canDoctor = Boolean(commands.doctor) && installed\n\n const name = connector.displayName || connector.id\n const run = async (action: string) => {\n try {\n await runConnectorAction(connector.id, action)\n showNotification(`${action.charAt(0).toUpperCase() + action.slice(1)} completed for ${name}`)\n } catch { /* error modal already shown by store */ }\n }\n\n return (\n <Card className=\"hover:border-zinc-600 transition-colors\">\n <CardHeader className=\"pb-2 pt-4 px-4\">\n <div className=\"flex items-start gap-2\">\n <div className={`p-1.5 rounded-md ${runtime.running ? 'bg-emerald-500/10' : 'bg-zinc-800'}`}>\n <Plug className={`w-4 h-4 ${runtime.running ? 'text-emerald-400' : 'text-zinc-500'}`} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <CardTitle className=\"text-sm font-medium truncate\">{connector.displayName || connector.id}</CardTitle>\n <div className=\"text-xs text-muted-foreground mt-0.5\">{connector.kind}</div>\n </div>\n <Badge className={`text-[10px] shrink-0 ${toneToColor(presence.tone)}`}>\n {presence.label}\n </Badge>\n </div>\n </CardHeader>\n\n <CardContent className=\"px-4 pb-4 space-y-2.5\">\n {/* Description */}\n {connector.description && (\n <p className=\"text-xs text-muted-foreground leading-relaxed line-clamp-2\">{connector.description}</p>\n )}\n\n {/* Runtime status detail */}\n {runtime.detail && (\n <div className={`text-xs px-2 py-1 rounded ${runtime.status === 'error' ? 'bg-red-500/10 text-red-400' : runtime.status === 'warn' ? 'bg-yellow-500/10 text-yellow-400' : 'bg-zinc-800 text-muted-foreground'}`}>\n {runtime.detail}\n </div>\n )}\n\n {/* Capabilities */}\n {userFacingCapabilities(connector.capabilities).length > 0 && (\n <div className=\"flex flex-wrap gap-1\">\n {userFacingCapabilities(connector.capabilities).map((c) => (\n <Badge key={c} variant=\"secondary\" className=\"text-[9px] px-1 py-0 h-4\">{c}</Badge>\n ))}\n </div>\n )}\n\n {/* Version */}\n {connector.version && (\n <div className=\"text-xs text-muted-foreground\">v{connector.version}</div>\n )}\n\n {/* Action buttons */}\n <div className=\"flex flex-wrap gap-1.5 pt-0.5\">\n {canStart && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1 text-emerald-400 border-emerald-500/30 hover:text-emerald-300\"\n onClick={() => run('start')}\n >\n <Play className=\"w-3 h-3\" />\n Start\n </Button>\n )}\n {canStop && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1 text-red-400 border-red-500/30 hover:text-red-300\"\n onClick={() => openConfirm('Stop Connector', `Stop ${connector.displayName || connector.id}?`, () => run('stop'))}\n >\n <Square className=\"w-3 h-3\" />\n Stop\n </Button>\n )}\n {canRestart && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1\"\n onClick={() => openConfirm('Restart Connector', `Restart ${connector.displayName || connector.id}?`, () => run('restart'))}\n >\n <RotateCw className=\"w-3 h-3\" />\n Restart\n </Button>\n )}\n {canDoctor && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-7 text-xs gap-1 text-muted-foreground\"\n onClick={() => run('doctor')}\n >\n <Stethoscope className=\"w-3 h-3\" />\n Doctor\n </Button>\n )}\n {!installed && commands.install && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1\"\n onClick={() => run('install')}\n >\n <Power className=\"w-3 h-3\" />\n Install\n </Button>\n )}\n {installed && commands.uninstall && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-7 text-xs text-muted-foreground hover:text-red-400\"\n onClick={() => openConfirm('Uninstall Connector', `Uninstall ${connector.displayName || connector.id}? This will remove the systemd service.`, () => run('uninstall'))}\n >\n Uninstall\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n )\n}\n\nexport function ConnectorsView() {\n const connectors = useRelayStore((s) => s.connectors)\n\n const runningCount = connectors.filter((c) => c.runtime.running).length\n\n return (\n <div className=\"space-y-4\">\n {/* Header */}\n <div className=\"flex items-center gap-3\">\n <div>\n <h2 className=\"text-base font-semibold\">Connectors</h2>\n <p className=\"text-xs text-muted-foreground\">Installed service connectors and integrations</p>\n </div>\n <div className=\"flex items-center gap-2 ml-auto\">\n <Badge variant=\"outline\" className=\"text-xs\">\n {connectors.length} total\n </Badge>\n {runningCount > 0 && (\n <Badge className=\"text-xs bg-emerald-500/15 text-emerald-400 border-emerald-500/30\">\n {runningCount} running\n </Badge>\n )}\n </div>\n </div>\n\n {/* Cards */}\n {connectors.length === 0 ? (\n <div className=\"text-center py-16 text-muted-foreground text-sm\">\n No connectors registered.\n </div>\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4\">\n {connectors.map((connector) => (\n <ConnectorCard key={connector.id} connector={connector} />\n ))}\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{Qn as t,Xn as n,dr as r}from"./lucide-react-BYZuAhQs.js";import{t as i}from"./store-
|
|
1
|
+
import{r as e}from"./chunk-CilyBKbf.js";import{Qn as t,Xn as n,dr as r}from"./lucide-react-BYZuAhQs.js";import{t as i}from"./store-Ch-QzxPq.js";import{L as a}from"./display-DRiGi1zj.js";import{M as o}from"./index-D3woTUwp.js";import{i as s,n as c,r as l,t as u}from"./lib-ng6WZYjE.js";var d=e(r(),1),f=t(),p=/((?:[A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*)?#\d+)\b|(https?:\/\/[^\s`'")\]]+)|((?:\/[\w.@+-][^\s`'")\]]*|(?:\.{1,2}\/|[\w.@+-]+\/)[^\s`'")\]]*))/g,m=/[.,;:!?]+$/,h=new Set([`src`,`app`,`apps`,`lib`,`server`,`client`,`dashboard`,`orchestrator`,`runner`,`sdk`,`codex`,`claude`,`public`,`docs`,`test`,`tests`,`scripts`,`config`,`configs`]),g={...l,attributes:{...l.attributes,code:[...l.attributes?.code||[],[`className`,/^language-[\w-]+$/]]}};function _(e){if(e===`/api`||e.startsWith(`/api/`))return!1;if(e.startsWith(`/`)||e.startsWith(`./`)||e.startsWith(`../`))return!0;let t=e.split(`/`).filter(Boolean),n=t[0]??``,r=t[t.length-1]??``;return n.startsWith(`.`)||h.has(n)?!0:r.includes(`.`)}function v(e,t){let n=[],r=0;for(let i of e.matchAll(p)){let a=i[1],o=i[2],s=i[3],c=a||o||s,l=i.index??0;if(!c||l<r)continue;if(a){let i=a.lastIndexOf(`#`),o=a.slice(0,i)||t,s=a.slice(i+1),c=e.slice(l+a.length).match(/^(?:\/\d+)+/)?.[0]??``;o?(l>r&&n.push({text:e.slice(r,l)}),n.push({text:a,issueUrl:`https://github.com/${o}/issues/${s}`}),c&&n.push({text:c}),r=l+a.length+c.length):c&&(l>r&&n.push({text:e.slice(r,l)}),n.push({text:a+c}),r=l+a.length+c.length);continue}if(o){let t=o.replace(m,``),i=o.slice(t.length);l>r&&n.push({text:e.slice(r,l)}),n.push({text:t,url:t}),i&&n.push({text:i}),r=l+o.length;continue}if(!c.includes(`/`))continue;let u=c.replace(m,``),d=c.slice(u.length),f=u.match(/^(.*):(\d+)$/),p=f?Number(f[2]):void 0;f&&(u=f[1]),_(u)&&(l>r&&n.push({text:e.slice(r,l)}),n.push({text:u,path:u,line:Number.isFinite(p)?p:void 0}),d&&n.push({text:d}),r=l+c.length)}return r<e.length&&n.push({text:e.slice(r)}),n}function y({text:e,onOpenPath:t,onPreviewPath:n,onPreviewPathEnd:r,isPathLinkable:i,resolvePathTitle:a,issueRepo:o}){let s=v(e,o);return s.length===1&&!s[0]?.path&&!s[0]?.url&&!s[0]?.issueUrl?(0,f.jsx)(f.Fragment,{children:e}):(0,f.jsx)(f.Fragment,{children:s.map((e,o)=>{if(e.issueUrl)return(0,f.jsx)(`a`,{href:e.issueUrl,target:`_blank`,rel:`noreferrer`,className:`font-medium underline decoration-dotted underline-offset-2`,onClick:e=>e.stopPropagation(),children:e.text},`${e.issueUrl}-${o}`);if(e.url)return(0,f.jsx)(`a`,{href:e.url,target:`_blank`,rel:`noreferrer`,className:`underline decoration-dotted underline-offset-2`,onClick:e=>e.stopPropagation(),children:e.text},`${e.url}-${o}`);if(e.path&&t){if(i&&!i(e.path,e.line))return(0,f.jsxs)(`span`,{children:[e.text,e.line?`:${e.line}`:``]},`${e.path}-${o}`);let s=a?.(e.path,e.line);return(0,f.jsxs)(`button`,{type:`button`,className:`chat-link rounded-sm font-mono underline decoration-dotted underline-offset-2`,onClick:n=>{n.stopPropagation(),t(e.path,e.line)},onMouseEnter:t=>n?.(e.path,e.line,t.currentTarget.getBoundingClientRect()),onFocus:t=>n?.(e.path,e.line,t.currentTarget.getBoundingClientRect()),onMouseLeave:()=>r?.(),onBlur:()=>r?.(),title:s?`Open ${s}`:`Open file`,children:[e.text,e.line?`:${e.line}`:``]},`${e.path}-${o}`)}return(0,f.jsx)(`span`,{children:e.text},o)})})}var b=({className:e,children:t})=>{let n=/language-([\w-]+)/.exec(e||``),r=String(t).replace(/\n$/,``);return n?(0,f.jsx)(o,{content:r,path:`.${n[1]}`,languageHint:n[1],compact:!0}):(0,f.jsx)(`code`,{className:e,children:t})},x=({href:e,children:t})=>(0,f.jsx)(`a`,{href:e,target:`_blank`,rel:`noreferrer`,onClick:e=>e.stopPropagation(),children:t});function S(e,t,n=!1){return d.Children.map(e,e=>{if(typeof e==`string`)return n?e:(0,f.jsx)(y,{text:e,onOpenPath:t.onOpenPath,onPreviewPath:t.onPreviewPath,onPreviewPathEnd:t.onPreviewPathEnd,isPathLinkable:t.isPathLinkable,resolvePathTitle:t.resolvePathTitle,issueRepo:t.issueRepo});if(!d.isValidElement(e))return e;let r=e.type;if(r===y||r===x||r===`a`)return e;let i=e.props;if(i?.children==null)return e;let a=n||r===b||r===`code`||r===`pre`;return d.cloneElement(e,void 0,S(i.children,t,a))})}function C({text:e,rawBody:t,className:r,onOpenPath:o,onPreviewPath:l,onPreviewPathEnd:p,isPathLinkable:m,resolvePathTitle:h,issueRepo:_,onPrimary:v}){let y=(0,d.useMemo)(()=>a(t||``),[t]),C=w(y?y.text:e),T=i(e=>e.stats?.defaultIssueRepo),E=_??T,D=(0,d.useMemo)(()=>{let e={onOpenPath:o,onPreviewPath:l,onPreviewPathEnd:p,isPathLinkable:m,resolvePathTitle:h,issueRepo:E},t=t=>({children:n})=>(0,f.jsx)(t,{children:S(n,e)});return{p:t(`p`),li:t(`li`),h1:t(`h1`),h2:t(`h2`),h3:t(`h3`),h4:t(`h4`),h5:t(`h5`),h6:t(`h6`),td:t(`td`),th:t(`th`),blockquote:t(`blockquote`),a:x,code:b}},[o,l,p,m,h,E]);return(0,f.jsxs)(`div`,{className:r,children:[(0,f.jsx)(`div`,{className:n(`chat-markdown`,v&&`chat-markdown-on-primary`),children:(0,f.jsx)(s,{remarkPlugins:[u],rehypePlugins:[[c,g]],components:D,children:C})}),y&&y.meta.length>0&&(0,f.jsx)(`div`,{className:`mt-1.5 flex flex-wrap gap-1`,children:y.meta.map(([e,t])=>(0,f.jsxs)(`span`,{className:`inline-flex text-[10px] leading-tight bg-muted px-1.5 py-0.5 rounded text-muted-foreground font-mono`,children:[e,`: `,t]},e))})]})}function w(e){return e.includes(`\\n`)?e.replace(/\\n/g,`
|
|
2
2
|
`):e}export{C as FormattedBody};
|
|
3
|
-
//# sourceMappingURL=formatted-body-impl-
|
|
3
|
+
//# sourceMappingURL=formatted-body-impl-Csr2DuEk.js.map
|
package/public/assets/{formatted-body-impl-ZwgTH3jh.js.map → formatted-body-impl-Csr2DuEk.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatted-body-impl-ZwgTH3jh.js","names":[],"sources":["../../dashboard/src/components/shared/formatted-body-impl.tsx"],"sourcesContent":["import React, { useMemo } from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize'\nimport remarkGfm from 'remark-gfm'\nimport { CodePreview } from './code-preview'\nimport { cn } from '@/lib/utils'\nimport { parseJsonBody } from '@/lib/display'\nimport { useRelayStore } from '@/store'\n\nexport interface FormattedBodyProps {\n text: string\n rawBody?: string\n className?: string\n onOpenPath?: (path: string, line?: number) => void\n onPreviewPath?: (path: string, line?: number, anchor?: DOMRect) => void\n onPreviewPathEnd?: () => void\n isPathLinkable?: (path: string, line?: number) => boolean\n resolvePathTitle?: (path: string, line?: number) => string | undefined\n /** Per-message tracker repo (`owner/repo`) for bare `#NNN` linkify (#533) — the originating\n * agent's project repo, resolved server-side. Falls back to the server-global default (#511). */\n issueRepo?: string\n /** Rendered inside a primary-background bubble (operator's outbound message). Flips link\n * color to primary-foreground so links stay legible against the accent bg (#612). */\n onPrimary?: boolean\n}\n\n// Order matters: the issue-ref alternative (`#NNN` or `owner/repo#NNN`) is FIRST so the\n// path matcher can't swallow `owner/repo#NNN` as a file path. URLs still win when they\n// start earlier (leftmost-match), so a URL fragment like `…/a#12` is never mis-linkified.\nconst LINK_RE = /((?:[A-Za-z0-9][\\w.-]*\\/[A-Za-z0-9][\\w.-]*)?#\\d+)\\b|(https?:\\/\\/[^\\s`'\")\\]]+)|((?:\\/[\\w.@+-][^\\s`'\")\\]]*|(?:\\.{1,2}\\/|[\\w.@+-]+\\/)[^\\s`'\")\\]]*))/g\nconst TRAILING_PUNCTUATION = /[.,;:!?]+$/\nconst KNOWN_PROJECT_DIRS = new Set(['src', 'app', 'apps', 'lib', 'server', 'client', 'dashboard', 'orchestrator', 'runner', 'sdk', 'codex', 'claude', 'public', 'docs', 'test', 'tests', 'scripts', 'config', 'configs'])\n\nconst markdownSchema = {\n ...defaultSchema,\n attributes: {\n ...defaultSchema.attributes,\n code: [\n ...(defaultSchema.attributes?.code || []),\n ['className', /^language-[\\w-]+$/],\n ],\n },\n}\n\nfunction looksLikeFilePath(path: string): boolean {\n if (path === '/api' || path.startsWith('/api/')) return false\n if (path.startsWith('/')) return true\n if (path.startsWith('./') || path.startsWith('../')) return true\n const segments = path.split('/').filter(Boolean)\n const first = segments[0] ?? ''\n const last = segments[segments.length - 1] ?? ''\n if (first.startsWith('.')) return true\n if (KNOWN_PROJECT_DIRS.has(first)) return true\n return last.includes('.')\n}\n\nexport function linkParts(text: string, issueRepo?: string): Array<{ text: string; path?: string; url?: string; line?: number; issueUrl?: string }> {\n const parts: Array<{ text: string; path?: string; url?: string; line?: number; issueUrl?: string }> = []\n let cursor = 0\n for (const match of text.matchAll(LINK_RE)) {\n const rawIssue = match[1]\n const rawUrl = match[2]\n const rawPath = match[3]\n const raw = rawIssue || rawUrl || rawPath\n const index = match.index ?? 0\n if (!raw || index < cursor) continue\n\n if (rawIssue) {\n // `#NNN` (uses the configured default repo) or `owner/repo#NNN` (explicit repo).\n // With no resolvable repo we leave it as plain text — never emit a broken link.\n const hashIdx = rawIssue.lastIndexOf('#')\n const repo = rawIssue.slice(0, hashIdx) || issueRepo\n const num = rawIssue.slice(hashIdx + 1)\n // Slash-shorthand like `#508/509/513` (#531): the trailing `/509/513` is a run of\n // bare ref numbers, NOT a file path. Consume it as plain text so the path matcher\n // (which would otherwise claim `/509/...` as a phantom path link) can't reach it.\n const trailingRefs = text.slice(index + rawIssue.length).match(/^(?:\\/\\d+)+/)?.[0] ?? ''\n if (repo) {\n if (index > cursor) parts.push({ text: text.slice(cursor, index) })\n parts.push({ text: rawIssue, issueUrl: `https://github.com/${repo}/issues/${num}` })\n if (trailingRefs) parts.push({ text: trailingRefs })\n cursor = index + rawIssue.length + trailingRefs.length\n } else if (trailingRefs) {\n // No repo to link against, but still neutralize the slash run so it stays plain text.\n if (index > cursor) parts.push({ text: text.slice(cursor, index) })\n parts.push({ text: rawIssue + trailingRefs })\n cursor = index + rawIssue.length + trailingRefs.length\n }\n continue\n }\n\n if (rawUrl) {\n const url = rawUrl.replace(TRAILING_PUNCTUATION, '')\n const trimmed = rawUrl.slice(url.length)\n if (index > cursor) parts.push({ text: text.slice(cursor, index) })\n parts.push({ text: url, url })\n if (trimmed) parts.push({ text: trimmed })\n cursor = index + rawUrl.length\n continue\n }\n\n if (!raw.includes('/')) continue\n let path = raw.replace(TRAILING_PUNCTUATION, '')\n const trimmed = raw.slice(path.length)\n const lineMatch = path.match(/^(.*):(\\d+)$/)\n const line = lineMatch ? Number(lineMatch[2]) : undefined\n if (lineMatch) path = lineMatch[1]!\n if (!looksLikeFilePath(path)) continue\n if (index > cursor) parts.push({ text: text.slice(cursor, index) })\n parts.push({ text: path, path, line: Number.isFinite(line) ? line : undefined })\n if (trimmed) parts.push({ text: trimmed })\n cursor = index + raw.length\n }\n if (cursor < text.length) parts.push({ text: text.slice(cursor) })\n return parts\n}\n\nfunction TextWithLinks({\n text,\n onOpenPath,\n onPreviewPath,\n onPreviewPathEnd,\n isPathLinkable,\n resolvePathTitle,\n issueRepo,\n}: {\n text: string\n onOpenPath?: (path: string, line?: number) => void\n onPreviewPath?: (path: string, line?: number, anchor?: DOMRect) => void\n onPreviewPathEnd?: () => void\n isPathLinkable?: (path: string, line?: number) => boolean\n resolvePathTitle?: (path: string, line?: number) => string | undefined\n issueRepo?: string\n}) {\n const parts = linkParts(text, issueRepo)\n if (parts.length === 1 && !parts[0]?.path && !parts[0]?.url && !parts[0]?.issueUrl) return <>{text}</>\n return (\n <>\n {parts.map((part, index) => {\n if (part.issueUrl) {\n return (\n <a\n key={`${part.issueUrl}-${index}`}\n href={part.issueUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"font-medium underline decoration-dotted underline-offset-2\"\n onClick={(e) => e.stopPropagation()}\n >\n {part.text}\n </a>\n )\n }\n if (part.url) {\n return (\n <a\n key={`${part.url}-${index}`}\n href={part.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"underline decoration-dotted underline-offset-2\"\n onClick={(e) => e.stopPropagation()}\n >\n {part.text}\n </a>\n )\n }\n if (part.path && onOpenPath) {\n if (isPathLinkable && !isPathLinkable(part.path, part.line)) return <span key={`${part.path}-${index}`}>{part.text}{part.line ? `:${part.line}` : ''}</span>\n const resolvedTitle = resolvePathTitle?.(part.path, part.line)\n return (\n <button\n key={`${part.path}-${index}`}\n type=\"button\"\n className=\"chat-link rounded-sm font-mono underline decoration-dotted underline-offset-2\"\n onClick={(e) => { e.stopPropagation(); onOpenPath(part.path!, part.line) }}\n onMouseEnter={(e) => onPreviewPath?.(part.path!, part.line, e.currentTarget.getBoundingClientRect())}\n onFocus={(e) => onPreviewPath?.(part.path!, part.line, e.currentTarget.getBoundingClientRect())}\n onMouseLeave={() => onPreviewPathEnd?.()}\n onBlur={() => onPreviewPathEnd?.()}\n title={resolvedTitle ? `Open ${resolvedTitle}` : 'Open file'}\n >\n {part.text}{part.line ? `:${part.line}` : ''}\n </button>\n )\n }\n return <span key={index}>{part.text}</span>\n })}\n </>\n )\n}\n\ninterface LinkifyContext {\n onOpenPath?: (path: string, line?: number) => void\n onPreviewPath?: (path: string, line?: number, anchor?: DOMRect) => void\n onPreviewPathEnd?: () => void\n isPathLinkable?: (path: string, line?: number) => boolean\n resolvePathTitle?: (path: string, line?: number) => string | undefined\n issueRepo?: string\n}\n\n// Inline code & fenced blocks (the `code`/`pre` overrides) — descend with `inCode`\n// set so `#NNN` inside backticks renders verbatim instead of linkifying.\nconst CodeComponent = ({ className: codeClass, children }: { className?: string; children?: React.ReactNode }) => {\n const match = /language-([\\w-]+)/.exec(codeClass || '')\n const code = String(children).replace(/\\n$/, '')\n if (match) {\n return <CodePreview content={code} path={`.${match[1]}`} languageHint={match[1]} compact />\n }\n return <code className={codeClass}>{children}</code>\n}\n\n// Markdown links — render the anchor and pass children through untouched. The\n// recursive walk skips this subtree so we never linkify a `#NNN` *inside* link\n// text (which would nest one <a> inside another). Text adjacent to a link still\n// linkifies via the enclosing block's walk.\nconst AnchorComponent = ({ href, children }: { href?: string; children?: React.ReactNode }) => (\n <a href={href} target=\"_blank\" rel=\"noreferrer\" onClick={(e) => e.stopPropagation()}>\n {children}\n </a>\n)\n\n// Recursively linkify every text leaf in a markdown subtree (#550). react-markdown\n// hands each block override its already-rendered React children, so nested inline\n// elements (strong/em/del/headings/table cells/…) arrive as element children with\n// their text strings buried one or more levels deep. We descend through them and\n// apply `linkParts` (via TextWithLinks) at every string leaf, keeping the linkify\n// rule in this ONE place. `inCode` suppresses linkify inside code/pre; anchors are\n// left whole to avoid nested links.\nfunction processTextChildren(children: React.ReactNode, ctx: LinkifyContext, inCode = false): React.ReactNode {\n return React.Children.map(children, (child) => {\n if (typeof child === 'string') {\n if (inCode) return child\n return (\n <TextWithLinks\n text={child}\n onOpenPath={ctx.onOpenPath}\n onPreviewPath={ctx.onPreviewPath}\n onPreviewPathEnd={ctx.onPreviewPathEnd}\n isPathLinkable={ctx.isPathLinkable}\n resolvePathTitle={ctx.resolvePathTitle}\n issueRepo={ctx.issueRepo}\n />\n )\n }\n if (!React.isValidElement(child)) return child\n const type = child.type\n // Already-linkified leaves carry their text in a prop, not children — leave whole.\n if (type === TextWithLinks) return child\n // Never linkify inside a link (no nested <a>); render the anchor subtree verbatim.\n if (type === AnchorComponent || type === 'a') return child\n const props = child.props as { children?: React.ReactNode }\n if (props?.children == null) return child\n const nextInCode = inCode || type === CodeComponent || type === 'code' || type === 'pre'\n return React.cloneElement(child, undefined, processTextChildren(props.children, ctx, nextInCode))\n })\n}\n\nexport function FormattedBody({ text, rawBody, className, onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle, issueRepo: issueRepoProp, onPrimary }: FormattedBodyProps) {\n const parsed = useMemo(() => parseJsonBody(rawBody || ''), [rawBody])\n const content = unescapeNewlines(parsed ? parsed.text : text)\n // Per-message tracker repo for bare #NNN linkify (#533): the originating agent's project\n // repo (`issueRepoProp`) wins; the server-global default (#511) is only a last-resort\n // fallback for messages with no resolvable project. undefined → #NNN stays plain text.\n const globalIssueRepo = useRelayStore((s) => s.stats?.defaultIssueRepo)\n const issueRepo = issueRepoProp ?? globalIssueRepo\n\n const components = useMemo(() => {\n const ctx: LinkifyContext = { onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle, issueRepo }\n // Every text-bearing block routes its children through the recursive walk, which\n // descends into nested inline elements (strong/em/del/code/links) on its own — so\n // these stay one-liners and the linkify rule lives only in processTextChildren.\n const block = (Tag: 'p' | 'li' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'td' | 'th' | 'blockquote') =>\n ({ children }: { children?: React.ReactNode }) => <Tag>{processTextChildren(children, ctx)}</Tag>\n return {\n p: block('p'),\n li: block('li'),\n h1: block('h1'),\n h2: block('h2'),\n h3: block('h3'),\n h4: block('h4'),\n h5: block('h5'),\n h6: block('h6'),\n td: block('td'),\n th: block('th'),\n blockquote: block('blockquote'),\n a: AnchorComponent,\n code: CodeComponent,\n }\n }, [onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle, issueRepo])\n\n return (\n <div className={className}>\n <div className={cn('chat-markdown', onPrimary && 'chat-markdown-on-primary')}>\n <ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[[rehypeSanitize, markdownSchema]]} components={components}>\n {content}\n </ReactMarkdown>\n </div>\n {parsed && parsed.meta.length > 0 && (\n <div className=\"mt-1.5 flex flex-wrap gap-1\">\n {parsed.meta.map(([k, v]) => (\n <span key={k} className=\"inline-flex text-[10px] leading-tight bg-muted px-1.5 py-0.5 rounded text-muted-foreground font-mono\">\n {k}: {v}\n </span>\n ))}\n </div>\n )}\n </div>\n )\n}\n\nfunction unescapeNewlines(text: string): string {\n if (!text.includes('\\\\n')) return text\n return text.replace(/\\\\n/g, '\\n')\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"formatted-body-impl-Csr2DuEk.js","names":[],"sources":["../../dashboard/src/components/shared/formatted-body-impl.tsx"],"sourcesContent":["import React, { useMemo } from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize'\nimport remarkGfm from 'remark-gfm'\nimport { CodePreview } from './code-preview'\nimport { cn } from '@/lib/utils'\nimport { parseJsonBody } from '@/lib/display'\nimport { useRelayStore } from '@/store'\n\nexport interface FormattedBodyProps {\n text: string\n rawBody?: string\n className?: string\n onOpenPath?: (path: string, line?: number) => void\n onPreviewPath?: (path: string, line?: number, anchor?: DOMRect) => void\n onPreviewPathEnd?: () => void\n isPathLinkable?: (path: string, line?: number) => boolean\n resolvePathTitle?: (path: string, line?: number) => string | undefined\n /** Per-message tracker repo (`owner/repo`) for bare `#NNN` linkify (#533) — the originating\n * agent's project repo, resolved server-side. Falls back to the server-global default (#511). */\n issueRepo?: string\n /** Rendered inside a primary-background bubble (operator's outbound message). Flips link\n * color to primary-foreground so links stay legible against the accent bg (#612). */\n onPrimary?: boolean\n}\n\n// Order matters: the issue-ref alternative (`#NNN` or `owner/repo#NNN`) is FIRST so the\n// path matcher can't swallow `owner/repo#NNN` as a file path. URLs still win when they\n// start earlier (leftmost-match), so a URL fragment like `…/a#12` is never mis-linkified.\nconst LINK_RE = /((?:[A-Za-z0-9][\\w.-]*\\/[A-Za-z0-9][\\w.-]*)?#\\d+)\\b|(https?:\\/\\/[^\\s`'\")\\]]+)|((?:\\/[\\w.@+-][^\\s`'\")\\]]*|(?:\\.{1,2}\\/|[\\w.@+-]+\\/)[^\\s`'\")\\]]*))/g\nconst TRAILING_PUNCTUATION = /[.,;:!?]+$/\nconst KNOWN_PROJECT_DIRS = new Set(['src', 'app', 'apps', 'lib', 'server', 'client', 'dashboard', 'orchestrator', 'runner', 'sdk', 'codex', 'claude', 'public', 'docs', 'test', 'tests', 'scripts', 'config', 'configs'])\n\nconst markdownSchema = {\n ...defaultSchema,\n attributes: {\n ...defaultSchema.attributes,\n code: [\n ...(defaultSchema.attributes?.code || []),\n ['className', /^language-[\\w-]+$/],\n ],\n },\n}\n\nfunction looksLikeFilePath(path: string): boolean {\n if (path === '/api' || path.startsWith('/api/')) return false\n if (path.startsWith('/')) return true\n if (path.startsWith('./') || path.startsWith('../')) return true\n const segments = path.split('/').filter(Boolean)\n const first = segments[0] ?? ''\n const last = segments[segments.length - 1] ?? ''\n if (first.startsWith('.')) return true\n if (KNOWN_PROJECT_DIRS.has(first)) return true\n return last.includes('.')\n}\n\nexport function linkParts(text: string, issueRepo?: string): Array<{ text: string; path?: string; url?: string; line?: number; issueUrl?: string }> {\n const parts: Array<{ text: string; path?: string; url?: string; line?: number; issueUrl?: string }> = []\n let cursor = 0\n for (const match of text.matchAll(LINK_RE)) {\n const rawIssue = match[1]\n const rawUrl = match[2]\n const rawPath = match[3]\n const raw = rawIssue || rawUrl || rawPath\n const index = match.index ?? 0\n if (!raw || index < cursor) continue\n\n if (rawIssue) {\n // `#NNN` (uses the configured default repo) or `owner/repo#NNN` (explicit repo).\n // With no resolvable repo we leave it as plain text — never emit a broken link.\n const hashIdx = rawIssue.lastIndexOf('#')\n const repo = rawIssue.slice(0, hashIdx) || issueRepo\n const num = rawIssue.slice(hashIdx + 1)\n // Slash-shorthand like `#508/509/513` (#531): the trailing `/509/513` is a run of\n // bare ref numbers, NOT a file path. Consume it as plain text so the path matcher\n // (which would otherwise claim `/509/...` as a phantom path link) can't reach it.\n const trailingRefs = text.slice(index + rawIssue.length).match(/^(?:\\/\\d+)+/)?.[0] ?? ''\n if (repo) {\n if (index > cursor) parts.push({ text: text.slice(cursor, index) })\n parts.push({ text: rawIssue, issueUrl: `https://github.com/${repo}/issues/${num}` })\n if (trailingRefs) parts.push({ text: trailingRefs })\n cursor = index + rawIssue.length + trailingRefs.length\n } else if (trailingRefs) {\n // No repo to link against, but still neutralize the slash run so it stays plain text.\n if (index > cursor) parts.push({ text: text.slice(cursor, index) })\n parts.push({ text: rawIssue + trailingRefs })\n cursor = index + rawIssue.length + trailingRefs.length\n }\n continue\n }\n\n if (rawUrl) {\n const url = rawUrl.replace(TRAILING_PUNCTUATION, '')\n const trimmed = rawUrl.slice(url.length)\n if (index > cursor) parts.push({ text: text.slice(cursor, index) })\n parts.push({ text: url, url })\n if (trimmed) parts.push({ text: trimmed })\n cursor = index + rawUrl.length\n continue\n }\n\n if (!raw.includes('/')) continue\n let path = raw.replace(TRAILING_PUNCTUATION, '')\n const trimmed = raw.slice(path.length)\n const lineMatch = path.match(/^(.*):(\\d+)$/)\n const line = lineMatch ? Number(lineMatch[2]) : undefined\n if (lineMatch) path = lineMatch[1]!\n if (!looksLikeFilePath(path)) continue\n if (index > cursor) parts.push({ text: text.slice(cursor, index) })\n parts.push({ text: path, path, line: Number.isFinite(line) ? line : undefined })\n if (trimmed) parts.push({ text: trimmed })\n cursor = index + raw.length\n }\n if (cursor < text.length) parts.push({ text: text.slice(cursor) })\n return parts\n}\n\nfunction TextWithLinks({\n text,\n onOpenPath,\n onPreviewPath,\n onPreviewPathEnd,\n isPathLinkable,\n resolvePathTitle,\n issueRepo,\n}: {\n text: string\n onOpenPath?: (path: string, line?: number) => void\n onPreviewPath?: (path: string, line?: number, anchor?: DOMRect) => void\n onPreviewPathEnd?: () => void\n isPathLinkable?: (path: string, line?: number) => boolean\n resolvePathTitle?: (path: string, line?: number) => string | undefined\n issueRepo?: string\n}) {\n const parts = linkParts(text, issueRepo)\n if (parts.length === 1 && !parts[0]?.path && !parts[0]?.url && !parts[0]?.issueUrl) return <>{text}</>\n return (\n <>\n {parts.map((part, index) => {\n if (part.issueUrl) {\n return (\n <a\n key={`${part.issueUrl}-${index}`}\n href={part.issueUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"font-medium underline decoration-dotted underline-offset-2\"\n onClick={(e) => e.stopPropagation()}\n >\n {part.text}\n </a>\n )\n }\n if (part.url) {\n return (\n <a\n key={`${part.url}-${index}`}\n href={part.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"underline decoration-dotted underline-offset-2\"\n onClick={(e) => e.stopPropagation()}\n >\n {part.text}\n </a>\n )\n }\n if (part.path && onOpenPath) {\n if (isPathLinkable && !isPathLinkable(part.path, part.line)) return <span key={`${part.path}-${index}`}>{part.text}{part.line ? `:${part.line}` : ''}</span>\n const resolvedTitle = resolvePathTitle?.(part.path, part.line)\n return (\n <button\n key={`${part.path}-${index}`}\n type=\"button\"\n className=\"chat-link rounded-sm font-mono underline decoration-dotted underline-offset-2\"\n onClick={(e) => { e.stopPropagation(); onOpenPath(part.path!, part.line) }}\n onMouseEnter={(e) => onPreviewPath?.(part.path!, part.line, e.currentTarget.getBoundingClientRect())}\n onFocus={(e) => onPreviewPath?.(part.path!, part.line, e.currentTarget.getBoundingClientRect())}\n onMouseLeave={() => onPreviewPathEnd?.()}\n onBlur={() => onPreviewPathEnd?.()}\n title={resolvedTitle ? `Open ${resolvedTitle}` : 'Open file'}\n >\n {part.text}{part.line ? `:${part.line}` : ''}\n </button>\n )\n }\n return <span key={index}>{part.text}</span>\n })}\n </>\n )\n}\n\ninterface LinkifyContext {\n onOpenPath?: (path: string, line?: number) => void\n onPreviewPath?: (path: string, line?: number, anchor?: DOMRect) => void\n onPreviewPathEnd?: () => void\n isPathLinkable?: (path: string, line?: number) => boolean\n resolvePathTitle?: (path: string, line?: number) => string | undefined\n issueRepo?: string\n}\n\n// Inline code & fenced blocks (the `code`/`pre` overrides) — descend with `inCode`\n// set so `#NNN` inside backticks renders verbatim instead of linkifying.\nconst CodeComponent = ({ className: codeClass, children }: { className?: string; children?: React.ReactNode }) => {\n const match = /language-([\\w-]+)/.exec(codeClass || '')\n const code = String(children).replace(/\\n$/, '')\n if (match) {\n return <CodePreview content={code} path={`.${match[1]}`} languageHint={match[1]} compact />\n }\n return <code className={codeClass}>{children}</code>\n}\n\n// Markdown links — render the anchor and pass children through untouched. The\n// recursive walk skips this subtree so we never linkify a `#NNN` *inside* link\n// text (which would nest one <a> inside another). Text adjacent to a link still\n// linkifies via the enclosing block's walk.\nconst AnchorComponent = ({ href, children }: { href?: string; children?: React.ReactNode }) => (\n <a href={href} target=\"_blank\" rel=\"noreferrer\" onClick={(e) => e.stopPropagation()}>\n {children}\n </a>\n)\n\n// Recursively linkify every text leaf in a markdown subtree (#550). react-markdown\n// hands each block override its already-rendered React children, so nested inline\n// elements (strong/em/del/headings/table cells/…) arrive as element children with\n// their text strings buried one or more levels deep. We descend through them and\n// apply `linkParts` (via TextWithLinks) at every string leaf, keeping the linkify\n// rule in this ONE place. `inCode` suppresses linkify inside code/pre; anchors are\n// left whole to avoid nested links.\nfunction processTextChildren(children: React.ReactNode, ctx: LinkifyContext, inCode = false): React.ReactNode {\n return React.Children.map(children, (child) => {\n if (typeof child === 'string') {\n if (inCode) return child\n return (\n <TextWithLinks\n text={child}\n onOpenPath={ctx.onOpenPath}\n onPreviewPath={ctx.onPreviewPath}\n onPreviewPathEnd={ctx.onPreviewPathEnd}\n isPathLinkable={ctx.isPathLinkable}\n resolvePathTitle={ctx.resolvePathTitle}\n issueRepo={ctx.issueRepo}\n />\n )\n }\n if (!React.isValidElement(child)) return child\n const type = child.type\n // Already-linkified leaves carry their text in a prop, not children — leave whole.\n if (type === TextWithLinks) return child\n // Never linkify inside a link (no nested <a>); render the anchor subtree verbatim.\n if (type === AnchorComponent || type === 'a') return child\n const props = child.props as { children?: React.ReactNode }\n if (props?.children == null) return child\n const nextInCode = inCode || type === CodeComponent || type === 'code' || type === 'pre'\n return React.cloneElement(child, undefined, processTextChildren(props.children, ctx, nextInCode))\n })\n}\n\nexport function FormattedBody({ text, rawBody, className, onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle, issueRepo: issueRepoProp, onPrimary }: FormattedBodyProps) {\n const parsed = useMemo(() => parseJsonBody(rawBody || ''), [rawBody])\n const content = unescapeNewlines(parsed ? parsed.text : text)\n // Per-message tracker repo for bare #NNN linkify (#533): the originating agent's project\n // repo (`issueRepoProp`) wins; the server-global default (#511) is only a last-resort\n // fallback for messages with no resolvable project. undefined → #NNN stays plain text.\n const globalIssueRepo = useRelayStore((s) => s.stats?.defaultIssueRepo)\n const issueRepo = issueRepoProp ?? globalIssueRepo\n\n const components = useMemo(() => {\n const ctx: LinkifyContext = { onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle, issueRepo }\n // Every text-bearing block routes its children through the recursive walk, which\n // descends into nested inline elements (strong/em/del/code/links) on its own — so\n // these stay one-liners and the linkify rule lives only in processTextChildren.\n const block = (Tag: 'p' | 'li' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'td' | 'th' | 'blockquote') =>\n ({ children }: { children?: React.ReactNode }) => <Tag>{processTextChildren(children, ctx)}</Tag>\n return {\n p: block('p'),\n li: block('li'),\n h1: block('h1'),\n h2: block('h2'),\n h3: block('h3'),\n h4: block('h4'),\n h5: block('h5'),\n h6: block('h6'),\n td: block('td'),\n th: block('th'),\n blockquote: block('blockquote'),\n a: AnchorComponent,\n code: CodeComponent,\n }\n }, [onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle, issueRepo])\n\n return (\n <div className={className}>\n <div className={cn('chat-markdown', onPrimary && 'chat-markdown-on-primary')}>\n <ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[[rehypeSanitize, markdownSchema]]} components={components}>\n {content}\n </ReactMarkdown>\n </div>\n {parsed && parsed.meta.length > 0 && (\n <div className=\"mt-1.5 flex flex-wrap gap-1\">\n {parsed.meta.map(([k, v]) => (\n <span key={k} className=\"inline-flex text-[10px] leading-tight bg-muted px-1.5 py-0.5 rounded text-muted-foreground font-mono\">\n {k}: {v}\n </span>\n ))}\n </div>\n )}\n </div>\n )\n}\n\nfunction unescapeNewlines(text: string): string {\n if (!text.includes('\\\\n')) return text\n return text.replace(/\\\\n/g, '\\n')\n}\n"],"mappings":"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"}
|