feat(aircoding): AirCoding V2 baseline — deterministic multi-agent architecture
Forked from OpenCode v1.17.4 with multi-agent system: - 5 agents: aircoding, scheduler, worker, architect, reviewer - Deterministic DAG scheduling engine (coordinator_tick) - Tool whitelists as hard enforcement - AirCoding validation plugin - System prompt injection for routing - V1 requirements: C4 docs, ADR, AGENTS.md, debug-log.md - Design documents in docs/
This commit is contained in:
74
packages/web/src/components/share/content-markdown.tsx
Normal file
74
packages/web/src/components/share/content-markdown.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import { marked } from "marked"
|
||||
import { codeToHtml } from "shiki"
|
||||
import markedShiki from "marked-shiki"
|
||||
import { createOverflow, useShareMessages } from "./common"
|
||||
import { CopyButton } from "./copy-button"
|
||||
import { createResource, createSignal } from "solid-js"
|
||||
import style from "./content-markdown.module.css"
|
||||
|
||||
const markedWithShiki = marked.use(
|
||||
{
|
||||
renderer: {
|
||||
link({ href, title, text }) {
|
||||
const titleAttr = title ? ` title="${title}"` : ""
|
||||
return `<a href="${href}"${titleAttr} target="_blank" rel="noopener noreferrer">${text}</a>`
|
||||
},
|
||||
},
|
||||
},
|
||||
markedShiki({
|
||||
highlight(code, lang) {
|
||||
return codeToHtml(code, {
|
||||
lang: lang || "text",
|
||||
themes: {
|
||||
light: "github-light",
|
||||
dark: "github-dark",
|
||||
},
|
||||
})
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
interface Props {
|
||||
text: string
|
||||
expand?: boolean
|
||||
highlight?: boolean
|
||||
}
|
||||
export function ContentMarkdown(props: Props) {
|
||||
const [html] = createResource(
|
||||
() => strip(props.text),
|
||||
async (markdown) => {
|
||||
return markedWithShiki.parse(markdown)
|
||||
},
|
||||
)
|
||||
const [expanded, setExpanded] = createSignal(false)
|
||||
const overflow = createOverflow()
|
||||
const messages = useShareMessages()
|
||||
|
||||
return (
|
||||
<div
|
||||
class={style.root}
|
||||
data-highlight={props.highlight === true ? true : undefined}
|
||||
data-expanded={expanded() || props.expand === true ? true : undefined}
|
||||
>
|
||||
<div data-slot="markdown" ref={overflow.ref} innerHTML={html()} />
|
||||
|
||||
{!props.expand && overflow.status && (
|
||||
<button
|
||||
type="button"
|
||||
data-component="text-button"
|
||||
data-slot="expand-button"
|
||||
onClick={() => setExpanded((e) => !e)}
|
||||
>
|
||||
{expanded() ? messages.show_less : messages.show_more}
|
||||
</button>
|
||||
)}
|
||||
<CopyButton text={props.text} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function strip(text: string): string {
|
||||
const wrappedRe = /^\s*<([A-Za-z]\w*)>\s*([\s\S]*?)\s*<\/\1>\s*$/
|
||||
const match = text.match(wrappedRe)
|
||||
return match ? match[2] : text
|
||||
}
|
||||
Reference in New Issue
Block a user