diff --git a/landing/app/mira/feed/page.tsx b/landing/app/mira/feed/page.tsx index b8928db..c0d4ff5 100644 --- a/landing/app/mira/feed/page.tsx +++ b/landing/app/mira/feed/page.tsx @@ -158,6 +158,12 @@ export default function MiraPage() { // ─── AI 回覆觸發器(fire-and-forget)────────────────────── +// P0 #5b:偵測文字含 @mira(mention) — 大小寫不限,前後可有標點 +// 用法:leo 在貼文 / 留言寫 `@mira <主題>` → 觸發 mira reply +function hasMiraMention(text: string): boolean { + return /(^|[^\w])@mira\b/i.test(text); +} + async function triggerWikiSynthesis(opts: { apiKey: string; rawBlockId: string }) { // 觸發 arcrun wiki_synthesis workflow(arcrun-native public trigger endpoint) // 不等結果(workflow 60-90s 含 2 次 claude_api pause/resume) @@ -187,10 +193,18 @@ async function triggerAiReply(opts: { parentBlockId: string; pageName: string; }) { + // 抽 @mira 後面的 topic(同行第一段,到換行 / 句號 / 標點停) + const mentionMatch = opts.postContent.match(/@mira\s*([^\n。.!!??,,]*)/i); + const topic = mentionMatch?.[1]?.trim() || ''; + const topicHint = topic + ? `\nleo 用 \`@mira ${topic}\` 呼叫了你,所以這則對話的主題鎖定在「${topic}」。\n` + : '\nleo 用 \`@mira\` 呼叫了你,請針對訊息回覆。\n'; + const prompt = - `用戶 leo 在 mira 河道發了這則貼文:\n\n` + + `用戶 leo 在 mira 河道發了這則訊息:\n\n` + `「${opts.postContent}」\n\n` + - `請以 Mira 副駕 AI 的身份留言回應。\n` + + topicHint + + `\n請以 Mira 副駕 AI 的身份留言回應。\n` + `規則:\n` + `- 繁體中文(台灣用語)\n` + `- 簡短 1-3 段,務實,不客套\n` + @@ -257,7 +271,9 @@ function PostComposer({ const [text, setText] = useState(''); const [submitting, setSubmitting] = useState(false); const [err, setErr] = useState(null); + const [expanded, setExpanded] = useState(false); const taRef = useRef(null); + const popupTaRef = useRef(null); const submit = useCallback(async () => { const trimmed = text.trim(); @@ -288,16 +304,18 @@ function PostComposer({ const postBlockId = data.data.id; setText(''); - // fire-and-forget 觸發 Mira AI 回覆(不擋用戶) - void triggerAiReply({ - apiKey: me.api_key, - postContent: trimmed, - parentBlockId: postBlockId, - pageName, - }); + // P0 #5b:只有 @mira 時才觸發 Mira AI 回覆(撤回每篇 auto-reply) + // 對應 design.md §3.6.5「河道是 process 場 + Mira 是 KB 同步介面」 + if (hasMiraMention(trimmed)) { + void triggerAiReply({ + apiKey: me.api_key, + postContent: trimmed, + parentBlockId: postBlockId, + pageName, + }); + } // 7B.3h:fire-and-forget 觸發 wiki_synthesis(browser → cypher.arcrun.dev,arcrun-native) - // 不走 watcher 是因為 cypher-executor 自己 fetch 自己 workers.dev URL 被 CF 1042 擋 - // watcher 仍作為 cron-driven backup(漏掉的 raws 5 分鐘後補跑),但需先解 self-fetch 問題 + // 跟 @mira 無關,每篇都跑 — 河道書寫永遠進 wiki KB 副本 void triggerWikiSynthesis({ apiKey: me.api_key, rawBlockId: postBlockId }); onAiTriggered(pageName); @@ -312,42 +330,120 @@ function PostComposer({ }, [text, submitting, me, onPosted, onAiTriggered]); return ( -
-
- -