@wrongstack/core 0.277.2 → 0.280.1

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.
Files changed (83) hide show
  1. package/dist/{agent-bridge-BFJ2ODzI.d.ts → agent-bridge-DXC6QDJ4.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-BimKihiC.d.ts → agent-subagent-runner-PoqNKiR4.d.ts} +563 -471
  3. package/dist/{compactor-D3BGw26y.d.ts → compactor-U3agvUIG.d.ts} +1 -1
  4. package/dist/{config-DAOjriz9.d.ts → config-Cr3312zc.d.ts} +102 -4
  5. package/dist/coordination/index.d.ts +1087 -998
  6. package/dist/coordination/index.js +12235 -12052
  7. package/dist/coordination/index.js.map +1 -1
  8. package/dist/defaults/index.d.ts +31 -30
  9. package/dist/defaults/index.js +403 -189
  10. package/dist/defaults/index.js.map +1 -1
  11. package/dist/{brain-CCfuEOdp.d.ts → events-Bs2fmldo.d.ts} +117 -112
  12. package/dist/execution/index.d.ts +27 -19
  13. package/dist/execution/index.js +216 -63
  14. package/dist/execution/index.js.map +1 -1
  15. package/dist/execution/prompt-enhancer.d.ts +1 -1
  16. package/dist/execution/prompt-enhancer.js.map +1 -1
  17. package/dist/extension/index.d.ts +8 -7
  18. package/dist/{global-mailbox-Dr4cTKqL.d.ts → global-mailbox-Ct7IorLJ.d.ts} +84 -6
  19. package/dist/{goal-store-C1uH4srH.d.ts → goal-store-C4F6DjC0.d.ts} +1 -1
  20. package/dist/hq/index.d.ts +504 -7
  21. package/dist/hq/index.js +1069 -20
  22. package/dist/hq/index.js.map +1 -1
  23. package/dist/{index-DJXj-dcr.d.ts → index-kidebiDh.d.ts} +8 -5
  24. package/dist/{index-cMEmzCVN.d.ts → index-nP09-oP2.d.ts} +2 -2
  25. package/dist/index.d.ts +153 -76
  26. package/dist/index.js +5791 -3163
  27. package/dist/index.js.map +1 -1
  28. package/dist/infrastructure/index.d.ts +7 -6
  29. package/dist/kernel/index.d.ts +14 -13
  30. package/dist/kernel/index.js +31 -15
  31. package/dist/kernel/index.js.map +1 -1
  32. package/dist/{mailbox-types-DTl7bRH3.d.ts → mailbox-types-BGZWrYTJ.d.ts} +38 -0
  33. package/dist/{mcp-servers-CFb60-pH.d.ts → mcp-servers-D910X5_r.d.ts} +3 -3
  34. package/dist/models/index.d.ts +5 -5
  35. package/dist/models/index.js.map +1 -1
  36. package/dist/{models-registry-5Ufn7f2m.d.ts → models-registry-CLkoOcHk.d.ts} +1 -1
  37. package/dist/{multi-agent-coordinator-CcrcncvG.d.ts → multi-agent-coordinator-CieyUoEL.d.ts} +1 -1
  38. package/dist/{null-fleet-bus-C9KsYyrI.d.ts → null-fleet-bus-DkdmZJ_W.d.ts} +464 -464
  39. package/dist/observability/index.d.ts +3 -2
  40. package/dist/{path-resolver-CEeX9I7O.d.ts → path-resolver-XfZ9eLxG.d.ts} +3 -3
  41. package/dist/{permission-DbsGOA1C.d.ts → permission-Dx6dIqS2.d.ts} +2 -7
  42. package/dist/{permission-policy-BpEea3r7.d.ts → permission-policy-C8vJcnX5.d.ts} +2 -2
  43. package/dist/{pipeline-CEjBjzVA.d.ts → pipeline-BwAP21_4.d.ts} +9 -4
  44. package/dist/{provider-model-resolve-BpfXp3Jj.d.ts → provider-model-resolve-CwQNZWt_.d.ts} +3 -3
  45. package/dist/{provider-runner-CnOSr5BN.d.ts → provider-runner-CYHFImzV.d.ts} +3 -3
  46. package/dist/{retry-policy-Git9WF6d.d.ts → retry-policy-D4feSLk3.d.ts} +1 -1
  47. package/dist/sdd/index.d.ts +11 -10
  48. package/dist/sdd/index.js +2 -2
  49. package/dist/sdd/index.js.map +1 -1
  50. package/dist/secret-scrubber-3MHDDAtm.d.ts +6 -0
  51. package/dist/{secret-vault-DDSMHqIm.d.ts → secret-vault-CImt2XrR.d.ts} +1 -1
  52. package/dist/security/index.d.ts +6 -5
  53. package/dist/security/index.js.map +1 -1
  54. package/dist/{selector-Cq72C0Oy.d.ts → selector-Dy-MzKp1.d.ts} +1 -1
  55. package/dist/{session-event-bridge-DG94B3Bk.d.ts → session-event-bridge-CqdiGnfU.d.ts} +1 -1
  56. package/dist/{session-reader-BzT-iMQT.d.ts → session-reader-Hk0WbNm9.d.ts} +1 -1
  57. package/dist/{skill-DGIXCtdv.d.ts → skill-DHniprNl.d.ts} +15 -1
  58. package/dist/skills/index.d.ts +472 -26
  59. package/dist/skills/index.js +872 -129
  60. package/dist/skills/index.js.map +1 -1
  61. package/dist/storage/index.d.ts +27 -14
  62. package/dist/storage/index.js +264 -85
  63. package/dist/storage/index.js.map +1 -1
  64. package/dist/{strategy-compactor-Bt_ZH6R0.d.ts → strategy-compactor-CQwhbErd.d.ts} +32 -17
  65. package/dist/{todos-checkpoint-CH1pcua9.d.ts → todos-checkpoint-Bk2uP7Ex.d.ts} +6 -6
  66. package/dist/{context-DPlA6kid.d.ts → tool-BkOgs_KL.d.ts} +306 -286
  67. package/dist/{tool-executor-SVFq7IOR.d.ts → tool-executor-SiE1wlZo.d.ts} +9 -9
  68. package/dist/tools/index.d.ts +2 -2
  69. package/dist/tools/index.js.map +1 -1
  70. package/dist/types/index.d.ts +22 -21
  71. package/dist/types/index.js +7 -9
  72. package/dist/types/index.js.map +1 -1
  73. package/dist/utils/index.d.ts +30 -4
  74. package/dist/utils/index.js +50 -1
  75. package/dist/utils/index.js.map +1 -1
  76. package/dist/{worktree-manager-C4YIf1Fa.d.ts → worktree-manager-BjOFF6bt.d.ts} +1 -1
  77. package/dist/{wstack-paths-_NrRovdr.d.ts → wstack-paths-CMl_cYgq.d.ts} +8 -0
  78. package/package.json +1 -1
  79. package/skills/mailbox-bridge/SKILL.md +1 -0
  80. package/skills/plugin-author/SKILL.md +350 -0
  81. package/skills/sdd/SKILL.md +134 -134
  82. package/skills/skill-creator/SKILL.md +45 -7
  83. package/skills/wrongstack-mailbox/SKILL.md +40 -21
@@ -1,4 +1,4 @@
1
- import { P as Provider, R as ReasoningRequest, a as ReasoningConfig, M as Message } from '../context-DPlA6kid.js';
1
+ import { P as Provider, R as ReasoningRequest, a as ReasoningConfig, M as Message } from '../tool-BkOgs_KL.js';
2
2
 
