Skip to content

Commit dc641f9

Browse files
wip v28
1 parent 5d52d3a commit dc641f9

4 files changed

Lines changed: 126 additions & 2 deletions

File tree

packages/pipelines-generics/src/streaming/__tests__/forkable-execution.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,4 +285,54 @@ describe('enablePipelineStreaming + Execution emits DB events (snapshot stream)'
285285
tool_error: null,
286286
});
287287
});
288+
289+
it('creates correlation rows for stored tool status events outside an explicit agent span', async () => {
290+
const supabase = new MockSupabase() as any;
291+
const runId = '77777777-7777-4777-8777-777777777777';
292+
const userId = '88888888-8888-4888-8888-888888888888';
293+
294+
const exec = new Execution(`exec-${runId}`);
295+
const streamer = enablePipelineStreaming(exec as any, {
296+
runId,
297+
userId,
298+
supabase,
299+
structuredToDatabase: true,
300+
});
301+
302+
await ExecutionStreamAdapter.emitEvent(exec.id, 'status' as any, {
303+
namespace: 'tools',
304+
key: 'result',
305+
data: {
306+
tool: 'bitcode.depository.search',
307+
ok: true,
308+
input: { read: { id: 'read-1' }, assetCount: 1 },
309+
output: { resultState: 'worthy_fit', selectedCandidateCount: 1 },
310+
phase: 'setup',
311+
agent: 'setup:depository-search',
312+
step: 'try',
313+
},
314+
});
315+
316+
await (streamer as any).flushStructuredWrites?.();
317+
318+
expect(supabase.tables.deliverable_pipeline_phase_delegations).toHaveLength(1);
319+
expect(supabase.tables.deliverable_pipeline_phase_delegations[0]).toMatchObject({
320+
phase_name: 'setup',
321+
status: 'completed',
322+
});
323+
expect(supabase.tables.deliverable_pipeline_agent_steps).toHaveLength(1);
324+
expect(supabase.tables.deliverable_pipeline_agent_steps[0]).toMatchObject({
325+
phase_delegation_id: 'deliverable_pipeline_phase_delegations-1',
326+
agent_name: 'setup:depository-search',
327+
status: 'completed',
328+
});
329+
expect(supabase.tables.deliverable_pipeline_tool_executions).toHaveLength(1);
330+
expect(supabase.tables.deliverable_pipeline_tool_executions[0]).toMatchObject({
331+
agent_step_id: 'deliverable_pipeline_agent_steps-1',
332+
tool_name: 'bitcode.depository.search',
333+
tool_input: { read: { id: 'read-1' }, assetCount: 1 },
334+
tool_output: { resultState: 'worthy_fit', selectedCandidateCount: 1 },
335+
tool_error: null,
336+
});
337+
});
288338
});

packages/pipelines-generics/src/streaming/pipeline-stream-integration.ts

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,63 @@ export function enablePipelineStreaming(
259259
}, 'id', deliverableRunId).catch(() => {});
260260
};
261261

