@dreb/coding-agent 2.64.0 → 2.64.2
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.
- package/README.md +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +5 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/buddy/buddy-manager.d.ts +6 -2
- package/dist/core/buddy/buddy-manager.d.ts.map +1 -1
- package/dist/core/buddy/buddy-manager.js +10 -6
- package/dist/core/buddy/buddy-manager.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +2 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +2 -2
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +2 -2
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +14 -10
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/dispatch-arbiter.d.ts +2 -0
- package/dist/core/dispatch-arbiter.d.ts.map +1 -1
- package/dist/core/dispatch-arbiter.js +2 -0
- package/dist/core/dispatch-arbiter.js.map +1 -1
- package/dist/core/output-guard.d.ts +9 -1
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js +75 -20
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/tab-title.d.ts +2 -0
- package/dist/core/tab-title.d.ts.map +1 -1
- package/dist/core/tab-title.js +3 -1
- package/dist/core/tab-title.js.map +1 -1
- package/dist/core/tools/subagent.d.ts +14 -2
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +17 -9
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +3 -2
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/index.d.ts +1 -0
- package/dist/modes/rpc/index.d.ts.map +1 -1
- package/dist/modes/rpc/index.js +1 -0
- package/dist/modes/rpc/index.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +1 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +21 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-event-projection.d.ts +7 -0
- package/dist/modes/rpc/rpc-event-projection.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-event-projection.js +161 -0
- package/dist/modes/rpc/rpc-event-projection.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +13 -9
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/docs/dashboard.md +15 -1
- package/docs/rpc.md +14 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tab-title.js","sourceRoot":"","sources":["../../src/core/tab-title.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Auto-generates a terminal tab title from session context after a threshold\n * number of tool calls. Uses a lightweight single-shot LLM call to produce a\n * concise title — the model aims for a configurable soft target (default 60\n * characters, via TabTitleSettings.maxTitleLength) and the result is hard-capped\n * at 300 characters — then sets it via the terminal's OSC 0 escape.\n *\n * Fires at most once per session. Final failures are reported through the\n * optional onError hook while preserving fire-and-forget behavior.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Api, Context, Model } from \"@dreb/ai\";\nimport { completeSimple } from \"@dreb/ai\";\nimport { CONFIG_DIR_NAME, getPackageDir } from \"../config.js\";\nimport { extractUserText, labelMessageEnd, labelToolEnd, RollingContextBuffer } from \"./context-buffer.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { TabTitleSettings } from \"./settings-manager.js\";\nimport { parseAgentFrontmatter, resolveModelForSubagentSpawn } from \"./tools/subagent.js\";\n\nconst DEFAULT_TRIGGER_AFTER = 9;\n// Soft target communicated to the model — titles should aim for this length but\n// may run longer when clarity demands it. Configurable via TabTitleSettings.maxTitleLength.\nconst DEFAULT_TITLE_SOFT_TARGET = 60;\n// Hidden hard cap — a safety limit that titles are truncated to regardless of the\n// soft target. The dashboard has room for long names; the TUI truncates visually.\nconst TITLE_HARD_CAP = 300;\n// Cap on how much of a single user message we feed into the title context.\nconst MAX_USER_TEXT_CHARS = 2000;\nconst TITLE_GENERATION_TIMEOUT_MS = 60_000;\n\nfunction buildTitlePrompt(softTarget: number): string {\n\treturn (\n\t\t\"You are a headless terminal-tab title generator. You are NOT the assistant in the session — \" +\n\t\t\"you will never speak to the user. Your only job is to output a single short title string, nothing else. \" +\n\t\t\"No quotes, no explanation, no preamble. \" +\n\t\t\"The title disambiguates terminal windows for a human at a glance. \" +\n\t\t\"Base the title PRIMARILY on the user's actual request and the concrete actions taken in THIS session. \" +\n\t\t\"Describe what is being DONE (e.g. 'Fix auth bug', 'Plan subagent refactor', 'Review modal'), \" +\n\t\t\"not just label the invocation. \" +\n\t\t\"Branch, repo, and cwd metadata are SECONDARY — use them only to disambiguate when the user's \" +\n\t\t\"request is otherwise ambiguous. Never let a branch name override the user's actual intent: \" +\n\t\t\"if the branch is 'feature/dashboard-foundation' but the user asked to install a Playwright skill, \" +\n\t\t\"the title is about the Playwright skill, not the dashboard. \" +\n\t\t\"Avoid reference-only formats like '#N' or 'mach6-X #N'. \" +\n\t\t\"Do not include 'dreb' — the caller already adds it. \" +\n\t\t`Output ONLY the title text. Aim for about ${softTarget} characters; a little longer is fine if needed for clarity.`\n\t);\n}\n\nexport interface TabTitleDeps {\n\t/** Set the terminal tab title (OSC 0). */\n\tsetTitle: (title: string) => void;\n\t/** Persist the generated title as the session name. Called with the raw title (without \"dreb - \" prefix). */\n\tsetSessionName?: (name: string) => void;\n\t/**\n\t * Get the current session name, if the session is already named. When this returns a\n\t * non-empty string, title generation is skipped — auto-titling only names unnamed\n\t * sessions and must never overwrite an existing (e.g. resumed) session's name.\n\t */\n\tgetSessionName?: () => string | undefined;\n\t/** Get the current session messages (for context). */\n\tgetMessages: () => Array<{ role: string; content?: unknown }>;\n\t/** Get the current model (parent session model — used as fallback). */\n\tgetModel: () => Model<Api> | undefined;\n\t/** Get model registry for API key resolution. */\n\tgetModelRegistry: () => ModelRegistry;\n\t/** Get the parent provider name. */\n\tgetProvider: () => string | undefined;\n\t/**\n\t * Get the user's agentModels settings override for a given agent name, if any.\n\t * Returns a non-empty fallback list when the user has configured an override.\n\t */\n\tgetAgentModelsOverride?: (agentName: string) => string[] | undefined;\n\t/** Current git branch name, or null/undefined if unavailable. */\n\tgetBranch?: () => string | null | undefined;\n\t/** Repository name (e.g., dirname of cwd), or undefined. */\n\tgetRepo?: () => string | undefined;\n\t/** Current working directory, or undefined. */\n\tgetCwd?: () => string | undefined;\n\t/** Report final title-generation failures without breaking fire-and-forget callers. */\n\tonError?: (err: unknown) => void;\n}\n\nexport class TabTitleGenerator {\n\tprivate toolCallCount = 0;\n\tprivate fired = false;\n\tprivate readonly threshold: number;\n\tprivate readonly softTarget: number;\n\tprivate readonly contextBuffer: RollingContextBuffer;\n\n\tconstructor(\n\t\tprivate readonly settings: TabTitleSettings | undefined,\n\t\tprivate readonly deps: TabTitleDeps,\n\t) {\n\t\tthis.threshold = settings?.triggerAfter ?? DEFAULT_TRIGGER_AFTER;\n\t\t// Soft target is configurable but always clamped to the hidden hard cap.\n\t\tconst configured = settings?.maxTitleLength ?? DEFAULT_TITLE_SOFT_TARGET;\n\t\tthis.softTarget = Math.max(1, Math.min(configured, TITLE_HARD_CAP));\n\t\tthis.contextBuffer = new RollingContextBuffer({ maxEntries: 30, maxChars: 6000 });\n\t}\n\n\t/** Whether this generator is enabled. */\n\tget enabled(): boolean {\n\t\treturn this.settings?.enabled !== false;\n\t}\n\n\t/**\n\t * Called on each tool_execution_end event. Captures context from the event,\n\t * increments the counter, and fires title generation when threshold is reached.\n\t */\n\tonToolEnd(event?: { toolName?: string; isError?: boolean; result?: unknown }): void {\n\t\tif (event?.toolName) {\n\t\t\tthis.contextBuffer.append(labelToolEnd(event as { toolName: string; isError?: boolean; result?: unknown }));\n\t\t}\n\n\t\tif (this.fired || !this.enabled) return;\n\n\t\tthis.toolCallCount++;\n\t\tif (this.toolCallCount >= this.threshold) {\n\t\t\tthis.fired = true;\n\t\t\t// Fire-and-forget — report final failures without throwing into the event stream.\n\t\t\tthis.generateTitle().catch((err) => this.reportError(err));\n\t\t}\n\t}\n\n\t/** Called on message_end events — captures labeled context. */\n\tonMessageEnd(message: { role: string; content?: unknown }): void {\n\t\tif (this.fired) return; // no need to accumulate after fired\n\t\tfor (const entry of labelMessageEnd(message)) {\n\t\t\tthis.contextBuffer.append(entry);\n\t\t}\n\t}\n\n\t/** Exposed for testing — the current tool call count. */\n\tget currentCount(): number {\n\t\treturn this.toolCallCount;\n\t}\n\n\t/** Exposed for testing — whether the title has been generated. */\n\tget hasFired(): boolean {\n\t\treturn this.fired;\n\t}\n\n\tprivate async generateTitle(): Promise<void> {\n\t\t// Skip entirely if the session already has a name (e.g. resumed session).\n\t\t// This guards the race where a name is set between generator construction and firing.\n\t\tif (this.deps.getSessionName?.()) return;\n\n\t\t// Single timeout bounds the entire pipeline (model probing + API key + LLM call)\n\t\tconst signal = AbortSignal.timeout(TITLE_GENERATION_TIMEOUT_MS);\n\n\t\tconst model = await this.resolveModel(signal);\n\t\tif (!model) return;\n\n\t\tconst userContext = this.buildContext();\n\t\tif (!userContext) return;\n\n\t\tconst context: Context = {\n\t\t\tsystemPrompt: buildTitlePrompt(this.softTarget),\n\t\t\tmessages: [{ role: \"user\", content: userContext, timestamp: Date.now() }],\n\t\t};\n\n\t\tconst response = await this.completeWithParentFallback(model, context, signal);\n\t\tconst title = this.sanitizeTitle(response);\n\t\tif (title) {\n\t\t\t// Re-check: a name may have landed during the async LLM call.\n\t\t\tif (this.deps.getSessionName?.()) return;\n\t\t\tthis.deps.setTitle(`dreb - ${title}`);\n\t\t\tthis.deps.setSessionName?.(title);\n\t\t}\n\t}\n\n\tprivate async completeWithParentFallback(\n\t\tmodel: Model<Api>,\n\t\tcontext: Context,\n\t\tsignal: AbortSignal,\n\t): Promise<unknown> {\n\t\tconst primaryErrorPrefix = `Tab title generation failed with model ${this.formatModel(model)}`;\n\t\ttry {\n\t\t\treturn await this.completeWithModel(model, context, signal);\n\t\t} catch (primaryErr) {\n\t\t\tconst parentModel = this.deps.getModel();\n\t\t\tif (!parentModel || this.isSameModel(model, parentModel)) {\n\t\t\t\tthrow new Error(`${primaryErrorPrefix}: ${this.formatError(primaryErr)}`, { cause: primaryErr });\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\treturn await this.completeWithModel(parentModel, context, signal);\n\t\t\t} catch (parentErr) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${primaryErrorPrefix}: ${this.formatError(primaryErr)}. ` +\n\t\t\t\t\t\t`Parent fallback ${this.formatModel(parentModel)} also failed: ${this.formatError(parentErr)}`,\n\t\t\t\t\t{ cause: parentErr },\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async completeWithModel(model: Model<Api>, context: Context, signal: AbortSignal): Promise<unknown> {\n\t\tconst registry = this.deps.getModelRegistry();\n\t\tconst apiKey = await registry.getApiKey(model);\n\t\treturn completeSimple(model, context, {\n\t\t\tapiKey,\n\t\t\tmaxRetryDelayMs: 0,\n\t\t\tsignal,\n\t\t});\n\t}\n\n\tprivate async resolveModel(signal?: AbortSignal): Promise<Model<Api> | undefined> {\n\t\tconst parentModel = this.deps.getModel();\n\t\tconst parentProvider = this.deps.getProvider();\n\t\tconst registry = this.deps.getModelRegistry();\n\n\t\t// A dedicated exact model bypasses Explore-agent routing. Dashboard/RPC writes\n\t\t// validate availability; a stale hand-edited value falls back to the parent.\n\t\tconst configuredModel = this.settings?.model;\n\t\tif (configuredModel) {\n\t\t\tconst slash = configuredModel.indexOf(\"/\");\n\t\t\tif (slash > 0 && slash < configuredModel.length - 1) {\n\t\t\t\tconst found = registry.find(configuredModel.slice(0, slash), configuredModel.slice(slash + 1));\n\t\t\t\tif (found) return found;\n\t\t\t}\n\t\t\treturn parentModel;\n\t\t}\n\n\t\t// Without a dedicated model, preserve the Explore agent fallback route.\n\t\tconst exploreModels = this.getExploreAgentModels();\n\t\tif (exploreModels) {\n\t\t\tconst resolution = await resolveModelForSubagentSpawn(\n\t\t\t\texploreModels,\n\t\t\t\tparentProvider,\n\t\t\t\tregistry,\n\t\t\t\tparentModel?.id,\n\t\t\t\tsignal,\n\t\t\t\t\"[tab-title]\",\n\t\t\t);\n\t\t\tif (resolution.ok) {\n\t\t\t\tconst found = resolution.provider\n\t\t\t\t\t? registry.find(resolution.provider, resolution.modelId)\n\t\t\t\t\t: registry.getAvailable().find((m) => m.id === resolution.modelId);\n\t\t\t\tif (found) return found;\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to parent session model\n\t\treturn parentModel;\n\t}\n\n\tprivate isSameModel(a: Model<Api>, b: Model<Api>): boolean {\n\t\treturn a.id === b.id && a.provider === b.provider;\n\t}\n\n\tprivate formatModel(model: Model<Api>): string {\n\t\treturn `${model.provider}/${model.id}`;\n\t}\n\n\tprivate formatError(err: unknown): string {\n\t\tif (err instanceof Error) return err.message;\n\t\tif (typeof err === \"string\") return err;\n\t\treturn String(err);\n\t}\n\n\tprivate reportError(err: unknown): void {\n\t\tconst reportedError =\n\t\t\terr instanceof Error\n\t\t\t\t? err\n\t\t\t\t: new Error(`Tab title generation failed: ${this.formatError(err)}`, { cause: err });\n\t\tthis.deps.onError?.(reportedError);\n\t}\n\n\tprivate getExploreAgentModels(): string | string[] | undefined {\n\t\t// Honor the user's agentModels settings override first. The settings key must\n\t\t// match the agent name exactly (\"Explore\", as declared in explore.md frontmatter).\n\t\tconst override = this.deps.getAgentModelsOverride?.(\"Explore\");\n\t\tif (override && override.length > 0) {\n\t\t\treturn override;\n\t\t}\n\n\t\t// Resolution order mirrors discoverAgentTypes: user override > project > package.\n\t\t// First match with a valid model wins.\n\t\tconst candidates = [\n\t\t\tjoin(homedir(), CONFIG_DIR_NAME, \"agents\", \"explore.md\"),\n\t\t\tjoin(process.cwd(), \".dreb\", \"agents\", \"explore.md\"),\n\t\t\tjoin(getPackageDir(), \"agents\", \"explore.md\"),\n\t\t];\n\n\t\tfor (const agentFile of candidates) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(agentFile, \"utf-8\");\n\t\t\t\tconst parsed = parseAgentFrontmatter(content);\n\t\t\t\tif (parsed.ok && parsed.config.model) {\n\t\t\t\t\treturn parsed.config.model;\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate buildContext(): string | undefined {\n\t\tconst lines: string[] = [];\n\n\t\t// Primary signal: the user's actual request(s) from the current session.\n\t\t// Pin the FIRST user message (session-defining intent) and append the LATEST\n\t\t// user message when it differs, to catch mid-session pivots. Sourced from the\n\t\t// live message list rather than the rolling buffer so early intent is never\n\t\t// evicted by later tool activity.\n\t\tconst userIntent = this.collectUserIntent();\n\t\tif (userIntent.length > 0) {\n\t\t\tlines.push(\"User request(s):\");\n\t\t\tfor (const req of userIntent) {\n\t\t\t\tlines.push(`- ${req}`);\n\t\t\t}\n\t\t}\n\n\t\t// Secondary signal: concrete current-session actions (assistant text + tools).\n\t\tconst bufferContent = this.contextBuffer.build();\n\t\tif (bufferContent) {\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\"Session activity:\");\n\t\t\tlines.push(bufferContent);\n\t\t}\n\n\t\t// Tertiary signal: metadata, for disambiguation only.\n\t\tconst branch = this.deps.getBranch?.();\n\t\tconst repo = this.deps.getRepo?.();\n\t\tconst cwd = this.deps.getCwd?.();\n\t\tconst metadata: string[] = [];\n\t\tif (branch) metadata.push(`Branch: ${branch}`);\n\t\tif (repo) metadata.push(`Repo: ${repo}`);\n\t\tif (cwd) metadata.push(`Cwd: ${cwd}`);\n\t\tif (metadata.length > 0) {\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\"Context metadata (secondary — disambiguation only):\");\n\t\t\tlines.push(...metadata);\n\t\t}\n\n\t\tif (lines.length === 0) return undefined;\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Collect the user's intent-bearing requests from the current session's messages.\n\t * Returns the first user message, plus the latest user message when it differs.\n\t */\n\tprivate collectUserIntent(): string[] {\n\t\tconst messages = this.deps.getMessages?.() ?? [];\n\t\tconst userTexts: string[] = [];\n\t\tfor (const message of messages) {\n\t\t\tconst text = extractUserText(message);\n\t\t\tif (text) userTexts.push(text.slice(0, MAX_USER_TEXT_CHARS));\n\t\t}\n\t\tif (userTexts.length === 0) return [];\n\n\t\tconst first = userTexts[0];\n\t\tconst last = userTexts[userTexts.length - 1];\n\t\treturn first === last ? [first] : [first, last];\n\t}\n\n\t/** Clean up LLM response to a usable tab title. */\n\tprivate sanitizeTitle(response: unknown): string | undefined {\n\t\tif (!response || typeof response !== \"object\") return undefined;\n\n\t\tconst msg = response as { content?: Array<{ type: string; text?: string }> };\n\t\tif (!msg.content || !Array.isArray(msg.content)) return undefined;\n\n\t\tconst textPart = msg.content.find((c) => c.type === \"text\");\n\t\tif (!textPart?.text) return undefined;\n\n\t\tlet title = textPart.text.trim();\n\t\t// Strip surrounding quotes if present\n\t\tif ((title.startsWith('\"') && title.endsWith('\"')) || (title.startsWith(\"'\") && title.endsWith(\"'\"))) {\n\t\t\ttitle = title.slice(1, -1).trim();\n\t\t}\n\t\t// Remove newlines\n\t\ttitle = title.replace(/[\\r\\n]+/g, \" \").trim();\n\t\t// Truncate to the hidden hard cap (safety limit; the soft target is a prompt hint)\n\t\tif (title.length > TITLE_HARD_CAP) {\n\t\t\ttitle = title.slice(0, TITLE_HARD_CAP);\n\t\t}\n\t\treturn title || undefined;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tab-title.js","sourceRoot":"","sources":["../../src/core/tab-title.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Auto-generates a terminal tab title from session context after a threshold\n * number of tool calls. Uses a lightweight single-shot LLM call to produce a\n * concise title — the model aims for a configurable soft target (default 60\n * characters, via TabTitleSettings.maxTitleLength) and the result is hard-capped\n * at 300 characters — then sets it via the terminal's OSC 0 escape.\n *\n * Fires at most once per session. Final failures are reported through the\n * optional onError hook while preserving fire-and-forget behavior.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Api, Context, Model } from \"@dreb/ai\";\nimport { completeSimple } from \"@dreb/ai\";\nimport { CONFIG_DIR_NAME, getPackageDir } from \"../config.js\";\nimport { extractUserText, labelMessageEnd, labelToolEnd, RollingContextBuffer } from \"./context-buffer.js\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport type { TabTitleSettings } from \"./settings-manager.js\";\nimport { parseAgentFrontmatter, resolveModelForSubagentSpawn } from \"./tools/subagent.js\";\n\nconst DEFAULT_TRIGGER_AFTER = 9;\n// Soft target communicated to the model — titles should aim for this length but\n// may run longer when clarity demands it. Configurable via TabTitleSettings.maxTitleLength.\nconst DEFAULT_TITLE_SOFT_TARGET = 60;\n// Hidden hard cap — a safety limit that titles are truncated to regardless of the\n// soft target. The dashboard has room for long names; the TUI truncates visually.\nconst TITLE_HARD_CAP = 300;\n// Cap on how much of a single user message we feed into the title context.\nconst MAX_USER_TEXT_CHARS = 2000;\nconst TITLE_GENERATION_TIMEOUT_MS = 60_000;\n\nfunction buildTitlePrompt(softTarget: number): string {\n\treturn (\n\t\t\"You are a headless terminal-tab title generator. You are NOT the assistant in the session — \" +\n\t\t\"you will never speak to the user. Your only job is to output a single short title string, nothing else. \" +\n\t\t\"No quotes, no explanation, no preamble. \" +\n\t\t\"The title disambiguates terminal windows for a human at a glance. \" +\n\t\t\"Base the title PRIMARILY on the user's actual request and the concrete actions taken in THIS session. \" +\n\t\t\"Describe what is being DONE (e.g. 'Fix auth bug', 'Plan subagent refactor', 'Review modal'), \" +\n\t\t\"not just label the invocation. \" +\n\t\t\"Branch, repo, and cwd metadata are SECONDARY — use them only to disambiguate when the user's \" +\n\t\t\"request is otherwise ambiguous. Never let a branch name override the user's actual intent: \" +\n\t\t\"if the branch is 'feature/dashboard-foundation' but the user asked to install a Playwright skill, \" +\n\t\t\"the title is about the Playwright skill, not the dashboard. \" +\n\t\t\"Avoid reference-only formats like '#N' or 'mach6-X #N'. \" +\n\t\t\"Do not include 'dreb' — the caller already adds it. \" +\n\t\t`Output ONLY the title text. Aim for about ${softTarget} characters; a little longer is fine if needed for clarity.`\n\t);\n}\n\nexport interface TabTitleDeps {\n\t/** Set the terminal tab title (OSC 0). */\n\tsetTitle: (title: string) => void;\n\t/** Persist the generated title as the session name. Called with the raw title (without \"dreb - \" prefix). */\n\tsetSessionName?: (name: string) => void;\n\t/**\n\t * Get the current session name, if the session is already named. When this returns a\n\t * non-empty string, title generation is skipped — auto-titling only names unnamed\n\t * sessions and must never overwrite an existing (e.g. resumed) session's name.\n\t */\n\tgetSessionName?: () => string | undefined;\n\t/** Get the current session messages (for context). */\n\tgetMessages: () => Array<{ role: string; content?: unknown }>;\n\t/** Get the current model (parent session model — used as fallback). */\n\tgetModel: () => Model<Api> | undefined;\n\t/** Get model registry for API key resolution. */\n\tgetModelRegistry: () => ModelRegistry;\n\t/** Get the parent provider name. */\n\tgetProvider: () => string | undefined;\n\t/** Get the parent session's stable conversation UUID, forwarded to LLM requests (issue 500). */\n\tgetSessionId?: () => string | undefined;\n\t/**\n\t * Get the user's agentModels settings override for a given agent name, if any.\n\t * Returns a non-empty fallback list when the user has configured an override.\n\t */\n\tgetAgentModelsOverride?: (agentName: string) => string[] | undefined;\n\t/** Current git branch name, or null/undefined if unavailable. */\n\tgetBranch?: () => string | null | undefined;\n\t/** Repository name (e.g., dirname of cwd), or undefined. */\n\tgetRepo?: () => string | undefined;\n\t/** Current working directory, or undefined. */\n\tgetCwd?: () => string | undefined;\n\t/** Report final title-generation failures without breaking fire-and-forget callers. */\n\tonError?: (err: unknown) => void;\n}\n\nexport class TabTitleGenerator {\n\tprivate toolCallCount = 0;\n\tprivate fired = false;\n\tprivate readonly threshold: number;\n\tprivate readonly softTarget: number;\n\tprivate readonly contextBuffer: RollingContextBuffer;\n\n\tconstructor(\n\t\tprivate readonly settings: TabTitleSettings | undefined,\n\t\tprivate readonly deps: TabTitleDeps,\n\t) {\n\t\tthis.threshold = settings?.triggerAfter ?? DEFAULT_TRIGGER_AFTER;\n\t\t// Soft target is configurable but always clamped to the hidden hard cap.\n\t\tconst configured = settings?.maxTitleLength ?? DEFAULT_TITLE_SOFT_TARGET;\n\t\tthis.softTarget = Math.max(1, Math.min(configured, TITLE_HARD_CAP));\n\t\tthis.contextBuffer = new RollingContextBuffer({ maxEntries: 30, maxChars: 6000 });\n\t}\n\n\t/** Whether this generator is enabled. */\n\tget enabled(): boolean {\n\t\treturn this.settings?.enabled !== false;\n\t}\n\n\t/**\n\t * Called on each tool_execution_end event. Captures context from the event,\n\t * increments the counter, and fires title generation when threshold is reached.\n\t */\n\tonToolEnd(event?: { toolName?: string; isError?: boolean; result?: unknown }): void {\n\t\tif (event?.toolName) {\n\t\t\tthis.contextBuffer.append(labelToolEnd(event as { toolName: string; isError?: boolean; result?: unknown }));\n\t\t}\n\n\t\tif (this.fired || !this.enabled) return;\n\n\t\tthis.toolCallCount++;\n\t\tif (this.toolCallCount >= this.threshold) {\n\t\t\tthis.fired = true;\n\t\t\t// Fire-and-forget — report final failures without throwing into the event stream.\n\t\t\tthis.generateTitle().catch((err) => this.reportError(err));\n\t\t}\n\t}\n\n\t/** Called on message_end events — captures labeled context. */\n\tonMessageEnd(message: { role: string; content?: unknown }): void {\n\t\tif (this.fired) return; // no need to accumulate after fired\n\t\tfor (const entry of labelMessageEnd(message)) {\n\t\t\tthis.contextBuffer.append(entry);\n\t\t}\n\t}\n\n\t/** Exposed for testing — the current tool call count. */\n\tget currentCount(): number {\n\t\treturn this.toolCallCount;\n\t}\n\n\t/** Exposed for testing — whether the title has been generated. */\n\tget hasFired(): boolean {\n\t\treturn this.fired;\n\t}\n\n\tprivate async generateTitle(): Promise<void> {\n\t\t// Skip entirely if the session already has a name (e.g. resumed session).\n\t\t// This guards the race where a name is set between generator construction and firing.\n\t\tif (this.deps.getSessionName?.()) return;\n\n\t\t// Single timeout bounds the entire pipeline (model probing + API key + LLM call)\n\t\tconst signal = AbortSignal.timeout(TITLE_GENERATION_TIMEOUT_MS);\n\n\t\tconst model = await this.resolveModel(signal);\n\t\tif (!model) return;\n\n\t\tconst userContext = this.buildContext();\n\t\tif (!userContext) return;\n\n\t\tconst context: Context = {\n\t\t\tsystemPrompt: buildTitlePrompt(this.softTarget),\n\t\t\tmessages: [{ role: \"user\", content: userContext, timestamp: Date.now() }],\n\t\t};\n\n\t\tconst response = await this.completeWithParentFallback(model, context, signal);\n\t\tconst title = this.sanitizeTitle(response);\n\t\tif (title) {\n\t\t\t// Re-check: a name may have landed during the async LLM call.\n\t\t\tif (this.deps.getSessionName?.()) return;\n\t\t\tthis.deps.setTitle(`dreb - ${title}`);\n\t\t\tthis.deps.setSessionName?.(title);\n\t\t}\n\t}\n\n\tprivate async completeWithParentFallback(\n\t\tmodel: Model<Api>,\n\t\tcontext: Context,\n\t\tsignal: AbortSignal,\n\t): Promise<unknown> {\n\t\tconst primaryErrorPrefix = `Tab title generation failed with model ${this.formatModel(model)}`;\n\t\ttry {\n\t\t\treturn await this.completeWithModel(model, context, signal);\n\t\t} catch (primaryErr) {\n\t\t\tconst parentModel = this.deps.getModel();\n\t\t\tif (!parentModel || this.isSameModel(model, parentModel)) {\n\t\t\t\tthrow new Error(`${primaryErrorPrefix}: ${this.formatError(primaryErr)}`, { cause: primaryErr });\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\treturn await this.completeWithModel(parentModel, context, signal);\n\t\t\t} catch (parentErr) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${primaryErrorPrefix}: ${this.formatError(primaryErr)}. ` +\n\t\t\t\t\t\t`Parent fallback ${this.formatModel(parentModel)} also failed: ${this.formatError(parentErr)}`,\n\t\t\t\t\t{ cause: parentErr },\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async completeWithModel(model: Model<Api>, context: Context, signal: AbortSignal): Promise<unknown> {\n\t\tconst registry = this.deps.getModelRegistry();\n\t\tconst apiKey = await registry.getApiKey(model);\n\t\tconst sessionId = this.deps.getSessionId?.();\n\t\treturn completeSimple(model, context, {\n\t\t\tapiKey,\n\t\t\tmaxRetryDelayMs: 0,\n\t\t\tsignal,\n\t\t\t...(sessionId ? { sessionId } : {}),\n\t\t});\n\t}\n\n\tprivate async resolveModel(signal?: AbortSignal): Promise<Model<Api> | undefined> {\n\t\tconst parentModel = this.deps.getModel();\n\t\tconst parentProvider = this.deps.getProvider();\n\t\tconst registry = this.deps.getModelRegistry();\n\n\t\t// A dedicated exact model bypasses Explore-agent routing. Dashboard/RPC writes\n\t\t// validate availability; a stale hand-edited value falls back to the parent.\n\t\tconst configuredModel = this.settings?.model;\n\t\tif (configuredModel) {\n\t\t\tconst slash = configuredModel.indexOf(\"/\");\n\t\t\tif (slash > 0 && slash < configuredModel.length - 1) {\n\t\t\t\tconst found = registry.find(configuredModel.slice(0, slash), configuredModel.slice(slash + 1));\n\t\t\t\tif (found) return found;\n\t\t\t}\n\t\t\treturn parentModel;\n\t\t}\n\n\t\t// Without a dedicated model, preserve the Explore agent fallback route.\n\t\tconst exploreModels = this.getExploreAgentModels();\n\t\tif (exploreModels) {\n\t\t\tconst resolution = await resolveModelForSubagentSpawn(\n\t\t\t\texploreModels,\n\t\t\t\tparentProvider,\n\t\t\t\tregistry,\n\t\t\t\tparentModel?.id,\n\t\t\t\tsignal,\n\t\t\t\t\"[tab-title]\",\n\t\t\t\tthis.deps.getSessionId?.(),\n\t\t\t);\n\t\t\tif (resolution.ok) {\n\t\t\t\tconst found = resolution.provider\n\t\t\t\t\t? registry.find(resolution.provider, resolution.modelId)\n\t\t\t\t\t: registry.getAvailable().find((m) => m.id === resolution.modelId);\n\t\t\t\tif (found) return found;\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to parent session model\n\t\treturn parentModel;\n\t}\n\n\tprivate isSameModel(a: Model<Api>, b: Model<Api>): boolean {\n\t\treturn a.id === b.id && a.provider === b.provider;\n\t}\n\n\tprivate formatModel(model: Model<Api>): string {\n\t\treturn `${model.provider}/${model.id}`;\n\t}\n\n\tprivate formatError(err: unknown): string {\n\t\tif (err instanceof Error) return err.message;\n\t\tif (typeof err === \"string\") return err;\n\t\treturn String(err);\n\t}\n\n\tprivate reportError(err: unknown): void {\n\t\tconst reportedError =\n\t\t\terr instanceof Error\n\t\t\t\t? err\n\t\t\t\t: new Error(`Tab title generation failed: ${this.formatError(err)}`, { cause: err });\n\t\tthis.deps.onError?.(reportedError);\n\t}\n\n\tprivate getExploreAgentModels(): string | string[] | undefined {\n\t\t// Honor the user's agentModels settings override first. The settings key must\n\t\t// match the agent name exactly (\"Explore\", as declared in explore.md frontmatter).\n\t\tconst override = this.deps.getAgentModelsOverride?.(\"Explore\");\n\t\tif (override && override.length > 0) {\n\t\t\treturn override;\n\t\t}\n\n\t\t// Resolution order mirrors discoverAgentTypes: user override > project > package.\n\t\t// First match with a valid model wins.\n\t\tconst candidates = [\n\t\t\tjoin(homedir(), CONFIG_DIR_NAME, \"agents\", \"explore.md\"),\n\t\t\tjoin(process.cwd(), \".dreb\", \"agents\", \"explore.md\"),\n\t\t\tjoin(getPackageDir(), \"agents\", \"explore.md\"),\n\t\t];\n\n\t\tfor (const agentFile of candidates) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(agentFile, \"utf-8\");\n\t\t\t\tconst parsed = parseAgentFrontmatter(content);\n\t\t\t\tif (parsed.ok && parsed.config.model) {\n\t\t\t\t\treturn parsed.config.model;\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate buildContext(): string | undefined {\n\t\tconst lines: string[] = [];\n\n\t\t// Primary signal: the user's actual request(s) from the current session.\n\t\t// Pin the FIRST user message (session-defining intent) and append the LATEST\n\t\t// user message when it differs, to catch mid-session pivots. Sourced from the\n\t\t// live message list rather than the rolling buffer so early intent is never\n\t\t// evicted by later tool activity.\n\t\tconst userIntent = this.collectUserIntent();\n\t\tif (userIntent.length > 0) {\n\t\t\tlines.push(\"User request(s):\");\n\t\t\tfor (const req of userIntent) {\n\t\t\t\tlines.push(`- ${req}`);\n\t\t\t}\n\t\t}\n\n\t\t// Secondary signal: concrete current-session actions (assistant text + tools).\n\t\tconst bufferContent = this.contextBuffer.build();\n\t\tif (bufferContent) {\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\"Session activity:\");\n\t\t\tlines.push(bufferContent);\n\t\t}\n\n\t\t// Tertiary signal: metadata, for disambiguation only.\n\t\tconst branch = this.deps.getBranch?.();\n\t\tconst repo = this.deps.getRepo?.();\n\t\tconst cwd = this.deps.getCwd?.();\n\t\tconst metadata: string[] = [];\n\t\tif (branch) metadata.push(`Branch: ${branch}`);\n\t\tif (repo) metadata.push(`Repo: ${repo}`);\n\t\tif (cwd) metadata.push(`Cwd: ${cwd}`);\n\t\tif (metadata.length > 0) {\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\"Context metadata (secondary — disambiguation only):\");\n\t\t\tlines.push(...metadata);\n\t\t}\n\n\t\tif (lines.length === 0) return undefined;\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Collect the user's intent-bearing requests from the current session's messages.\n\t * Returns the first user message, plus the latest user message when it differs.\n\t */\n\tprivate collectUserIntent(): string[] {\n\t\tconst messages = this.deps.getMessages?.() ?? [];\n\t\tconst userTexts: string[] = [];\n\t\tfor (const message of messages) {\n\t\t\tconst text = extractUserText(message);\n\t\t\tif (text) userTexts.push(text.slice(0, MAX_USER_TEXT_CHARS));\n\t\t}\n\t\tif (userTexts.length === 0) return [];\n\n\t\tconst first = userTexts[0];\n\t\tconst last = userTexts[userTexts.length - 1];\n\t\treturn first === last ? [first] : [first, last];\n\t}\n\n\t/** Clean up LLM response to a usable tab title. */\n\tprivate sanitizeTitle(response: unknown): string | undefined {\n\t\tif (!response || typeof response !== \"object\") return undefined;\n\n\t\tconst msg = response as { content?: Array<{ type: string; text?: string }> };\n\t\tif (!msg.content || !Array.isArray(msg.content)) return undefined;\n\n\t\tconst textPart = msg.content.find((c) => c.type === \"text\");\n\t\tif (!textPart?.text) return undefined;\n\n\t\tlet title = textPart.text.trim();\n\t\t// Strip surrounding quotes if present\n\t\tif ((title.startsWith('\"') && title.endsWith('\"')) || (title.startsWith(\"'\") && title.endsWith(\"'\"))) {\n\t\t\ttitle = title.slice(1, -1).trim();\n\t\t}\n\t\t// Remove newlines\n\t\ttitle = title.replace(/[\\r\\n]+/g, \" \").trim();\n\t\t// Truncate to the hidden hard cap (safety limit; the soft target is a prompt hint)\n\t\tif (title.length > TITLE_HARD_CAP) {\n\t\t\ttitle = title.slice(0, TITLE_HARD_CAP);\n\t\t}\n\t\treturn title || undefined;\n\t}\n}\n"]}
|
|
@@ -135,6 +135,8 @@ export interface ProbeModelAvailabilityOptions {
|
|
|
135
135
|
registry?: ModelRegistry;
|
|
136
136
|
/** Override the default model availability probe timeout; primarily useful for tests. */
|
|
137
137
|
timeoutMs?: number;
|
|
138
|
+
/** Stable conversation ID forwarded to providers that use session-based routing. */
|
|
139
|
+
sessionId?: string;
|
|
138
140
|
}
|
|
139
141
|
export type ProbeModelAvailabilityResult = {
|
|
140
142
|
ok: true;
|
|
@@ -162,7 +164,9 @@ export type SubagentModelResolution = {
|
|
|
162
164
|
};
|
|
163
165
|
export declare function resolveModelForSubagentSpawn(models: string | string[], parentProvider: string | undefined, registry: ModelRegistry | undefined, parentModel?: string, signal?: AbortSignal,
|
|
164
166
|
/** Optional log prefix for warning messages (defaults to "[subagent]") */
|
|
165
|
-
logPrefix?: string
|
|
167
|
+
logPrefix?: string,
|
|
168
|
+
/** Stable conversation ID forwarded to availability probes (issue 500). */
|
|
169
|
+
sessionId?: string): Promise<SubagentModelResolution>;
|
|
166
170
|
export declare function formatModelFallbackSummary(skippedModels: SkippedFallbackModel[], proposalModel: string | undefined, finalModel?: string): string | undefined;
|
|
167
171
|
export declare function prependModelFallbackSummary(output: string, skippedModels: SkippedFallbackModel[], proposalModel: string | undefined, finalModel?: string): string;
|
|
168
172
|
/**
|
|
@@ -191,7 +195,9 @@ export interface SubagentArbitrationHooks {
|
|
|
191
195
|
defaultThinkingLevel?: ThinkingLevel;
|
|
192
196
|
getAgentModelsForAgent?: (name: string) => string[] | undefined;
|
|
193
197
|
}
|
|
194
|
-
export declare function executeSingle(agents: Map<string, AgentTypeConfig>, agentName: string | undefined, task: string, cwd: string, signal?: AbortSignal, onProgress?: (event: string) => void, modelOverride?: string, parentProvider?: string, registry?: ModelRegistry, sessionDir?: string, parentModel?: string, agentModels?: string[], parentSessionFile?: string, onChildEvent?: (event: Record<string, unknown>) => void, thinkingOverride?: ThinkingLevel, arbitration?: SubagentArbitrationHooks, onControlAvailable?: (client: RpcClient | undefined) => void
|
|
198
|
+
export declare function executeSingle(agents: Map<string, AgentTypeConfig>, agentName: string | undefined, task: string, cwd: string, signal?: AbortSignal, onProgress?: (event: string) => void, modelOverride?: string, parentProvider?: string, registry?: ModelRegistry, sessionDir?: string, parentModel?: string, agentModels?: string[], parentSessionFile?: string, onChildEvent?: (event: Record<string, unknown>) => void, thinkingOverride?: ThinkingLevel, arbitration?: SubagentArbitrationHooks, onControlAvailable?: (client: RpcClient | undefined) => void,
|
|
199
|
+
/** Parent session UUID for spawn-time availability probes (issue 500). */
|
|
200
|
+
parentSessionId?: string): Promise<SubagentResult>;
|
|
195
201
|
export interface BackgroundAgentInfo {
|
|
196
202
|
agentId: string;
|
|
197
203
|
agentType: string;
|
|
@@ -249,6 +255,12 @@ export interface SubagentToolOptions {
|
|
|
249
255
|
parentModel?: () => string | undefined;
|
|
250
256
|
/** Parent session's current session file path. Used to link subagent child sessions back to their parent session. */
|
|
251
257
|
parentSessionFile?: () => string | undefined;
|
|
258
|
+
/**
|
|
259
|
+
* Parent session's stable conversation UUID. Forwarded to spawn-time model availability
|
|
260
|
+
* probes so providers with session-based routing (e.g. OpenCode) can group the probe
|
|
261
|
+
* with the parent conversation (issue 500).
|
|
262
|
+
*/
|
|
263
|
+
parentSessionId?: () => string | undefined;
|
|
252
264
|
/** Model registry for validating model names before spawning child processes. */
|
|
253
265
|
modelRegistry?: ModelRegistry;
|
|
254
266
|
/** Settings-based model override getter for mach6.models. */
|