/** * design/140 §6 1c — BUILT-IN named workflows offered by the `Workflow` tool's `{name}` calling surface, * mirroring the built-in agents precedent (src/agents/builtin-agents.ts: GA default-on, opt out via a * deployment config flag, same-name deployment registration SHADOWS the built-in): * - `RunWorkflowToolDeps.builtinWorkflows: false` (threaded from `RunnerDeps.builtinWorkflows`) removes * them wholesale; * - a deployment `WorkflowScriptStore.resolveName` hit for the SAME NAME wins (the built-in is consulted * only when the deployment registry does not resolve the name). * * The first built-in is `team-discussion` — the round-based collab profile design/140 §1 verified live * (docs/DESIGN-140-VERIFICATION-2026-07-11.md B 面: 2 members × 2 rounds + finalizer, 8.2s/10.5K tokens, * round 2 genuinely responding to round 1). It is pure SCRIPT CONTENT over the existing primitives — zero * new runtime mechanism: * - args schema (ALL optional — zero-config must run): `{ topic, members?: [{ role, prompt?, model? }], * rounds?, finalizer?: { prompt?, model? } }`; a bare STRING args is accepted as the topic. * - budget: reuses the workflow `budget` hard ceiling + DETERMINISTIC in-script truncation (a rounds/member * cap and a `budget.remaining()` early-stop — never an evaluator agent; design/140 §1 "预算" row). * - `meta.whenToUse` carries the REQUIRED negative boundary (when-NOT-to-use: single factual question / * budget-sensitive runs — design/140 §4 "两投影"). */ import type { NamedWorkflowListing } from "./workflow-script-store.js"; /** The built-in round-based team-discussion workflow's registered name. */ export declare const TEAM_DISCUSSION_WORKFLOW_NAME = "team-discussion"; /** * The `team-discussion` script source (design/140 §1 table row 1, live-verified shape: for-loop rounds + * `agent()` members with transcript re-feed + a schema'd finalizer). Deterministic by construction — no * clock/randomness reads (locked by test against `workflowScriptReadsClockOrRandom`). */ export declare const TEAM_DISCUSSION_SCRIPT = "export const meta = {\n name: \"team-discussion\",\n description: \"Round-based team discussion: configurable members debate a topic across rounds (each member sees the transcript so far), then a finalizer synthesizes a structured verdict.\",\n whenToUse: \"Use for a genuinely contested question that benefits from several perspectives arguing across rounds - design trade-offs, plan or risk reviews, adversarial critique of a proposal. Do NOT use it for a single factual question, a task with one obvious answer, or a budget-sensitive run: every round costs one agent call per member, so a discussion is never cheaper than asking once. args (all optional): { topic, members?: [{ role, prompt?, model? }], rounds?, finalizer?: { prompt?, model? } }.\",\n phases: [\n { title: \"Discussion\" },\n { title: \"Synthesis\" },\n ],\n};\n// Zero-config runnable (design/140 \u00A76 1c): every arg has an opinionated fallback.\nconst raw = args;\nconst a = raw !== null && typeof raw === \"object\" && !Array.isArray(raw) ? raw : {};\nconst topic =\n typeof a.topic === \"string\" && a.topic.trim() !== \"\"\n ? a.topic\n : typeof raw === \"string\" && raw.trim() !== \"\"\n ? raw // ergonomic form: a bare string args IS the topic\n : \"No topic was provided. Discuss: what information should a caller supply to make a team discussion like this productive, and when should they NOT convene one?\";\nconst defaultMembers = [\n { role: \"advocate\", prompt: \"Make the strongest constructive case. Propose concrete options and argue their benefits with specifics.\" },\n { role: \"skeptic\", prompt: \"Stress-test every claim made so far. Surface risks, hidden costs, failure modes, and cheaper alternatives.\" },\n];\nconst rawMembers = Array.isArray(a.members) && a.members.length > 0 ? a.members : defaultMembers;\nconst members = rawMembers.slice(0, 6).map((m, i) => {\n const mm = m !== null && typeof m === \"object\" ? m : {};\n const member = {\n role: typeof mm.role === \"string\" && mm.role.trim() !== \"\" ? mm.role : \"member-\" + (i + 1),\n prompt: typeof mm.prompt === \"string\" && mm.prompt.trim() !== \"\" ? mm.prompt : \"Contribute your own distinct perspective: be concrete, give reasons, and engage with what others said.\",\n };\n if (typeof mm.model === \"string\" && mm.model.trim() !== \"\") member.model = mm.model;\n // Slot-tools carrier (design/140 \u2461-3 + F4): a member may BE a registered agent type ({agent:\"reviewer\"}) \u2014\n // persona/tools/model then come from the deployment's AgentDefinition (role library), args stay thin.\n if (typeof mm.agent === \"string\" && mm.agent.trim() !== \"\") member.agent = mm.agent;\n return member;\n});\n// Deterministic budget truncation (design/140 \u00A71 \u9884\u7B97 row): a HARD rounds ceiling + member cap \u2014 never an\n// evaluator agent. The engine's budget/maxAgents hard stops remain the backstop.\nconst requestedRounds = Math.floor(Number(a.rounds));\nconst rounds = Math.min(Number.isFinite(requestedRounds) && requestedRounds >= 1 ? requestedRounds : 2, 5);\nconst fin = a.finalizer !== null && typeof a.finalizer === \"object\" && !Array.isArray(a.finalizer) ? a.finalizer : {};\nconst finalizerPrompt = typeof fin.prompt === \"string\" && fin.prompt.trim() !== \"\"\n ? fin.prompt\n : \"You are the synthesis lead. Read the full discussion transcript and produce the final verdict: the decision/answer, the key supporting points, and the strongest unresolved dissent (if any). Do not introduce new arguments of your own.\";\nconst clip = (s) => { const t = String(s); return t.length > 4000 ? t.slice(0, 4000) + \" ...[truncated]\" : t; };\nconst isBudgetStop = (e) => e !== null && typeof e === \"object\" && e.code === \"workflow.budget_exceeded\";\n\nphase(\"Discussion\");\nconst transcript = [];\nlet truncated = null;\nfor (let r = 1; r <= rounds && truncated === null; r++) {\n // Deterministic early stop on an exhausted budget (a live read of the engine budget; the engine's\n // hard WorkflowBudgetExceededError remains the backstop if a member call itself crosses the line).\n if (budget.total !== null && budget.remaining() <= 0) { truncated = \"budget exhausted before round \" + r; break; }\n for (const m of members) {\n const history = transcript.length === 0 ? \"(none yet - you open the discussion)\" : transcript.join(\"\\n\\n\");\n const spec = {\n objective:\n \"Team discussion on: \" + topic + \"\\n\\n\" +\n 'You are \"' + m.role + '\" in round ' + r + \" of \" + rounds + \".\\n\" +\n \"Your brief: \" + m.prompt + \"\\n\\n\" +\n \"Transcript so far:\\n\" + history + \"\\n\\n\" +\n \"Respond to the strongest points others made (do not repeat yourself), then advance your own position. Be concise: a few tight paragraphs at most.\",\n };\n if (m.model !== undefined) spec.modelName = m.model;\n let res;\n try {\n res = await agent(spec, m.agent !== undefined ? { label: m.role + \"-r\" + r, phase: \"Discussion\", agentType: m.agent } : { label: m.role + \"-r\" + r, phase: \"Discussion\" });\n } catch (e) {\n // The engine's budget hard stop: keep what the discussion already produced instead of failing the run.\n if (isBudgetStop(e)) { truncated = \"budget exhausted at \" + m.role + \", round \" + r; break; }\n throw e;\n }\n const text = res && res.status === \"completed\" ? clip(res.result) : \"(no contribution - agent ended \" + (res ? res.status : \"unknown\") + \")\";\n transcript.push(m.role + \" (round \" + r + \"): \" + text);\n }\n}\n\nphase(\"Synthesis\");\nconst finalSpec = {\n objective:\n finalizerPrompt + \"\\n\\nTopic: \" + topic + \"\\n\\nFull transcript:\\n\" +\n (transcript.length === 0 ? \"(the discussion produced no contributions)\" : transcript.join(\"\\n\\n\")) +\n (truncated ? \"\\n\\nNote: the discussion was cut short (\" + truncated + \").\" : \"\"),\n};\nif (typeof fin.model === \"string\" && fin.model.trim() !== \"\") finalSpec.modelName = fin.model;\nlet verdict = null;\ntry {\n verdict = await agent(finalSpec, {\n label: \"finalizer\",\n phase: \"Synthesis\",\n schema: {\n type: \"object\",\n properties: {\n decision: { type: \"string\", description: \"The final answer/decision, one paragraph.\" },\n keyPoints: { type: \"array\", items: { type: \"string\" }, description: \"The strongest supporting points from the discussion.\" },\n dissent: { type: \"string\", description: \"The strongest unresolved counter-position, if any.\" },\n },\n required: [\"decision\", \"keyPoints\"],\n },\n });\n} catch (e) {\n // Budget died before synthesis: return the transcript honestly rather than failing the whole run.\n if (!isBudgetStop(e)) throw e;\n truncated = truncated === null ? \"budget exhausted before synthesis\" : truncated;\n}\n\nreturn {\n topic,\n rounds,\n members: members.map((m) => m.role),\n ...(truncated ? { truncated } : {}),\n transcript,\n verdict: verdict && verdict.structuredOutput !== undefined ? verdict.structuredOutput : (verdict ? verdict.result : null),\n};\n"; /** One built-in named workflow: the registered name + its self-contained script source. The name is the * routing key of the `{name}` calling surface; the script's `meta.name` matches it (locked by test). */ export interface BuiltinWorkflowDefinition { name: string; script: string; } /** The built-in named-workflow registry (CC `HCe`-analog shape, workflows arm). Order = card listing order. */ export declare function builtinWorkflowDefinitions(): BuiltinWorkflowDefinition[]; /** Resolve a built-in workflow by name (the `{name}` surface's SECOND lookup — a deployment * `scriptStore.resolveName` hit for the same name shadows this, design/140 §6 1c). */ export declare function resolveBuiltinWorkflow(name: string): BuiltinWorkflowDefinition | undefined; /** design/140 §6 1b — the built-ins' listing projection rows (name + description + whenToUse, parsed from * each script's static meta). Consumed by the Workflow tool card renderer. */ export declare function builtinWorkflowListings(): NamedWorkflowListing[]; //# sourceMappingURL=builtin-workflows.d.ts.map