agent-relay-server 0.38.0 → 0.40.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 +2 -2
- package/public/assets/{activity-ClpDglG8.js → activity-DAz3DcDA.js} +2 -2
- package/public/assets/{activity-ClpDglG8.js.map → activity-DAz3DcDA.js.map} +1 -1
- package/public/assets/{agents-CHmEJvqV.js → agents-BJ7qRWxt.js} +2 -2
- package/public/assets/{agents-CHmEJvqV.js.map → agents-BJ7qRWxt.js.map} +1 -1
- package/public/assets/{analytics-2kTjXIj1.js → analytics-MNCS2qnT.js} +2 -2
- package/public/assets/{analytics-2kTjXIj1.js.map → analytics-MNCS2qnT.js.map} +1 -1
- package/public/assets/{automation-B5U_g-1P.js → automation-COp2Kb3h.js} +2 -2
- package/public/assets/{automation-B5U_g-1P.js.map → automation-COp2Kb3h.js.map} +1 -1
- package/public/assets/chat-D_O8VqMR.js +2 -0
- package/public/assets/chat-D_O8VqMR.js.map +1 -0
- package/public/assets/display-ConJ9cJB.js.map +1 -1
- package/public/assets/{formatted-body-impl-tmf8IBfr.js → formatted-body-impl-BbMHqkCy.js} +2 -2
- package/public/assets/{formatted-body-impl-tmf8IBfr.js.map → formatted-body-impl-BbMHqkCy.js.map} +1 -1
- package/public/assets/{index-B1QUkb_O.js → index-DgJOEApM.js} +5 -5
- package/public/assets/{index-B1QUkb_O.js.map → index-DgJOEApM.js.map} +1 -1
- package/public/assets/{index-Bins8N_5.css → index-Dop-uXiy.css} +1 -1
- package/public/assets/{maintenance-Tn23oWBF.js → maintenance-BHv90kXZ.js} +2 -2
- package/public/assets/{maintenance-Tn23oWBF.js.map → maintenance-BHv90kXZ.js.map} +1 -1
- package/public/assets/managed-agents-BAlvkxfo.js +2 -0
- package/public/assets/managed-agents-BAlvkxfo.js.map +1 -0
- package/public/assets/{markdown-preview-impl-D4UIjB3I.js → markdown-preview-impl-6k_FWjmd.js} +2 -2
- package/public/assets/{markdown-preview-impl-D4UIjB3I.js.map → markdown-preview-impl-6k_FWjmd.js.map} +1 -1
- package/public/assets/{memory-SVCob0fo.js → memory-DBjqdVpg.js} +2 -2
- package/public/assets/{memory-SVCob0fo.js.map → memory-DBjqdVpg.js.map} +1 -1
- package/public/assets/{messages-CHK24Uxx.js → messages-axoaJY2N.js} +2 -2
- package/public/assets/{messages-CHK24Uxx.js.map → messages-axoaJY2N.js.map} +1 -1
- package/public/assets/{orchestrators-CQcJb6VE.js → orchestrators-DMfHZ44H.js} +2 -2
- package/public/assets/{orchestrators-CQcJb6VE.js.map → orchestrators-DMfHZ44H.js.map} +1 -1
- package/public/assets/{overview-DbyX7k-7.js → overview-DqxYWpUT.js} +2 -2
- package/public/assets/{overview-DbyX7k-7.js.map → overview-DqxYWpUT.js.map} +1 -1
- package/public/assets/{pairs-CaL0_ZfW.js → pairs-D3wnzC1V.js} +2 -2
- package/public/assets/{pairs-CaL0_ZfW.js.map → pairs-D3wnzC1V.js.map} +1 -1
- package/public/assets/{security-BogsfkbT.js → security-KWrb7PKj.js} +2 -2
- package/public/assets/{security-BogsfkbT.js.map → security-KWrb7PKj.js.map} +1 -1
- package/public/assets/{settings-BOsnUh5f.js → settings-PXMEzNAm.js} +2 -2
- package/public/assets/{settings-BOsnUh5f.js.map → settings-PXMEzNAm.js.map} +1 -1
- package/public/assets/{tasks-CCxQovOv.js → tasks-CFYShBCz.js} +2 -2
- package/public/assets/{tasks-CCxQovOv.js.map → tasks-CFYShBCz.js.map} +1 -1
- package/public/assets/{terminal-viewer-impl-BDikdsxs.js → terminal-viewer-impl-BwPYZlWI.js} +2 -2
- package/public/assets/{terminal-viewer-impl-BDikdsxs.js.map → terminal-viewer-impl-BwPYZlWI.js.map} +1 -1
- package/public/assets/{work-queue-fM-tu0iP.js → work-queue-VQ_6QDJc.js} +2 -2
- package/public/assets/{work-queue-fM-tu0iP.js.map → work-queue-VQ_6QDJc.js.map} +1 -1
- package/public/index.html +2 -2
- package/runner/src/adapter.ts +5 -1
- package/src/config-store.ts +1 -1
- package/src/db/messages.ts +36 -2
- package/src/db/migrations.ts +5 -0
- package/src/lifecycle-manager.ts +74 -6
- package/src/maintenance.ts +20 -27
- package/src/reviewer-pipeline.ts +197 -0
- package/src/routes/commands.ts +28 -0
- package/src/services/managed-running.ts +1 -0
- package/src/services/send-message.ts +4 -0
- package/src/workspace-pr-completion.ts +121 -0
- package/public/assets/chat-zPXWB-03.js +0 -2
- package/public/assets/chat-zPXWB-03.js.map +0 -1
- package/public/assets/managed-agents-CasacvJX.js +0 -2
- package/public/assets/managed-agents-CasacvJX.js.map +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{An as t,Hn as n}from"./lucide-react-DLQFnqNm.js";import{P as r}from"./display-ConJ9cJB.js";import{S as i}from"./index-
|
|
1
|
+
import{r as e}from"./chunk-CilyBKbf.js";import{An as t,Hn as n}from"./lucide-react-DLQFnqNm.js";import{P as r}from"./display-ConJ9cJB.js";import{S as i}from"./index-DgJOEApM.js";import{i as a,n as o,r as s,t as c}from"./lib-BAE--T4O.js";var l=e(n(),1),u=t(),d=/(https?:\/\/[^\s`'")\]]+)|((?:\/[\w.@+-][^\s`'")\]]*|(?:\.{1,2}\/|[\w.@+-]+\/)[^\s`'")\]]*))/g,f=/[.,;:!?]+$/,p=new Set([`src`,`app`,`apps`,`lib`,`server`,`client`,`dashboard`,`orchestrator`,`runner`,`sdk`,`codex`,`claude`,`public`,`docs`,`test`,`tests`,`scripts`,`config`,`configs`]),m={...s,attributes:{...s.attributes,code:[...s.attributes?.code||[],[`className`,/^language-[\w-]+$/]]}};function h(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(`.`)||p.has(n)?!0:r.includes(`.`)}function g(e){let t=[],n=0;for(let r of e.matchAll(d)){let i=r[1],a=r[2],o=i||a,s=r.index??0;if(!o||s<n)continue;if(i){let r=i.replace(f,``),a=i.slice(r.length);s>n&&t.push({text:e.slice(n,s)}),t.push({text:r,url:r}),a&&t.push({text:a}),n=s+i.length;continue}if(!o.includes(`/`))continue;let c=o.replace(f,``),l=o.slice(c.length),u=c.match(/^(.*):(\d+)$/),d=u?Number(u[2]):void 0;u&&(c=u[1]),h(c)&&(s>n&&t.push({text:e.slice(n,s)}),t.push({text:c,path:c,line:Number.isFinite(d)?d:void 0}),l&&t.push({text:l}),n=s+o.length)}return n<e.length&&t.push({text:e.slice(n)}),t}function _({text:e,onOpenPath:t,onPreviewPath:n,onPreviewPathEnd:r,isPathLinkable:i,resolvePathTitle:a}){let o=g(e);return o.length===1&&!o[0]?.path&&!o[0]?.url?(0,u.jsx)(u.Fragment,{children:e}):(0,u.jsx)(u.Fragment,{children:o.map((e,o)=>{if(e.url)return(0,u.jsx)(`a`,{href:e.url,target:`_blank`,rel:`noreferrer`,className:`underline decoration-dotted underline-offset-2 hover:text-primary`,onClick:e=>e.stopPropagation(),children:e.text},`${e.url}-${o}`);if(e.path&&t){if(i&&!i(e.path,e.line))return(0,u.jsxs)(`span`,{children:[e.text,e.line?`:${e.line}`:``]},`${e.path}-${o}`);let s=a?.(e.path,e.line);return(0,u.jsxs)(`button`,{type:`button`,className:`rounded-sm font-mono underline decoration-dotted underline-offset-2 hover:text-primary`,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,u.jsx)(`span`,{children:e.text},o)})})}function v(e,t,n,r,i,a){return l.Children.map(e,e=>typeof e==`string`?(0,u.jsx)(_,{text:e,onOpenPath:t,onPreviewPath:n,onPreviewPathEnd:r,isPathLinkable:i,resolvePathTitle:a}):e)}function y({text:e,rawBody:t,className:n,onOpenPath:s,onPreviewPath:d,onPreviewPathEnd:f,isPathLinkable:p,resolvePathTitle:h}){let g=(0,l.useMemo)(()=>r(t||``),[t]),_=b(g?g.text:e),y=(0,l.useMemo)(()=>({p({children:e}){return(0,u.jsx)(`p`,{children:v(e,s,d,f,p,h)})},li({children:e}){return(0,u.jsx)(`li`,{children:v(e,s,d,f,p,h)})},a({href:e,children:t}){return(0,u.jsx)(`a`,{href:e,target:`_blank`,rel:`noreferrer`,onClick:e=>e.stopPropagation(),children:t})},code({className:e,children:t}){let n=/language-([\w-]+)/.exec(e||``),r=String(t).replace(/\n$/,``);return n?(0,u.jsx)(i,{content:r,path:`.${n[1]}`,languageHint:n[1],compact:!0}):(0,u.jsx)(`code`,{className:e,children:t})}}),[s,d,f,p,h]);return(0,u.jsxs)(`div`,{className:n,children:[(0,u.jsx)(`div`,{className:`chat-markdown`,children:(0,u.jsx)(a,{remarkPlugins:[c],rehypePlugins:[[o,m]],components:y,children:_})}),g&&g.meta.length>0&&(0,u.jsx)(`div`,{className:`mt-1.5 flex flex-wrap gap-1`,children:g.meta.map(([e,t])=>(0,u.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 b(e){return e.includes(`\\n`)?e.replace(/\\n/g,`
|
|
2
2
|
`):e}export{y as FormattedBody};
|
|
3
|
-
//# sourceMappingURL=formatted-body-impl-
|
|
3
|
+
//# sourceMappingURL=formatted-body-impl-BbMHqkCy.js.map
|
package/public/assets/{formatted-body-impl-tmf8IBfr.js.map → formatted-body-impl-BbMHqkCy.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatted-body-impl-tmf8IBfr.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'\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}\n\nconst LINK_RE = /(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\nfunction linkParts(text: string): Array<{ text: string; path?: string; url?: string; line?: number }> {\n const parts: Array<{ text: string; path?: string; url?: string; line?: number }> = []\n let cursor = 0\n for (const match of text.matchAll(LINK_RE)) {\n const rawUrl = match[1]\n const rawPath = match[2]\n const raw = rawUrl || rawPath\n const index = match.index ?? 0\n if (!raw || index < cursor) continue\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}: {\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}) {\n const parts = linkParts(text)\n if (parts.length === 1 && !parts[0]?.path && !parts[0]?.url) return <>{text}</>\n return (\n <>\n {parts.map((part, index) => {\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 hover:text-primary\"\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=\"rounded-sm font-mono underline decoration-dotted underline-offset-2 hover:text-primary\"\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\nfunction processTextChildren(\n children: React.ReactNode,\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): React.ReactNode {\n return React.Children.map(children, (child) =>\n typeof child === 'string'\n ? <TextWithLinks text={child} onOpenPath={onOpenPath} onPreviewPath={onPreviewPath} onPreviewPathEnd={onPreviewPathEnd} isPathLinkable={isPathLinkable} resolvePathTitle={resolvePathTitle} />\n : child\n )\n}\n\nexport function FormattedBody({ text, rawBody, className, onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle }: FormattedBodyProps) {\n const parsed = useMemo(() => parseJsonBody(rawBody || ''), [rawBody])\n const content = unescapeNewlines(parsed ? parsed.text : text)\n\n const components = useMemo(() => ({\n p({ children }: { children?: React.ReactNode }) {\n return <p>{processTextChildren(children, onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle)}</p>\n },\n li({ children }: { children?: React.ReactNode }) {\n return <li>{processTextChildren(children, onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle)}</li>\n },\n a({ href, children }: { href?: string; children?: React.ReactNode }) {\n return (\n <a href={href} target=\"_blank\" rel=\"noreferrer\" onClick={(e) => e.stopPropagation()}>\n {children}\n </a>\n )\n },\n code({ 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 }), [onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle])\n\n return (\n <div className={className}>\n <div className=\"chat-markdown\">\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-BbMHqkCy.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'\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}\n\nconst LINK_RE = /(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\nfunction linkParts(text: string): Array<{ text: string; path?: string; url?: string; line?: number }> {\n const parts: Array<{ text: string; path?: string; url?: string; line?: number }> = []\n let cursor = 0\n for (const match of text.matchAll(LINK_RE)) {\n const rawUrl = match[1]\n const rawPath = match[2]\n const raw = rawUrl || rawPath\n const index = match.index ?? 0\n if (!raw || index < cursor) continue\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}: {\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}) {\n const parts = linkParts(text)\n if (parts.length === 1 && !parts[0]?.path && !parts[0]?.url) return <>{text}</>\n return (\n <>\n {parts.map((part, index) => {\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 hover:text-primary\"\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=\"rounded-sm font-mono underline decoration-dotted underline-offset-2 hover:text-primary\"\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\nfunction processTextChildren(\n children: React.ReactNode,\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): React.ReactNode {\n return React.Children.map(children, (child) =>\n typeof child === 'string'\n ? <TextWithLinks text={child} onOpenPath={onOpenPath} onPreviewPath={onPreviewPath} onPreviewPathEnd={onPreviewPathEnd} isPathLinkable={isPathLinkable} resolvePathTitle={resolvePathTitle} />\n : child\n )\n}\n\nexport function FormattedBody({ text, rawBody, className, onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle }: FormattedBodyProps) {\n const parsed = useMemo(() => parseJsonBody(rawBody || ''), [rawBody])\n const content = unescapeNewlines(parsed ? parsed.text : text)\n\n const components = useMemo(() => ({\n p({ children }: { children?: React.ReactNode }) {\n return <p>{processTextChildren(children, onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle)}</p>\n },\n li({ children }: { children?: React.ReactNode }) {\n return <li>{processTextChildren(children, onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle)}</li>\n },\n a({ href, children }: { href?: string; children?: React.ReactNode }) {\n return (\n <a href={href} target=\"_blank\" rel=\"noreferrer\" onClick={(e) => e.stopPropagation()}>\n {children}\n </a>\n )\n },\n code({ 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 }), [onOpenPath, onPreviewPath, onPreviewPathEnd, isPathLinkable, resolvePathTitle])\n\n return (\n <div className={className}>\n <div className=\"chat-markdown\">\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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"}
|