3
3
  /**
4
4
  * Prompt refinement ("did you mean this?").
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/blocks.ts","../../src/utils/error.ts","../../src/utils/instruction-file.ts","../../src/execution/prompt-enhancer.ts"],"names":[],"mappings":"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","file":"prompt-enhancer.js","sourcesContent":["export interface TextBlock {\n type: 'text';\n text: string;\n cache_control?: { type: 'ephemeral' | undefined };\n}\n\nexport interface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n /**\n * Provider-specific opaque metadata captured from the wire response.\n * Echoed back verbatim in the next request so providers that bind\n * extra state to function calls keep working. Example: Gemini's\n * `thoughtSignature` — required for tool-use turns with thinking\n * models, otherwise the next request fails with 400 \"Function call\n * is missing a thought_signature in functionCall parts\".\n *\n * Keys are namespaced by intent so multiple wires can coexist:\n * - `google.thoughtSignature` — Gemini signed-thought blob\n * Other providers can add their own keys without colliding.\n */\n providerMeta?: Record<string, unknown>;\n}\n\nexport interface ToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n /**\n * The original tool name. Useful for providers like Google Gemini that\n * need the tool name in `functionResponse.name` — the tool_use_id is\n * only a session-local identifier and is not stable across replays.\n * Always set by ToolExecutor; may be absent on manually-constructed blocks.\n */\n name?: string | undefined;\n content: string;\n is_error?: boolean | undefined;\n}\n\nexport interface ImageBlock {\n type: 'image';\n source: {\n type: 'base64' | 'url';\n media_type?: string | undefined;\n data?: string | undefined;\n url?: string | undefined;\n };\n}\n\n/**\n * Chain-of-thought / extended-thinking content emitted by the model.\n *\n * Both Anthropic extended thinking (`{type:'thinking', thinking, signature}`)\n * and DeepSeek reasoning mode (top-level `reasoning_content` on the assistant\n * message) require this content to be echoed back verbatim on the next\n * request, otherwise the provider returns 400:\n * - Anthropic: \"The `content[].thinking` in the thinking mode must be passed back\"\n * - DeepSeek: \"The `reasoning_content` in the thinking mode must be passed back\"\n *\n * `signature` is Anthropic-specific (an opaque integrity blob). DeepSeek\n * doesn't issue a signature — the field is absent for that provider.\n *\n * Per Anthropic, thinking blocks MUST appear before any text/tool_use blocks\n * in an assistant message. Stream builders preserve that order.\n */\nexport interface ThinkingBlock {\n type: 'thinking';\n thinking: string;\n signature?: string | undefined;\n providerMeta?: Record<string, unknown>;\n}\n\nexport type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ImageBlock | ThinkingBlock;\n\nexport function isTextBlock(b: ContentBlock): b is TextBlock {\n return b.type === 'text';\n}\nexport function isToolUseBlock(b: ContentBlock): b is ToolUseBlock {\n return b.type === 'tool_use';\n}\nexport function isToolResultBlock(b: ContentBlock): b is ToolResultBlock {\n return b.type === 'tool_result';\n}\nexport function isImageBlock(b: ContentBlock): b is ImageBlock {\n return b.type === 'image';\n}\nexport function isThinkingBlock(b: ContentBlock): b is ThinkingBlock {\n return b.type === 'thinking';\n}\n","/**\n * Converts an unknown error value to a human-readable string.\n * Used in 40+ files across the codebase to normalize error messaging.\n */\nexport function toErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","import { readFileSync, statSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport function readBundledInstructionText(relativePath: string): string {\n for (const root of instructionRootCandidates()) {\n try {\n return readFileSync(path.join(root, relativePath), 'utf8').trimEnd();\n } catch {\n // try next candidate\n }\n }\n return '';\n}\n\nexport function renderInstructionTemplate(\n template: string,\n values: Record<string, string>,\n): string {\n return template.replace(/\\{\\{\\s*([a-zA-Z0-9_.-]+)\\s*\\}\\}/g, (match, key: string) =>\n Object.prototype.hasOwnProperty.call(values, key) ? values[key] ?? '' : match,\n );\n}\n\nfunction instructionRootCandidates(): string[] {\n const here = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(here, '../../instructions'),\n path.resolve(here, '../instructions'),\n path.resolve(here, 'instructions'),\n ];\n return candidates.sort((a, b) => Number(!isDirectory(a)) - Number(!isDirectory(b)));\n}\n\nfunction isDirectory(candidate: string): boolean {\n try {\n return statSync(candidate).isDirectory();\n } catch {\n return false;\n }\n}\n","import type { ContentBlock } from '../types/blocks.js';\nimport { isTextBlock } from '../types/blocks.js';\nimport type { Message } from '../types/messages.js';\nimport type {\n Provider,\n ReasoningConfig,\n ReasoningEffort,\n ReasoningRequest,\n Request,\n} from '../types/provider.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { readBundledInstructionText } from '../utils/instruction-file.js';\n\n/**\n * Prompt refinement (\"did you mean this?\").\n *\n * Runs a one-shot LLM call in a SEPARATE context (its own system prompt, no\n * conversation history, no tools) that rewrites a raw user message into a\n * clearer, more complete instruction BEFORE the main agent sees it. The goal\n * is to make the main context start from a well-understood request rather than\n * guessing intent from terse input like \"fix the bug\".\n *\n * This mirrors `IntelligentCompactor.callSummarizer` — a plain\n * `provider.complete()` with a dedicated system prompt — and is deliberately\n * free of React / TUI dependencies so it can be unit-tested in isolation.\n */\n\nexport const ENHANCER_SYSTEM_PROMPT = readBundledInstructionText('llm/prompt-enhancer.md');\n\n/** Words/phrases that are control answers, not refinable requests. */\nconst AFFIRMATION_RE =\n /^(y|n|yes|no|yep|nope|ok|okay|sure|go|go ahead|continue|proceed|stop|cancel|done|next|skip|retry|again|please do|do it)\\b[.! ]*$/i;\n\n/**\n * Heuristic gate: should this raw input be sent through the refiner at all?\n * Pure + exported for unit testing. Returns false for inputs where refinement\n * is pointless or unwanted (slash commands, one-word affirmations, trivially\n * short text, bare numbers).\n */\nexport function shouldEnhance(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n if (t.startsWith('/')) return false; // slash command\n if (t.length < 12) return false; // too short to be worth refining\n if (AFFIRMATION_RE.test(t)) return false; // \"yes\" / \"continue\" / ...\n if (/^[\\d\\s.,]+$/.test(t)) return false; // bare numbers (menu picks, etc.)\n const words = t.split(/\\s+/).filter(Boolean);\n if (words.length < 3) return false; // 1–2 words rarely benefit\n return true;\n}\n\n/**\n * Preference order when picking an effort level: the cheapest level that still\n * does SOME reasoning first ('low', then 'minimal'), then up the ladder, with\n * fully-off ('none') last so it's only chosen when it's the sole advertised\n * option. This keeps the refiner cheap without dropping reasoning entirely when\n * a little still helps. 'low' leads because it's the most widely accepted low\n * level across adapters (e.g. OpenAI's reasoning_effort set).\n */\nconst EFFORT_PREFERENCE: ReasoningEffort[] = [\n 'low',\n 'minimal',\n 'medium',\n 'high',\n 'xhigh',\n 'max',\n 'none',\n];\n\n/**\n * Build a reasoning directive for the refiner that minimizes wasted thinking,\n * gated to what the model actually accepts. Refinement is a shallow rewrite\n * task — extended thinking adds latency and (hidden) token cost for little\n * gain — so we ask the model to spend as little reasoning as it safely can.\n *\n * The gating mirrors `resolveReasoningForRequest` so we never send a field the\n * model would reject:\n * - effort-capable model → its lowest advertised effort level;\n * - else disable-capable model → disable thinking (`enabled: false`);\n * - else (always-on / unknown) → `undefined` (leave the provider default).\n *\n * Returns `undefined` whenever nothing can be safely reduced. Callers forward\n * that verbatim to `enhanceUserPrompt`, which then sends no reasoning field —\n * identical to the behavior before this hint existed. Pure + exported for unit\n * testing.\n */\nexport function gatedEnhancerReasoning(\n rc: ReasoningConfig | undefined,\n): ReasoningRequest | undefined {\n // Capabilities unknown → don't risk an unsupported field (matches the\n // conservative \"capabilities unknown\" branch in resolveReasoningForRequest).\n if (!rc) return undefined;\n if (rc.effortSupported && rc.effortLevels.length > 0) {\n const lowest = EFFORT_PREFERENCE.find((e) => rc.effortLevels.includes(e)) ?? rc.effortLevels[0];\n if (lowest) return { effort: lowest };\n }\n if (rc.disableSupported) return { enabled: false };\n return undefined;\n}\n\n/**\n * Normalize for \"did the refiner actually change anything?\" comparison —\n * collapse whitespace and lowercase so trivial reformatting doesn't trigger\n * the confirmation panel.\n */\nexport function normalizedEqual(a: string, b: string): boolean {\n const norm = (s: string) => s.trim().replace(/\\s+/g, ' ').toLowerCase();\n return norm(a) === norm(b);\n}\n\n/** A single text-only conversation turn used as refiner context. */\nexport interface ConversationTurn {\n role: 'user' | 'assistant';\n text: string;\n}\n\n/**\n * Result of a successful prompt refinement. Carries the original-language and\n * English versions so the UI can offer both. When the input was already in\n * English the refiner emits a single version and both fields hold the same\n * text (the UI then offers two identical choices, which is correct).\n */\nexport interface EnhanceResult {\n /** Refined in the user's original language. */\n refined: string;\n /** Refined in English. Equals `refined` when the input was already English. */\n english: string;\n}\n\nexport interface EnhanceUserPromptOptions {\n provider: Provider;\n model: string;\n text: string;\n /**\n * Recent conversation turns (oldest→newest), text only, used purely as\n * CONTEXT so the refiner can resolve references in a follow-up message\n * (\"it\", \"the same\", \"that file\"). Without this, the refiner is blind to\n * the conversation and can only refine self-contained prompts. Build with\n * `recentTextTurns(ctx.messages)`.\n */\n history?: ConversationTurn[] | undefined;\n /** Parent abort signal (e.g. the run controller / Esc). */\n signal?: AbortSignal | undefined;\n /** Hard cap on how long to wait for the refiner before giving up. Default 90s. */\n timeoutMs?: number | undefined;\n /** Max tokens for the refined output. Default 2048. */\n maxTokens?: number | undefined;\n /**\n * Reasoning directive for the refiner call. Refinement is a shallow\n * restate-this-more-clearly task that does not benefit from extended\n * thinking, so callers pass a low-effort / thinking-disabled hint here to\n * cut latency and (hidden) reasoning-token cost — most impactful on slow\n * reasoning models. Build it with `gatedEnhancerReasoning(rc)` so the field\n * is gated to what the model accepts. Omit (undefined) to send no reasoning\n * directive at all (the provider's own default applies).\n */\n reasoning?: ReasoningRequest | undefined;\n /**\n * Called with a short reason when refinement fails (provider error, timeout,\n * empty response). NOT called when the caller cancels via `signal`. Lets the\n * UI surface *why* a refine fell through instead of a generic message.\n */\n onError?: ((reason: string) => void) | undefined;\n}\n\n/**\n * Compose the single user message sent to the refiner: the recent\n * conversation embedded as plain text (so we never trip provider\n * role-alternation rules) followed by the latest message to refine.\n */\nfunction buildRefinerInput(text: string, history?: ConversationTurn[]): string {\n if (!history || history.length === 0) return text;\n const lines = history.map((t) => `${t.role === 'user' ? 'User' : 'Assistant'}: ${t.text}`);\n return [\n 'Recent conversation (context only — do not act on it):',\n ...lines,\n '',\n 'Latest message to refine:',\n text,\n ].join('\\n');\n}\n\n/**\n * Refine a raw user prompt. Returns the refined text, or `null` when the\n * caller should fall back to the original (refiner errored, timed out, was\n * aborted, or returned nothing useful). NEVER throws — refinement is a\n * best-effort convenience and must never block the user from sending.\n */\nexport async function enhanceUserPrompt(\n opts: EnhanceUserPromptOptions,\n): Promise<EnhanceResult | null> {\n const { provider, model, text } = opts;\n // Reasoning models (\"thinking\" models like DeepSeek reasoner / o1) take\n // longer to first token, so give a generous default window.\n const timeoutMs = opts.timeoutMs ?? 90000;\n // Generous default: on some endpoints the model's hidden \"thinking\" tokens\n // count against this budget, so a small cap can leave NO room for the actual\n // refined text (→ empty completion → null). 2048 keeps the output room ample.\n const maxTokens = opts.maxTokens ?? 2048;\n\n const req: Request = {\n model,\n system: [{ type: 'text', text: ENHANCER_SYSTEM_PROMPT }],\n messages: [{ role: 'user', content: buildRefinerInput(text, opts.history) }],\n maxTokens,\n // NOTE: deliberately NO `temperature`. The main agent loop never sets it,\n // and reasoning models (DeepSeek reasoner, o1/o3, …) return HTTP 400 when\n // `temperature` is present — which would make every refine call fail and\n // silently fall back to the original (no panel shown).\n //\n // A reasoning hint is forwarded ONLY when the caller supplies one (it must\n // already be gated to the model's advertised support — see\n // `gatedEnhancerReasoning`). Absent it, no reasoning field is sent, which\n // is identical to the original behavior.\n ...(opts.reasoning ? { reasoning: opts.reasoning } : {}),\n };\n\n // Link a local timeout to the parent signal so a stuck provider call can't\n // hang the submit path. AbortSignal.any keeps both cancellation sources.\n const timer = new AbortController();\n const to = setTimeout(() => timer.abort(new Error('enhancer timeout')), timeoutMs);\n const signal = opts.signal ? AbortSignal.any([opts.signal, timer.signal]) : timer.signal;\n\n try {\n const res = await provider.complete(req, { signal });\n const raw = res.content\n .filter(isTextBlock)\n .map((b) => b.text)\n .join('\\n')\n .trim();\n if (!raw) {\n opts.onError?.('model returned no text');\n return null;\n }\n\n // English input → ONE version (no \"---\"); other languages → two versions\n // separated by a line with only \"---\". Split on the first occurrence so the\n // delimiter can still appear inside the second version's text.\n const sepIdx = raw.indexOf('\\n---\\n');\n if (sepIdx === -1) {\n // Single version: the input was already English (or the model chose not\n // to translate). Use it for both fields — the UI offers identical\n // \"refined\" / \"english\" options, which is correct and saves the model\n // from generating a redundant second copy. NOT an error.\n return { refined: raw, english: raw };\n }\n const refined = raw.slice(0, sepIdx).trim();\n const english = raw.slice(sepIdx + 5).trim(); // skip \"\\n---\\n\"\n if (!refined || !english) {\n opts.onError?.('one or both versions empty');\n return null;\n }\n return { refined, english };\n } catch (err) {\n // User-initiated cancel → stay silent (they chose to send the original).\n if (opts.signal?.aborted) return null;\n if (timer.signal.aborted) {\n opts.onError?.(`timed out after ${Math.round(timeoutMs / 1000)}s`);\n return null;\n }\n opts.onError?.(toErrorMessage(err));\n return null;\n } finally {\n // Idempotent — abort() after signal already fired is a no-op, so this is\n // always safe regardless of whether the timeout fired first.\n timer.abort();\n clearTimeout(to);\n }\n}\n\n/** Pull the visible text out of a message's content (ignores tool blocks). */\nfunction messageText(content: string | ContentBlock[]): string {\n if (typeof content === 'string') return content;\n return content\n .filter(isTextBlock)\n .map((b) => b.text)\n .join('\\n')\n .trim();\n}\n\n/**\n * Extract the last few user/assistant TEXT turns from a conversation, newest\n * last, for use as refiner context. Skips system messages and tool-only turns\n * (tool_use / tool_result carry no useful natural-language context and bloat\n * the call). Each turn is truncated to `maxChars`; at most `maxTurns` are\n * returned. Pure + exported for unit testing.\n */\nexport function recentTextTurns(\n messages: Message[],\n maxTurns = 6,\n maxChars = 1500,\n): ConversationTurn[] {\n const turns: ConversationTurn[] = [];\n for (let i = messages.length - 1; i >= 0 && turns.length < maxTurns; i--) {\n const m = messages[i];\n if (!m || (m.role !== 'user' && m.role !== 'assistant')) continue;\n const text = messageText(m.content);\n if (!text) continue;\n turns.unshift({\n role: m.role,\n text: text.length > maxChars ? `${text.slice(0, maxChars - 1)}…` : text,\n });\n }\n return turns;\n}\n"]}
1
+ {"version":3,"sources":["../../src/types/blocks.ts","../../src/utils/error.ts","../../src/utils/instruction-file.ts","../../src/execution/prompt-enhancer.ts"],"names":[],"mappings":"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","file":"prompt-enhancer.js","sourcesContent":["export interface TextBlock {\n type: 'text';\n text: string;\n cache_control?: { type: 'ephemeral' | undefined };\n}\n\nexport interface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n /**\n * Provider-specific opaque metadata captured from the wire response.\n * Echoed back verbatim in the next request so providers that bind\n * extra state to function calls keep working. Example: Gemini's\n * `thoughtSignature` — required for tool-use turns with thinking\n * models, otherwise the next request fails with 400 \"Function call\n * is missing a thought_signature in functionCall parts\".\n *\n * Keys are namespaced by intent so multiple wires can coexist:\n * - `google.thoughtSignature` — Gemini signed-thought blob\n * Other providers can add their own keys without colliding.\n */\n providerMeta?: Record<string, unknown>;\n}\n\nexport interface ToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n /**\n * The original tool name. Useful for providers like Google Gemini that\n * need the tool name in `functionResponse.name` — the tool_use_id is\n * only a session-local identifier and is not stable across replays.\n * Always set by ToolExecutor; may be absent on manually-constructed blocks.\n */\n name?: string | undefined;\n content: string;\n is_error?: boolean | undefined;\n}\n\nexport interface ImageBlock {\n type: 'image';\n source: {\n type: 'base64' | 'url';\n media_type?: string | undefined;\n data?: string | undefined;\n url?: string | undefined;\n };\n}\n\n/**\n * Chain-of-thought / extended-thinking content emitted by the model.\n *\n * Both Anthropic extended thinking (`{type:'thinking', thinking, signature}`)\n * and DeepSeek reasoning mode (top-level `reasoning_content` on the assistant\n * message) require this content to be echoed back verbatim on the next\n * request, otherwise the provider returns 400:\n * - Anthropic: \"The `content[].thinking` in the thinking mode must be passed back\"\n * - DeepSeek: \"The `reasoning_content` in the thinking mode must be passed back\"\n *\n * `signature` is Anthropic-specific (an opaque integrity blob). DeepSeek\n * doesn't issue a signature — the field is absent for that provider.\n *\n * Per Anthropic, thinking blocks MUST appear before any text/tool_use blocks\n * in an assistant message. Stream builders preserve that order.\n */\nexport interface ThinkingBlock {\n type: 'thinking';\n thinking: string;\n signature?: string | undefined;\n providerMeta?: Record<string, unknown>;\n}\n\nexport type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ImageBlock | ThinkingBlock;\n\nexport function isTextBlock(b: ContentBlock): b is TextBlock {\n return b.type === 'text';\n}\nexport function isToolUseBlock(b: ContentBlock): b is ToolUseBlock {\n return b.type === 'tool_use';\n}\nexport function isToolResultBlock(b: ContentBlock): b is ToolResultBlock {\n return b.type === 'tool_result';\n}\nexport function isImageBlock(b: ContentBlock): b is ImageBlock {\n return b.type === 'image';\n}\nexport function isThinkingBlock(b: ContentBlock): b is ThinkingBlock {\n return b.type === 'thinking';\n}\n","/**\n * Converts an unknown error value to a human-readable string.\n * Used in 40+ files across the codebase to normalize error messaging.\n */\nexport function toErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","import { readFileSync, statSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport function readBundledInstructionText(relativePath: string): string {\n for (const root of instructionRootCandidates()) {\n try {\n return readFileSync(path.join(root, relativePath), 'utf8').trimEnd();\n } catch {\n // try next candidate\n }\n }\n return '';\n}\n\nexport function renderInstructionTemplate(\n template: string,\n values: Record<string, string>,\n): string {\n return template.replace(/\\{\\{\\s*([a-zA-Z0-9_.-]+)\\s*\\}\\}/g, (match, key: string) =>\n Object.hasOwn(values, key) ? values[key] ?? '' : match,\n );\n}\n\nfunction instructionRootCandidates(): string[] {\n const here = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(here, '../../instructions'),\n path.resolve(here, '../instructions'),\n path.resolve(here, 'instructions'),\n ];\n return candidates.sort((a, b) => Number(!isDirectory(a)) - Number(!isDirectory(b)));\n}\n\nfunction isDirectory(candidate: string): boolean {\n try {\n return statSync(candidate).isDirectory();\n } catch {\n return false;\n }\n}\n","import type { ContentBlock } from '../types/blocks.js';\nimport { isTextBlock } from '../types/blocks.js';\nimport type { Message } from '../types/messages.js';\nimport type {\n Provider,\n ReasoningConfig,\n ReasoningEffort,\n ReasoningRequest,\n Request,\n} from '../types/provider.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { readBundledInstructionText } from '../utils/instruction-file.js';\n\n/**\n * Prompt refinement (\"did you mean this?\").\n *\n * Runs a one-shot LLM call in a SEPARATE context (its own system prompt, no\n * conversation history, no tools) that rewrites a raw user message into a\n * clearer, more complete instruction BEFORE the main agent sees it. The goal\n * is to make the main context start from a well-understood request rather than\n * guessing intent from terse input like \"fix the bug\".\n *\n * This mirrors `IntelligentCompactor.callSummarizer` — a plain\n * `provider.complete()` with a dedicated system prompt — and is deliberately\n * free of React / TUI dependencies so it can be unit-tested in isolation.\n */\n\nexport const ENHANCER_SYSTEM_PROMPT = readBundledInstructionText('llm/prompt-enhancer.md');\n\n/** Words/phrases that are control answers, not refinable requests. */\nconst AFFIRMATION_RE =\n /^(y|n|yes|no|yep|nope|ok|okay|sure|go|go ahead|continue|proceed|stop|cancel|done|next|skip|retry|again|please do|do it)\\b[.! ]*$/i;\n\n/**\n * Heuristic gate: should this raw input be sent through the refiner at all?\n * Pure + exported for unit testing. Returns false for inputs where refinement\n * is pointless or unwanted (slash commands, one-word affirmations, trivially\n * short text, bare numbers).\n */\nexport function shouldEnhance(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n if (t.startsWith('/')) return false; // slash command\n if (t.length < 12) return false; // too short to be worth refining\n if (AFFIRMATION_RE.test(t)) return false; // \"yes\" / \"continue\" / ...\n if (/^[\\d\\s.,]+$/.test(t)) return false; // bare numbers (menu picks, etc.)\n const words = t.split(/\\s+/).filter(Boolean);\n if (words.length < 3) return false; // 1–2 words rarely benefit\n return true;\n}\n\n/**\n * Preference order when picking an effort level: the cheapest level that still\n * does SOME reasoning first ('low', then 'minimal'), then up the ladder, with\n * fully-off ('none') last so it's only chosen when it's the sole advertised\n * option. This keeps the refiner cheap without dropping reasoning entirely when\n * a little still helps. 'low' leads because it's the most widely accepted low\n * level across adapters (e.g. OpenAI's reasoning_effort set).\n */\nconst EFFORT_PREFERENCE: ReasoningEffort[] = [\n 'low',\n 'minimal',\n 'medium',\n 'high',\n 'xhigh',\n 'max',\n 'none',\n];\n\n/**\n * Build a reasoning directive for the refiner that minimizes wasted thinking,\n * gated to what the model actually accepts. Refinement is a shallow rewrite\n * task — extended thinking adds latency and (hidden) token cost for little\n * gain — so we ask the model to spend as little reasoning as it safely can.\n *\n * The gating mirrors `resolveReasoningForRequest` so we never send a field the\n * model would reject:\n * - effort-capable model → its lowest advertised effort level;\n * - else disable-capable model → disable thinking (`enabled: false`);\n * - else (always-on / unknown) → `undefined` (leave the provider default).\n *\n * Returns `undefined` whenever nothing can be safely reduced. Callers forward\n * that verbatim to `enhanceUserPrompt`, which then sends no reasoning field —\n * identical to the behavior before this hint existed. Pure + exported for unit\n * testing.\n */\nexport function gatedEnhancerReasoning(\n rc: ReasoningConfig | undefined,\n): ReasoningRequest | undefined {\n // Capabilities unknown → don't risk an unsupported field (matches the\n // conservative \"capabilities unknown\" branch in resolveReasoningForRequest).\n if (!rc) return undefined;\n if (rc.effortSupported && rc.effortLevels.length > 0) {\n const lowest = EFFORT_PREFERENCE.find((e) => rc.effortLevels.includes(e)) ?? rc.effortLevels[0];\n if (lowest) return { effort: lowest };\n }\n if (rc.disableSupported) return { enabled: false };\n return undefined;\n}\n\n/**\n * Normalize for \"did the refiner actually change anything?\" comparison —\n * collapse whitespace and lowercase so trivial reformatting doesn't trigger\n * the confirmation panel.\n */\nexport function normalizedEqual(a: string, b: string): boolean {\n const norm = (s: string) => s.trim().replace(/\\s+/g, ' ').toLowerCase();\n return norm(a) === norm(b);\n}\n\n/** A single text-only conversation turn used as refiner context. */\nexport interface ConversationTurn {\n role: 'user' | 'assistant';\n text: string;\n}\n\n/**\n * Result of a successful prompt refinement. Carries the original-language and\n * English versions so the UI can offer both. When the input was already in\n * English the refiner emits a single version and both fields hold the same\n * text (the UI then offers two identical choices, which is correct).\n */\nexport interface EnhanceResult {\n /** Refined in the user's original language. */\n refined: string;\n /** Refined in English. Equals `refined` when the input was already English. */\n english: string;\n}\n\nexport interface EnhanceUserPromptOptions {\n provider: Provider;\n model: string;\n text: string;\n /**\n * Recent conversation turns (oldest→newest), text only, used purely as\n * CONTEXT so the refiner can resolve references in a follow-up message\n * (\"it\", \"the same\", \"that file\"). Without this, the refiner is blind to\n * the conversation and can only refine self-contained prompts. Build with\n * `recentTextTurns(ctx.messages)`.\n */\n history?: ConversationTurn[] | undefined;\n /** Parent abort signal (e.g. the run controller / Esc). */\n signal?: AbortSignal | undefined;\n /** Hard cap on how long to wait for the refiner before giving up. Default 90s. */\n timeoutMs?: number | undefined;\n /** Max tokens for the refined output. Default 2048. */\n maxTokens?: number | undefined;\n /**\n * Reasoning directive for the refiner call. Refinement is a shallow\n * restate-this-more-clearly task that does not benefit from extended\n * thinking, so callers pass a low-effort / thinking-disabled hint here to\n * cut latency and (hidden) reasoning-token cost — most impactful on slow\n * reasoning models. Build it with `gatedEnhancerReasoning(rc)` so the field\n * is gated to what the model accepts. Omit (undefined) to send no reasoning\n * directive at all (the provider's own default applies).\n */\n reasoning?: ReasoningRequest | undefined;\n /**\n * Called with a short reason when refinement fails (provider error, timeout,\n * empty response). NOT called when the caller cancels via `signal`. Lets the\n * UI surface *why* a refine fell through instead of a generic message.\n */\n onError?: ((reason: string) => void) | undefined;\n}\n\n/**\n * Compose the single user message sent to the refiner: the recent\n * conversation embedded as plain text (so we never trip provider\n * role-alternation rules) followed by the latest message to refine.\n */\nfunction buildRefinerInput(text: string, history?: ConversationTurn[]): string {\n if (!history || history.length === 0) return text;\n const lines = history.map((t) => `${t.role === 'user' ? 'User' : 'Assistant'}: ${t.text}`);\n return [\n 'Recent conversation (context only — do not act on it):',\n ...lines,\n '',\n 'Latest message to refine:',\n text,\n ].join('\\n');\n}\n\n/**\n * Refine a raw user prompt. Returns the refined text, or `null` when the\n * caller should fall back to the original (refiner errored, timed out, was\n * aborted, or returned nothing useful). NEVER throws — refinement is a\n * best-effort convenience and must never block the user from sending.\n */\nexport async function enhanceUserPrompt(\n opts: EnhanceUserPromptOptions,\n): Promise<EnhanceResult | null> {\n const { provider, model, text } = opts;\n // Reasoning models (\"thinking\" models like DeepSeek reasoner / o1) take\n // longer to first token, so give a generous default window.\n const timeoutMs = opts.timeoutMs ?? 90000;\n // Generous default: on some endpoints the model's hidden \"thinking\" tokens\n // count against this budget, so a small cap can leave NO room for the actual\n // refined text (→ empty completion → null). 2048 keeps the output room ample.\n const maxTokens = opts.maxTokens ?? 2048;\n\n const req: Request = {\n model,\n system: [{ type: 'text', text: ENHANCER_SYSTEM_PROMPT }],\n messages: [{ role: 'user', content: buildRefinerInput(text, opts.history) }],\n maxTokens,\n // NOTE: deliberately NO `temperature`. The main agent loop never sets it,\n // and reasoning models (DeepSeek reasoner, o1/o3, …) return HTTP 400 when\n // `temperature` is present — which would make every refine call fail and\n // silently fall back to the original (no panel shown).\n //\n // A reasoning hint is forwarded ONLY when the caller supplies one (it must\n // already be gated to the model's advertised support — see\n // `gatedEnhancerReasoning`). Absent it, no reasoning field is sent, which\n // is identical to the original behavior.\n ...(opts.reasoning ? { reasoning: opts.reasoning } : {}),\n };\n\n // Link a local timeout to the parent signal so a stuck provider call can't\n // hang the submit path. AbortSignal.any keeps both cancellation sources.\n const timer = new AbortController();\n const to = setTimeout(() => timer.abort(new Error('enhancer timeout')), timeoutMs);\n const signal = opts.signal ? AbortSignal.any([opts.signal, timer.signal]) : timer.signal;\n\n try {\n const res = await provider.complete(req, { signal });\n const raw = res.content\n .filter(isTextBlock)\n .map((b) => b.text)\n .join('\\n')\n .trim();\n if (!raw) {\n opts.onError?.('model returned no text');\n return null;\n }\n\n // English input → ONE version (no \"---\"); other languages → two versions\n // separated by a line with only \"---\". Split on the first occurrence so the\n // delimiter can still appear inside the second version's text.\n const sepIdx = raw.indexOf('\\n---\\n');\n if (sepIdx === -1) {\n // Single version: the input was already English (or the model chose not\n // to translate). Use it for both fields — the UI offers identical\n // \"refined\" / \"english\" options, which is correct and saves the model\n // from generating a redundant second copy. NOT an error.\n return { refined: raw, english: raw };\n }\n const refined = raw.slice(0, sepIdx).trim();\n const english = raw.slice(sepIdx + 5).trim(); // skip \"\\n---\\n\"\n if (!refined || !english) {\n opts.onError?.('one or both versions empty');\n return null;\n }\n return { refined, english };\n } catch (err) {\n // User-initiated cancel → stay silent (they chose to send the original).\n if (opts.signal?.aborted) return null;\n if (timer.signal.aborted) {\n opts.onError?.(`timed out after ${Math.round(timeoutMs / 1000)}s`);\n return null;\n }\n opts.onError?.(toErrorMessage(err));\n return null;\n } finally {\n // Idempotent — abort() after signal already fired is a no-op, so this is\n // always safe regardless of whether the timeout fired first.\n timer.abort();\n clearTimeout(to);\n }\n}\n\n/** Pull the visible text out of a message's content (ignores tool blocks). */\nfunction messageText(content: string | ContentBlock[]): string {\n if (typeof content === 'string') return content;\n return content\n .filter(isTextBlock)\n .map((b) => b.text)\n .join('\\n')\n .trim();\n}\n\n/**\n * Extract the last few user/assistant TEXT turns from a conversation, newest\n * last, for use as refiner context. Skips system messages and tool-only turns\n * (tool_use / tool_result carry no useful natural-language context and bloat\n * the call). Each turn is truncated to `maxChars`; at most `maxTurns` are\n * returned. Pure + exported for unit testing.\n */\nexport function recentTextTurns(\n messages: Message[],\n maxTurns = 6,\n maxChars = 1500,\n): ConversationTurn[] {\n const turns: ConversationTurn[] = [];\n for (let i = messages.length - 1; i >= 0 && turns.length < maxTurns; i--) {\n const m = messages[i];\n if (!m || (m.role !== 'user' && m.role !== 'assistant')) continue;\n const text = messageText(m.content);\n if (!text) continue;\n turns.unshift({\n role: m.role,\n text: text.length > maxChars ? `${text.slice(0, maxChars - 1)}…` : text,\n });\n }\n return turns;\n}\n"]}
@@ -1,9 +1,10 @@
1
- export { j as AfterIterationHook, k as AfterRunHook, l as AfterToolExecutionHook, i as AgentExtension, B as BeforeIterationHook, m as BeforeRunHook, n as BeforeToolExecutionHook, E as ExtensionRegistry, O as OnErrorHook, v as ProviderRunnerFn, t as ProviderRunnerWrapper } from '../index-DJXj-dcr.js';
2
- import '../context-DPlA6kid.js';
1
+ export { j as AfterIterationHook, k as AfterRunHook, l as AfterToolExecutionHook, i as AgentExtension, B as BeforeIterationHook, m as BeforeRunHook, n as BeforeToolExecutionHook, E as ExtensionRegistry, O as OnErrorHook, v as ProviderRunnerFn, t as ProviderRunnerWrapper } from '../index-kidebiDh.js';
2
+ import '../tool-BkOgs_KL.js';
3
3
  import '../logger-B63L5bTg.js';
4
- import '../pipeline-CEjBjzVA.js';
5
- import '../mailbox-types-DTl7bRH3.js';
6
- import '../config-DAOjriz9.js';
4
+ import '../pipeline-BwAP21_4.js';
5
+ import '../mailbox-types-BGZWrYTJ.js';
6
+ import '../config-Cr3312zc.js';
7
+ import '../permission-Dx6dIqS2.js';
7
8
  import '../observability-D-HZN_mF.js';
8
- import '../brain-CCfuEOdp.js';
9
- import '../permission-DbsGOA1C.js';
9
+ import '../events-Bs2fmldo.js';
10
+ import '../secret-scrubber-3MHDDAtm.js';
@@ -1,5 +1,5 @@
1
- import { E as EventBus } from './brain-CCfuEOdp.js';
2
- import { M as MailboxMessage, a as MailboxAgentStatus, b as Mailbox, c as MailboxSendInput, d as MailboxQuery, e as MailboxAckInput, f as MailboxAckBatchInput, A as AgentRegistrationInput, g as AgentHeartbeatInput, C as ClientRegistrationInput, h as ClientHeartbeatInput, i as ClientStatus, P as PurgeOptions, j as PurgeResult } from './mailbox-types-DTl7bRH3.js';
1
+ import { M as MailboxMessage, a as MailboxAgentStatus, b as Mailbox, c as MailboxSendInput, d as MailboxQuery, e as MailboxAckInput, f as MailboxAckBatchInput, A as AgentRegistrationInput, g as AgentHeartbeatInput, C as ClientRegistrationInput, h as ClientHeartbeatInput, i as ClientStatus, P as PurgeOptions, j as PurgeResult } from './mailbox-types-BGZWrYTJ.js';
2
+ import { E as EventBus } from './events-Bs2fmldo.js';
3
3
 
4
4
  declare const HQ_PROTOCOL_VERSION: 1;
5
5
  type HqProtocolVersion = typeof HQ_PROTOCOL_VERSION;
@@ -58,7 +58,7 @@ interface HqEventEnvelope<TPayload = unknown> {
58
58
  seq: number;
59
59
  payload: TPayload;
60
60
  }
61
- type HqEventType = 'client.hello' | 'client.heartbeat' | 'session.started' | 'session.status' | 'session.usage' | 'tool.started' | 'tool.completed' | 'fleet.snapshot' | 'fleet.event' | 'mailbox.snapshot' | 'mailbox.event' | 'worklist.snapshot' | 'git.snapshot' | 'agent.message' | 'agent.status' | 'session.snapshot' | 'session.transcript' | 'session.ended';
61
+ type HqEventType = 'client.hello' | 'client.heartbeat' | 'session.started' | 'session.status' | 'session.usage' | 'tool.started' | 'tool.completed' | 'fleet.snapshot' | 'fleet.event' | 'mailbox.snapshot' | 'mailbox.event' | 'worklist.snapshot' | 'git.snapshot' | 'agent.message' | 'agent.status' | 'session.snapshot' | 'session.transcript' | 'session.ended' | 'brain.event' | 'worktree.event';
62
62
  interface HqClientHeartbeatPayload {
63
63
  uptimeMs: number;
64
64
  activeSessionId?: string;
@@ -123,7 +123,7 @@ interface HqAgentMessagePayload {
123
123
  subagentId: string;
124
124
  agentName: string;
125
125
  content: string;
126
- kind: 'text' | 'tool_use' | 'error' | 'status';
126
+ kind: 'text' | 'thinking' | 'tool_use' | 'tool_result' | 'error' | 'status' | 'system';
127
127
  iteration: number;
128
128
  ts: string;
129
129
  toolName?: string;
@@ -145,6 +145,53 @@ interface HqFleetEventPayload {
145
145
  summary?: string;
146
146
  data?: unknown;
147
147
  }
148
+ type HqBrainEventKind = 'decision_requested' | 'decision_answered' | 'decision_ask_human' | 'human_answered' | 'decision_denied' | 'intervention';
149
+ interface HqBrainEventPayload {
150
+ /** Which brain lifecycle event this is (mirrors the EventBus `brain.*` name suffix). */
151
+ kind: HqBrainEventKind;
152
+ /** The decision request id, when present (decision_request/answer/deny). */
153
+ requestId?: string;
154
+ /** Short human-readable question the brain was asked. */
155
+ question?: string;
156
+ /** The source that triggered the decision (e.g. 'autonomy', 'system'). */
157
+ source?: string;
158
+ /** Resolved risk tier, when known (e.g. 'low' | 'medium' | 'high'). */
159
+ risk?: string;
160
+ /** The chosen decision kind, when answered/denied (e.g. 'answer' | 'ask_human' | 'deny'). */
161
+ decision?: string;
162
+ /** Free-text rationale or answer payload, when present. */
163
+ detail?: string;
164
+ /** For `intervention`: the watched signal that engaged the brain. */
165
+ interventionKind?: 'tool_failure_streak' | 'error_storm';
166
+ /** For `intervention`: true when a steer was actually delivered to the agent. */
167
+ intervened?: boolean;
168
+ /** Epoch milliseconds at which the event occurred. */
169
+ at: number;
170
+ }
171
+ type HqWorktreeEventKind = 'allocated' | 'committed' | 'merged' | 'conflict' | 'released' | 'failed';
172
+ interface HqWorktreeEventPayload {
173
+ /** Which worktree lifecycle event this is (mirrors `worktree.<kind>`). */
174
+ kind: HqWorktreeEventKind;
175
+ handleId: string;
176
+ ownerId: string;
177
+ ownerLabel?: string;
178
+ slug?: string;
179
+ branch?: string;
180
+ baseBranch?: string;
181
+ /** For `committed`: diff stats. */
182
+ insertions?: number;
183
+ deletions?: number;
184
+ files?: number;
185
+ sha?: string;
186
+ /** For `merged`: whether the merge was a squash. */
187
+ squash?: boolean;
188
+ /** For `conflict`: the list of conflicting files. */
189
+ conflictFiles?: readonly string[];
190
+ /** For `released`: whether the worktree was kept (true) or pruned (false). */
191
+ kept?: boolean;
192
+ /** For `failed`: the error message. */
193
+ error?: string;
194
+ }
148
195
  type HqSessionLiveStatus = 'active' | 'idle' | 'closing' | 'stale';
149
196
  type HqSessionAgentLiveStatus = 'idle' | 'running' | 'streaming' | 'waiting_user' | 'error';
150
197
  /** A single live agent inside a session snapshot (mirrors SessionRegistry's AgentEntry). */
@@ -280,7 +327,7 @@ interface HqMailboxSnapshotPayload {
280
327
  }
281
328
  interface HqMailboxEventPayload {
282
329
  mailboxId: string;
283
- action: 'message.sent' | 'message.read' | 'message.completed' | 'message.updated' | 'agent.registered' | 'agent.heartbeat' | 'agent.offline';
330
+ action: 'message.sent' | 'message.read' | 'message.completed' | 'message.updated' | 'agent.registered' | 'agent.heartbeat' | 'agent.offline' | 'agent.deregistered';
284
331
  message?: HqMailboxMessageSummary;
285
332
  agent?: HqMailboxAgentSummary;
286
333
  summary?: string;
@@ -559,6 +606,22 @@ interface HqPublisherOptions {
559
606
  commandPollIntervalMs?: number;
560
607
  commandPollLimit?: number;
561
608
  onCommand?: HqPublisherCommandHandler;
609
+ /**
610
+ * Local auto-discovery hook: re-resolve the HQ endpoint before EVERY
611
+ * connect attempt (e.g. by reading `<hq dataDir>/runtime.json`). Returning
612
+ * `undefined` means no HQ is currently discoverable — the publisher stays
613
+ * dormant (events keep queueing, bounded) and re-checks every
614
+ * {@link HqPublisherOptions.discoveryPollMs}. Because the endpoint is
615
+ * re-resolved per attempt, an HQ started AFTER this client — or restarted
616
+ * on a different port, or one that minted its first client token on boot —
617
+ * is picked up automatically.
618
+ */
619
+ resolveEndpoint?: () => {
620
+ url: string;
621
+ token?: string | undefined;
622
+ } | undefined;
623
+ /** Dormant re-check interval while `resolveEndpoint` yields nothing. Default 5s. */
624
+ discoveryPollMs?: number;
562
625
  }
563
626
  interface HqPublishEventOptions {
564
627
  type: HqEventType | (string & {});
@@ -621,6 +684,11 @@ declare class HqPublisher {
621
684
  publishSessionEnded(payload: HqSessionEndedPayload, opts?: {
622
685
  timestamp?: string;
623
686
  }): HqEventEnvelope<HqSessionEndedPayload>;
687
+ /** Publish a fleet (multi-agent coordinator) snapshot. */
688
+ publishFleetSnapshot(payload: HqFleetSnapshotPayload, opts?: {
689
+ sessionId?: string;
690
+ timestamp?: string;
691
+ }): HqEventEnvelope<HqFleetSnapshotPayload>;
624
692
  pollCommands(): void;
625
693
  ackCommand(result: HqPublisherCommandResult): void;
626
694
  private sendHello;
@@ -634,6 +702,13 @@ declare class HqPublisher {
634
702
  private extractMessageData;
635
703
  private handleCommandBatch;
636
704
  private scheduleReconnect;
705
+ /**
706
+ * Dormant re-check while no HQ endpoint is discoverable. Uses a FIXED
707
+ * interval (not the exponential reconnect backoff): the check is a cheap
708
+ * local file read, and backing off would delay attaching to an HQ the
709
+ * user just started — the whole point of auto-discovery.
710
+ */
711
+ private scheduleDiscoveryPoll;
637
712
  }
638
713
 
639
714
  /**
@@ -726,7 +801,10 @@ declare class GlobalMailbox implements Mailbox {
726
801
  ack(input: MailboxAckInput): Promise<MailboxMessage | null>;
727
802
  ackMany(input: MailboxAckBatchInput): Promise<MailboxMessage[]>;
728
803
  unreadCount(forAgentId: string): Promise<number>;
804
+ softDelete(mailId: string, by: string): Promise<MailboxMessage | null>;
805
+ restore(mailId: string): Promise<MailboxMessage | null>;
729
806
  registerAgent(input: AgentRegistrationInput): Promise<void>;
807
+ deregisterAgent(agentId: string): Promise<void>;
730
808
  heartbeat(input: AgentHeartbeatInput): Promise<void>;
731
809
  getAgentStatuses(): Promise<MailboxAgentStatus[]>;
732
810
  getOnlineAgents(): Promise<MailboxAgentStatus[]>;
@@ -801,4 +879,4 @@ declare class GlobalMailbox implements Mailbox {
801
879
  private _writeClientRegistry;
802
880
  }
803
881
 
804
- export { type HqServerMessage as $, type HqMailboxAgentSummary as A, type HqMailboxEventAction as B, type HqMailboxEventPayload as C, DEFAULT_HQ_REDACTION_POLICY as D, type HqMailboxMappingOptions as E, type HqMailboxMessageSummary as F, GlobalMailbox as G, HQ_PROTOCOL_VERSION as H, type HqMailboxMessageType as I, type HqMailboxPriority as J, type HqMailboxSnapshotOptions as K, type HqMailboxSnapshotPayload as L, type HqMailboxSummary as M, type HqParseResult as N, type HqPathPolicy as O, type HqProjectIdentity as P, type HqProjectRecord as Q, type HqProjectStatus as R, type HqProtocolVersion as S, type HqPublishEventOptions as T, HqPublisher as U, type HqPublisherCommandHandler as V, type HqPublisherCommandResult as W, type HqPublisherOptions as X, type HqQueuedCommand as Y, type HqRedactionPolicy as Z, type HqServerCommandBatchMessage as _, type HqAgentMessagePayload as a, type HqSessionAgentLiveStatus as a0, type HqSessionAgentSummary as a1, type HqSessionEndedPayload as a2, type HqSessionLiveStatus as a3, type HqSessionSnapshotPayload as a4, type HqSessionStartedPayload as a5, type HqSessionStatus as a6, type HqSessionStatusPayload as a7, type HqSessionSummary as a8, type HqSnapshot as a9, type HqSocketFactory as aa, type HqSocketLike as ab, type HqSubagentSummary as ac, type HqToolArgsPolicy as ad, type HqToolCompletedPayload as ae, type HqToolStartedPayload as af, type HqTranscriptAppendPayload as ag, type HqTranscriptEntry as ah, type HqTranscriptRole as ai, type HqUsagePayload as aj, type HqWelcomePayload as ak, type HqWorklistCounts as al, type HqWorklistSnapshotPayload as am, type HqWorkspaceKind as an, createHqEventEnvelope as ao, createMailboxEventPayload as ap, createMailboxSnapshotPayload as aq, createMailboxSnapshotPayloadFromMailbox as ar, mapMailboxAgentToHqSummary as as, mapMailboxMessageToHqSummary as at, parseHqEventPayload as au, parseHqFrame as av, resolveProjectDir as aw, type HqAgentStatusPayload as b, type HqAlertMessage as c, type HqBrowserEventMessage as d, type HqBrowserMessage as e, type HqBrowserSnapshotMessage as f, type HqClientCapability as g, type HqClientCommandAckMessage as h, type HqClientCommandPollMessage as i, type HqClientEventMessage as j, type HqClientHeartbeatPayload as k, type HqClientHelloMessage as l, type HqClientHelloPayload as m, type HqClientIdentity as n, type HqClientKind as o, type HqClientMessage as p, type HqClientRecord as q, type HqEventEnvelope as r, type HqEventPayloadResult as s, type HqEventType as t, type HqFleetEventPayload as u, type HqFleetSnapshotPayload as v, type HqFleetSummary as w, type HqGitSnapshotPayload as x, type HqMachineRecord as y, type HqMailboxAgentStatus as z };
882
+ export { type HqRedactionPolicy as $, type HqMachineRecord as A, type HqMailboxAgentStatus as B, type HqMailboxAgentSummary as C, DEFAULT_HQ_REDACTION_POLICY as D, type HqMailboxEventAction as E, type HqMailboxEventPayload as F, GlobalMailbox as G, HQ_PROTOCOL_VERSION as H, type HqMailboxMappingOptions as I, type HqMailboxMessageSummary as J, type HqMailboxMessageType as K, type HqMailboxPriority as L, type HqMailboxSnapshotOptions as M, type HqMailboxSnapshotPayload as N, type HqMailboxSummary as O, type HqParseResult as P, type HqPathPolicy as Q, type HqProjectIdentity as R, type HqProjectRecord as S, type HqProjectStatus as T, type HqProtocolVersion as U, type HqPublishEventOptions as V, HqPublisher as W, type HqPublisherCommandHandler as X, type HqPublisherCommandResult as Y, type HqPublisherOptions as Z, type HqQueuedCommand as _, type HqAgentMessagePayload as a, type HqServerCommandBatchMessage as a0, type HqServerMessage as a1, type HqSessionAgentLiveStatus as a2, type HqSessionAgentSummary as a3, type HqSessionEndedPayload as a4, type HqSessionLiveStatus as a5, type HqSessionSnapshotPayload as a6, type HqSessionStartedPayload as a7, type HqSessionStatus as a8, type HqSessionStatusPayload as a9, resolveProjectDir as aA, type HqSessionSummary as aa, type HqSnapshot as ab, type HqSocketFactory as ac, type HqSocketLike as ad, type HqSubagentSummary as ae, type HqToolArgsPolicy as af, type HqToolCompletedPayload as ag, type HqToolStartedPayload as ah, type HqTranscriptAppendPayload as ai, type HqTranscriptEntry as aj, type HqTranscriptRole as ak, type HqUsagePayload as al, type HqWelcomePayload as am, type HqWorklistCounts as an, type HqWorklistSnapshotPayload as ao, type HqWorkspaceKind as ap, type HqWorktreeEventKind as aq, type HqWorktreeEventPayload as ar, createHqEventEnvelope as as, createMailboxEventPayload as at, createMailboxSnapshotPayload as au, createMailboxSnapshotPayloadFromMailbox as av, mapMailboxAgentToHqSummary as aw, mapMailboxMessageToHqSummary as ax, parseHqEventPayload as ay, parseHqFrame as az, type HqAgentStatusPayload as b, type HqAlertMessage as c, type HqBrainEventKind as d, type HqBrainEventPayload as e, type HqBrowserEventMessage as f, type HqBrowserMessage as g, type HqBrowserSnapshotMessage as h, type HqClientCapability as i, type HqClientCommandAckMessage as j, type HqClientCommandPollMessage as k, type HqClientEventMessage as l, type HqClientHeartbeatPayload as m, type HqClientHelloMessage as n, type HqClientHelloPayload as o, type HqClientIdentity as p, type HqClientKind as q, type HqClientMessage as r, type HqClientRecord as s, type HqEventEnvelope as t, type HqEventPayloadResult as u, type HqEventType as v, type HqFleetEventPayload as w, type HqFleetSnapshotPayload as x, type HqFleetSummary as y, type HqGitSnapshotPayload as z };
@@ -1,4 +1,4 @@
1
- import { E as EventBus } from './brain-CCfuEOdp.js';
1
+ import { E as EventBus } from './events-Bs2fmldo.js';
2
2
 
3
3
  /**
4
4
  * Long-running autonomous mission. A goal survives across sessions and