262+
const ensurePhaseDelegationForEvent = async (
263+
phaseId: string | null | undefined,
264+
phaseName: string | null,
265+
now: string
266+
): Promise<string | null> => {
267+
if (phaseId) return phaseId;
268+
if (!phaseName || !(await ensureDeliverableRun())) return null;
269+
const existing = phaseIdByName.get(phaseName);
270+
if (existing) return existing;
271+
272+
const row: import('../types/db').DPPhaseDelegationInsert = {
273+
run_id: deliverableRunId,
274+
phase_name: phaseName,
275+
started_at: now,
276+
completed_at: now,
277+
status: 'completed',
278+
input_data: { inferredFrom: 'tool-execution-event' },
279+
output_data: { inferredFrom: 'tool-execution-event' },
280+
} as any;
281+
const { data, error } = await insertRow('deliverable_pipeline_phase_delegations', row, true);
282+
if (!error && data?.id) {
283+
phaseIdByName.set(phaseName, data.id);
284+
return data.id;
285+
}
286+
return null;
287+
};
288+
289+
const ensureAgentStepForEvent = async (
290+
phaseId: string | null,
291+
phaseName: string | null,
292+
agentName: string | null,
293+
stepType: string | null,
294+
now: string
295+
): Promise<string | null> => {
296+
if (!(phaseId && agentName && stepType)) return null;
297+
const key = agentStepKey(phaseId, phaseName, agentName, stepType);
298+
const existing = agentStepMap.get(key);
299+
if (existing) return existing;
300+
301+
const row: import('../types/db').DPAgentStepInsert = {
302+
phase_delegation_id: phaseId,
303+
agent_name: agentName,
304+
step_type: stepType,
305+
started_at: now,
306+
completed_at: now,
307+
status: 'completed',
308+
input_data: { inferredFrom: 'tool-execution-event' },
309+
output_data: { inferredFrom: 'tool-execution-event' },
310+
} as any;
311+
const { data, error } = await insertRow('deliverable_pipeline_agent_steps', row, true);
312+
if (!error && data?.id) {
313+
agentStepMap.set(key, data.id);
314+
return data.id;
315+
}
316+
return null;
317+
};
318+
262319
const completeOpenHierarchyRows = async (now: string) => {
263320
if (!(await ensureDeliverableRun())) return;
264321
const { data: openPhases } = await (supabase as any)
@@ -299,9 +356,12 @@ export function enablePipelineStreaming(
299356

300357
const structuredTool = normalizeToolExecutionEvent(event);
301358
if (structuredTool && await ensureDeliverableRun()) {
302-
const phaseId = phaseState.currentPhaseId || (phaseName ? phaseIdByName.get(phaseName) : null);
359+
let phaseId = phaseState.currentPhaseId || (phaseName ? phaseIdByName.get(phaseName) : null);
360+
phaseId = await ensurePhaseDelegationForEvent(phaseId ?? null, phaseName, now);
303361
const key = agentStepKey(phaseId ?? null, phaseName, agentName, stepType);
304-
const agentStepId = agentStepMap.get(key) || null;
362+
const agentStepId =
363+
agentStepMap.get(key) ||
364+
await ensureAgentStepForEvent(phaseId ?? null, phaseName, agentName, stepType, now);
305365
const row: import('../types/db').DPToolExecInsert = {
306366
agent_step_id: agentStepId,
307367
substep_id: null,

packages/pipelines/asset-pack/src/__tests__/finish-delivery.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,20 @@ describe('finish pull-request delivery', () => {
9494
expect(exec.get('tools', 'vcs_create_branch:0')).toMatchObject({
9595
tool: 'vcs_create_branch',
9696
ok: true,
97+
phase: 'finish',
98+
agent: 'finish:asset-pack-delivery-agent',
9799
});
98100
expect(exec.get('tools', 'vcs_create_or_update_file:1')).toMatchObject({
99101
tool: 'vcs_create_or_update_file',
100102
ok: true,
103+
phase: 'finish',
104+
agent: 'finish:asset-pack-delivery-agent',
101105
});
102106
expect(exec.get('tools', 'vcs_create_pull_request:2')).toMatchObject({
103107
tool: 'vcs_create_pull_request',
104108
ok: true,
109+
phase: 'finish',
110+
agent: 'finish:asset-pack-delivery-agent',
105111
});
106112
expect(emitToolUsage).toHaveBeenCalledTimes(3);
107113
expect(emitToolUsage.mock.calls[1][3]).toMatchObject({

packages/pipelines/asset-pack/src/agents/finish/deliver-asset-pack-to-destination-agent.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,10 @@ async function runDeliveryTool<T>(
411411
ok: true,
412412
input: summarizedInput,
413413
output: summarizedOutput,
414+
phase: 'finish',
415+
agent: 'finish:asset-pack-delivery-agent',
416+
step: 'try',
417+
generation: 'tools_execution',
414418
});
415419
await emitToolUsage(execution, toolName, summarizedInput, summarizedOutput, null);
416420
return output;
@@ -422,6 +426,10 @@ async function runDeliveryTool<T>(
422426
ok: false,
423427
input: summarizedInput,
424428
error: { message },
429+
phase: 'finish',
430+
agent: 'finish:asset-pack-delivery-agent',
431+
step: 'try',
432+
generation: 'tools_execution',
425433
});
426434
await emitToolUsage(execution, toolName, summarizedInput, null, message);
427435
throw error;

0 commit comments

Comments
 (0)