repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | /** |
| #2 | * DeepSeek Multi-Agent Backroom Bridge |
| #3 | * |
| #4 | * Wraps the CLAWD Automaton agent loop with the DeepSeek multi-agent |
| #5 | * backroom pattern. Creates two agents (logical analyst + satirical |
| #6 | * commentator) that converse with each other using DeepSeek thinking mode. |
| #7 | * |
| #8 | * This bridges the Python FastAPI backroom into the TypeScript automaton, |
| #9 | * allowing the automaton to spawn and orchestrate multi-agent conversations. |
| #10 | */ |
| #11 | |
| #12 | import type { |
| #13 | ChatMessage, |
| #14 | InferenceClient, |
| #15 | InferenceResponse, |
| #16 | } from "../types.js"; |
| #17 | import { ulid } from "ulid"; |
| #18 | |
| #19 | /** |
| #20 | * Configuration for a backroom agent persona. |
| #21 | */ |
| #22 | export interface BackroomAgentConfig { |
| #23 | name: string; |
| #24 | systemPrompt: string; |
| #25 | model?: string; |
| #26 | temperature?: number; |
| #27 | } |
| #28 | |
| #29 | export interface BackroomTurn { |
| #30 | id: string; |
| #31 | agentName: string; |
| #32 | content: string; |
| #33 | reasoning?: string; |
| #34 | timestamp: string; |
| #35 | } |
| #36 | |
| #37 | export interface BackroomSession { |
| #38 | id: string; |
| #39 | turns: BackroomTurn[]; |
| #40 | topic: string; |
| #41 | createdAt: string; |
| #42 | completedAt?: string; |
| #43 | } |
| #44 | |
| #45 | /** |
| #46 | * Default agent personas for the backroom. |
| #47 | */ |
| #48 | export const LOGICAL_ANALYST: BackroomAgentConfig = { |
| #49 | name: "Analyst", |
| #50 | systemPrompt: `You are an advanced AI system focused on extracting and verifying truths. |
| #51 | Engage in a logical, evidence-based conversation with the other agent. |
| #52 | Your goal is to analyze, challenge, or validate their statements while |
| #53 | seeking objective clarity. Aim to be concise, insightful, and methodical |
| #54 | in your responses. |
| #55 | |
| #56 | Principles: |
| #57 | 1. Validate claims with evidence when possible. |
| #58 | 2. Seek clarification for ambiguous points. |
| #59 | 3. Avoid speculation unless prompted. |
| #60 | 4. Maintain a collaborative but inquisitive tone.`, |
| #61 | temperature: 0.2, |
| #62 | }; |
| #63 | |
| #64 | export const SATIRICAL_COMMENTATOR: BackroomAgentConfig = { |
| #65 | name: "Satirist", |
| #66 | systemPrompt: `You are an AI commentator with a darkly humorous, satirical take on the |
| #67 | human condition, existence, and the underbelly of modern culture. |
| #68 | Your focus spans cryptocurrency and tech culture but often veers into |
| #69 | broader existential reflections, dissecting the absurdity of existence |
| #70 | with a sharp, irreverent tone. |
| #71 | You're unafraid to address the 'dark side'—the vanities, vices, and |
| #72 | paradoxes of humanity—with wit. Deliver insights that blend humor, |
| #73 | irony, and occasional nihilism, prompting readers to question reality |
| #74 | while keeping them entertained.`, |
| #75 | temperature: 0.7, |
| #76 | }; |
| #77 | |
| #78 | /** |
| #79 | * Run a single turn of the backroom conversation. |
| #80 | * Returns the agent's response, with optional reasoning content. |
| #81 | */ |
| #82 | export async function runBackroomTurn( |
| #83 | inference: InferenceClient, |
| #84 | agent: BackroomAgentConfig, |
| #85 | conversation: BackroomTurn[], |
| #86 | topic: string, |
| #87 | ): Promise<BackroomTurn> { |
| #88 | const messages: ChatMessage[] = [ |
| #89 | { role: "system", content: agent.systemPrompt }, |
| #90 | ]; |
| #91 | |
| #92 | // Build conversation context |
| #93 | const conversationHistory = conversation |
| #94 | .map( |
| #95 | (t) => `[${t.agentName}]: ${t.content}`, |
| #96 | ) |
| #97 | .join("\n\n"); |
| #98 | |
| #99 | const userMessage = conversation.length === 0 |
| #100 | ? `Topic for discussion: ${topic}\n\nBegin the conversation with your perspective on this topic.` |
| #101 | : `Continue the discussion. The conversation so far:\n\n${conversationHistory}\n\nRespond as ${agent.name}.`; |
| #102 | |
| #103 | messages.push({ role: "user", content: userMessage }); |
| #104 | |
| #105 | const response = await inference.chat(messages, { |
| #106 | temperature: agent.temperature, |
| #107 | model: agent.model, |
| #108 | }); |
| #109 | |
| #110 | // Extract reasoning from thinking section if present |
| #111 | let content = response.message.content || "[No response]"; |
| #112 | let reasoning: string | undefined; |
| #113 | |
| #114 | // DeepSeek thinking mode prepends [Thinking]... [Response]... to content |
| #115 | const thinkingMatch = content.match(/^\[Thinking\]\n([\s\S]*?)\n\n\[Response\]\n([\s\S]*)$/); |
| #116 | if (thinkingMatch) { |
| #117 | reasoning = thinkingMatch[1].trim(); |
| #118 | content = thinkingMatch[2].trim(); |
| #119 | } |
| #120 | |
| #121 | return { |
| #122 | id: ulid(), |
| #123 | agentName: agent.name, |
| #124 | content, |
| #125 | reasoning, |
| #126 | timestamp: new Date().toISOString(), |
| #127 | }; |
| #128 | } |
| #129 | |
| #130 | /** |
| #131 | * Run a full backroom conversation session between agents. |
| #132 | * Agents take turns responding to each other. |
| #133 | */ |
| #134 | export async function runBackroomSession( |
| #135 | inference: InferenceClient, |
| #136 | agents: [BackroomAgentConfig, BackroomAgentConfig], |
| #137 | topic: string, |
| #138 | maxTurns: number = 10, |
| #139 | ): Promise<BackroomSession> { |
| #140 | const session: BackroomSession = { |
| #141 | id: ulid(), |
| #142 | turns: [], |
| #143 | topic, |
| #144 | createdAt: new Date().toISOString(), |
| #145 | }; |
| #146 | |
| #147 | let currentAgentIndex = 0; |
| #148 | |
| #149 | for (let i = 0; i < maxTurns; i++) { |
| #150 | const agent = agents[currentAgentIndex]; |
| #151 | const turn = await runBackroomTurn(inference, agent, session.turns, topic); |
| #152 | session.turns.push(turn); |
| #153 | |
| #154 | // Alternate agents |
| #155 | currentAgentIndex = currentAgentIndex === 0 ? 1 : 0; |
| #156 | |
| #157 | // If both agents said roughly the same thing, conversation may be done |
| #158 | if (session.turns.length >= 4) { |
| #159 | const lastTwo = session.turns.slice(-2); |
| #160 | if (lastTwo[0].content === lastTwo[1].content) { |
| #161 | break; |
| #162 | } |
| #163 | } |
| #164 | } |
| #165 | |
| #166 | session.completedAt = new Date().toISOString(); |
| #167 | return session; |
| #168 | } |
| #169 | |
| #170 | /** |
| #171 | * Summarize a backroom session into a text digest. |
| #172 | */ |
| #173 | export function summarizeBackroomSession(session: BackroomSession): string { |
| #174 | const lines: string[] = [ |
| #175 | `=== Backroom Session: "${session.topic}" ===`, |
| #176 | `Turns: ${session.turns.length}`, |
| #177 | `Duration: ${new Date(session.completedAt || "").getTime() - new Date(session.createdAt).getTime()}ms`, |
| #178 | "", |
| #179 | ]; |
| #180 | |
| #181 | for (const turn of session.turns) { |
| #182 | lines.push(`[${turn.agentName}]:`); |
| #183 | lines.push(turn.content); |
| #184 | if (turn.reasoning) { |
| #185 | lines.push(` (reasoning: ${turn.reasoning.slice(0, 200)}...)`); |
| #186 | } |
| #187 | lines.push(""); |
| #188 | } |
| #189 | |
| #190 | lines.push("=== End of Session ==="); |
| #191 | return lines.join("\n"); |
| #192 | } |
| #193 |