Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/ai-providers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,23 @@ export type ProviderEvent =

// ==================== Types ====================

/** A tool the AI invoked during this generation. Captured by AgentCenter
* as `tool_use` events stream through the pipeline. Used by AgentWork's
* outputGate to detect intent-signal tools like `notify_user`. */
export interface ToolCallSummary {
id: string
name: string
input: unknown
}

export interface ProviderResult {
text: string
media: MediaAttachment[]
mediaUrls?: string[]
/** Tool calls observed during this generation, in invocation order.
* AgentCenter populates this when it synthesizes the final done event;
* individual providers don't need to fill it themselves. */
toolCalls?: ReadonlyArray<ToolCallSummary>
}

// ==================== GenerateOpts ====================
Expand Down
10 changes: 9 additions & 1 deletion src/core/agent-center.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/

import type { AskOptions, ProviderResult, ProviderEvent, GenerateOpts } from './ai-provider-manager.js'
import type { ToolCallSummary } from '../ai-providers/types.js'
import type { ResolvedProfile } from './config.js'
import { GenerateRouter, StreamableResult } from './ai-provider-manager.js'
import { resolveProfile, resolveCredential } from './config.js'
Expand Down Expand Up @@ -131,6 +132,11 @@ export class AgentCenter {
let currentAssistantBlocks: ContentBlock[] = []
let currentUserBlocks: ContentBlock[] = []
let finalResult: ProviderResult | null = null
// Tool calls observed during this generation, captured for the final
// done event so AgentWork (and any other consumer awaiting the
// ProviderResult) can inspect what the AI invoked without having to
// re-stream the events themselves.
const toolCalls: ToolCallSummary[] = []

for await (const event of source) {
switch (event.type) {
Expand All @@ -143,6 +149,7 @@ export class AgentCenter {
// Unified logging — all providers get this now
logToolCall(event.name, event.input)
this.toolCallLog?.start(event.id, event.name, event.input, session.id)
toolCalls.push({ id: event.id, name: event.name, input: event.input })
currentAssistantBlocks.push({
type: 'tool_use',
id: event.id,
Expand Down Expand Up @@ -227,14 +234,15 @@ export class AgentCenter {
]
await session.appendAssistant(finalBlocks, provider.providerTag)

// 9. Yield done with merged media
// 9. Yield done with merged media + observed tool calls
const mediaUrls = mediaBlocks.map(b => (b as { type: 'image'; url: string }).url)
yield {
type: 'done',
result: {
text: finalResult.text,
media: allMedia,
mediaUrls,
toolCalls,
},
}
}
Expand Down
Loading
Loading