feat(events): add timeline and agent runtime baselines

This commit is contained in:
Saravana Achu Mac 2026-04-03 19:53:41 -07:00
parent c465fc3607
commit 3f2482b12c
5 changed files with 486 additions and 0 deletions

View File

@ -0,0 +1,119 @@
import { describe, expect, it } from 'vitest';
import {
AgentActionLogSchema,
AgentApprovalCheckpointSchema,
AgentDispatchRequestSchema,
AgentRunSchema,
AgentSessionSchema,
AgentTaskSchema,
AgentTodoSchema,
} from './agent-runtime.js';
describe('agent runtime contract baseline', () => {
it('validates a dispatched Cowork session with task and approval checkpoint', () => {
const session = AgentSessionSchema.parse({
sessionId: 'sess_cowork_1',
productId: 'cowork',
userId: 'saravana',
status: 'waiting-approval',
startedAt: '2026-04-03T16:00:00.000Z',
updatedAt: '2026-04-03T16:05:00.000Z',
resumable: true,
currentTaskId: 'task_cowork_1',
memoryRefs: ['mem_proj_1'],
artifactRefs: ['art_note_1'],
approvalRefs: ['approval_1'],
dispatchContext: {
originSurface: 'browser',
originProductId: 'notelett',
dispatchMode: 'remote',
initiatedAt: '2026-04-03T15:59:00.000Z',
},
});
const task = AgentTaskSchema.parse({
taskId: 'task_cowork_1',
sessionId: session.sessionId,
title: 'Investigate imported roadmap risks',
intent: 'Audit the imported note and produce findings',
status: 'blocked',
priority: 'high',
createdAt: '2026-04-03T16:00:00.000Z',
updatedAt: '2026-04-03T16:05:00.000Z',
});
const approval = AgentApprovalCheckpointSchema.parse({
approvalId: 'approval_1',
sessionId: session.sessionId,
runId: 'run_cowork_1',
actionLabel: 'Delete temporary export',
riskLevel: 'high',
status: 'requested',
requestedAt: '2026-04-03T16:05:00.000Z',
resolvedAt: null,
resolverSurface: null,
});
expect(session.dispatchContext?.originSurface).toBe('browser');
expect(task.status).toBe('blocked');
expect(approval.status).toBe('requested');
});
it('validates a scheduled FlowMonk run with todos and action logs', () => {
const dispatch = AgentDispatchRequestSchema.parse({
dispatchId: 'dispatch_flow_1',
targetProductId: 'flowmonk',
targetExecutor: 'flowmonk',
userId: 'saravana',
title: 'Execute weekly planning refresh',
intent: 'Rebuild plan, routines, and habits for next week',
artifactRefs: ['art_plan_template_1'],
memoryRefs: ['mem_goal_1'],
dispatchContext: {
originSurface: 'web',
originProductId: 'flowmonk',
dispatchMode: 'scheduled',
initiatedAt: '2026-04-03T17:00:00.000Z',
},
});
const run = AgentRunSchema.parse({
runId: 'run_flow_1',
sessionId: 'sess_flow_1',
productId: 'flowmonk',
status: 'running',
startedAt: '2026-04-03T17:01:00.000Z',
completedAt: null,
checkpointArtifactId: 'art_plan_1',
correlationId: 'corr_phase2',
});
const todo = AgentTodoSchema.parse({
todoId: 'todo_flow_1',
sessionId: 'sess_flow_1',
text: 'Generate routines from approved plan',
status: 'in-progress',
createdAt: '2026-04-03T17:01:30.000Z',
updatedAt: '2026-04-03T17:02:00.000Z',
});
const actionLog = AgentActionLogSchema.parse({
actionLogId: 'alog_flow_1',
sessionId: 'sess_flow_1',
runId: 'run_flow_1',
eventName: 'agent.run.started',
occurredAt: '2026-04-03T17:01:00.000Z',
actorType: 'agent',
correlationId: 'corr_phase2',
payload: {
dispatchId: dispatch.dispatchId,
title: dispatch.title,
},
});
expect(dispatch.dispatchContext.dispatchMode).toBe('scheduled');
expect(run.checkpointArtifactId).toBe('art_plan_1');
expect(todo.status).toBe('in-progress');
expect(actionLog.eventName).toBe('agent.run.started');
});
});

View File

@ -0,0 +1,126 @@
import { z } from 'zod';
export const AgentDispatchContextSchema = z.object({
originSurface: z.enum(['browser', 'mobile', 'desktop', 'web', 'product-api']),
originProductId: z.string().min(1),
dispatchMode: z.enum(['interactive', 'queued', 'scheduled', 'remote']),
initiatedAt: z.string().datetime(),
});
export const AgentSessionStatusSchema = z.enum([
'active',
'paused',
'waiting-approval',
'completed',
'failed',
'cancelled',
]);
export const AgentSessionSchema = z.object({
sessionId: z.string().min(1),
productId: z.string().min(1),
userId: z.string().min(1),
status: AgentSessionStatusSchema,
startedAt: z.string().datetime(),
updatedAt: z.string().datetime(),
resumable: z.boolean(),
currentTaskId: z.string().min(1).nullable().optional(),
memoryRefs: z.array(z.string().min(1)),
artifactRefs: z.array(z.string().min(1)),
approvalRefs: z.array(z.string().min(1)),
dispatchContext: AgentDispatchContextSchema.nullable().optional(),
});
export const AgentTaskStatusSchema = z.enum([
'queued',
'running',
'blocked',
'completed',
'failed',
'cancelled',
]);
export const AgentTaskSchema = z.object({
taskId: z.string().min(1),
sessionId: z.string().min(1),
title: z.string().min(1),
intent: z.string().min(1),
status: AgentTaskStatusSchema,
priority: z.string().min(1).nullable().optional(),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
});
export const AgentTodoStatusSchema = z.enum(['open', 'in-progress', 'done', 'dropped']);
export const AgentTodoSchema = z.object({
todoId: z.string().min(1),
sessionId: z.string().min(1),
text: z.string().min(1),
status: AgentTodoStatusSchema,
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
});
export const AgentRunStatusSchema = z.enum([
'running',
'paused',
'completed',
'failed',
'cancelled',
]);
export const AgentRunSchema = z.object({
runId: z.string().min(1),
sessionId: z.string().min(1),
productId: z.string().min(1),
status: AgentRunStatusSchema,
startedAt: z.string().datetime(),
completedAt: z.string().datetime().nullable().optional(),
checkpointArtifactId: z.string().min(1).nullable().optional(),
correlationId: z.string().min(1).nullable().optional(),
});
export const AgentApprovalCheckpointSchema = z.object({
approvalId: z.string().min(1),
sessionId: z.string().min(1),
runId: z.string().min(1),
actionLabel: z.string().min(1),
riskLevel: z.enum(['low', 'medium', 'high', 'critical']),
status: z.enum(['requested', 'approved', 'denied', 'expired']),
requestedAt: z.string().datetime(),
resolvedAt: z.string().datetime().nullable().optional(),
resolverSurface: z.enum(['mobile', 'web', 'desktop']).nullable().optional(),
});
export const AgentDispatchRequestSchema = z.object({
dispatchId: z.string().min(1),
targetProductId: z.string().min(1),
targetExecutor: z.enum(['cowork', 'jarvisjr', 'flowmonk', 'generic-agent']),
userId: z.string().min(1),
title: z.string().min(1),
intent: z.string().min(1),
artifactRefs: z.array(z.string().min(1)).default([]),
memoryRefs: z.array(z.string().min(1)).default([]),
dispatchContext: AgentDispatchContextSchema,
});
export const AgentActionLogSchema = z.object({
actionLogId: z.string().min(1),
sessionId: z.string().min(1),
runId: z.string().min(1),
eventName: z.string().min(1),
occurredAt: z.string().datetime(),
actorType: z.enum(['user', 'agent', 'system', 'device']),
correlationId: z.string().min(1).nullable().optional(),
payload: z.record(z.unknown()),
});
export type AgentDispatchContext = z.infer<typeof AgentDispatchContextSchema>;
export type AgentSession = z.infer<typeof AgentSessionSchema>;
export type AgentTask = z.infer<typeof AgentTaskSchema>;
export type AgentTodo = z.infer<typeof AgentTodoSchema>;
export type AgentRun = z.infer<typeof AgentRunSchema>;
export type AgentApprovalCheckpoint = z.infer<typeof AgentApprovalCheckpointSchema>;
export type AgentDispatchRequest = z.infer<typeof AgentDispatchRequestSchema>;
export type AgentActionLog = z.infer<typeof AgentActionLogSchema>;

View File

@ -3,6 +3,16 @@ export type { EmitResult, EmitError } from './memory.js';
export { DurableEventBus } from './durable.js';
export type { DurableEventBusOptions } from './durable.js';
export { PlatformEventSchemas } from './types.js';
export {
AgentActionLogSchema,
AgentApprovalCheckpointSchema,
AgentDispatchContextSchema,
AgentDispatchRequestSchema,
AgentRunSchema,
AgentSessionSchema,
AgentTaskSchema,
AgentTodoSchema,
} from './agent-runtime.js';
export {
ArtifactCreatedBySchema,
ArtifactLineageStepSchema,
@ -34,6 +44,22 @@ export {
ArtifactLinkedEventSchema,
ArtifactLinkedPayloadSchema,
} from './ecosystem.js';
export {
buildTimelineItem,
buildTimelineItems,
TimelineItemSchema,
TimelineVisibilitySchema,
} from './timeline.js';
export type {
AgentActionLog,
AgentApprovalCheckpoint,
AgentDispatchContext,
AgentDispatchRequest,
AgentRun,
AgentSession,
AgentTask,
AgentTodo,
} from './agent-runtime.js';
export type {
PlatformEventName,
PlatformEventPayload,
@ -49,3 +75,4 @@ export type {
Phase1EcosystemEvent,
TranscriptArtifactEnvelope,
} from './ecosystem.js';
export type { TimelineItem } from './timeline.js';

View File

@ -0,0 +1,94 @@
import { describe, expect, it } from 'vitest';
import { buildTimelineItems, TimelineItemSchema } from './timeline.js';
describe('timeline contract baseline', () => {
it('builds unified timeline items across phases 1 to 3', () => {
const items = buildTimelineItems([
{
eventId: 'evt_capture_1',
eventName: 'capture.transcript.created',
occurredAt: '2026-04-03T12:00:00.000Z',
productId: 'lysnrai',
artifactId: 'art_transcript_1',
actor: { actorType: 'user', actorId: 'saravana' },
trace: { correlationId: 'corr_phase1', causationId: null, parentEventId: null },
payload: { durationMs: 42150, transcriptSource: 'microphone' },
},
{
eventId: 'evt_plan_1',
eventName: 'artifact.created',
occurredAt: '2026-04-03T13:00:00.000Z',
productId: 'flowmonk',
artifactId: 'art_plan_1',
actor: { actorType: 'agent', actorId: 'phase2-plan-exporter' },
trace: { correlationId: 'corr_phase2', causationId: null, parentEventId: null },
payload: { artifactType: 'plan', title: 'FlowMonk weekly plan', status: 'draft' },
},
{
eventId: 'evt_trail_1',
eventName: 'artifact.created',
occurredAt: '2026-04-03T14:00:00.000Z',
productId: 'actiontrail',
artifactId: 'art_trail_1',
actor: { actorType: 'agent', actorId: 'phase3-audit-importer' },
trace: {
correlationId: 'corr_phase3',
causationId: 'task_phase3',
parentEventId: 'task_phase3',
},
payload: {
artifactType: 'trail-report',
title: 'Cowork audit report for task task_phase3',
status: 'recorded',
},
},
{
eventId: 'evt_memory_1',
eventName: 'memory.entry.created',
occurredAt: '2026-04-03T14:10:00.000Z',
productId: 'mindlyst',
artifactId: 'art_memory_1',
actor: { actorType: 'agent', actorId: 'phase3-audit-note-importer' },
trace: {
correlationId: 'corr_phase3',
causationId: 'evt_note_linked_1',
parentEventId: 'evt_note_linked_1',
},
payload: {
memoryKind: 'insight',
sourceArtifactIds: ['art_note_1', 'art_trail_1'],
},
},
]);
expect(items.map(item => item.eventName)).toEqual([
'memory.entry.created',
'artifact.created',
'artifact.created',
'capture.transcript.created',
]);
expect(items[0]?.title).toBe('Insight memory proposed');
expect(items[1]?.title).toBe('Cowork audit report for task task_phase3');
expect(items[2]?.summary).toBe('plan status: draft');
expect(items[3]?.summary).toContain('microphone transcript captured');
});
it('exposes a stable timeline item schema', () => {
const item = TimelineItemSchema.parse({
itemId: 'timeline_evt_1',
occurredAt: '2026-04-03T14:10:00.000Z',
eventName: 'memory.entry.created',
productId: 'mindlyst',
title: 'Insight memory proposed',
summary: '2 source artifacts linked',
artifactRefs: ['art_memory_1'],
relatedEventIds: ['evt_note_linked_1'],
actorType: 'agent',
visibility: 'private',
correlationId: 'corr_phase3',
});
expect(item.visibility).toBe('private');
expect(item.relatedEventIds).toHaveLength(1);
});
});

View File

@ -0,0 +1,120 @@
import { z } from 'zod';
import type { EcosystemEvent } from './ecosystem.js';
export const TimelineVisibilitySchema = z.enum(['private', 'org', 'shared', 'local-only']);
export const TimelineItemSchema = z.object({
itemId: z.string().min(1),
occurredAt: z.string().datetime(),
eventName: z.string().min(1),
productId: z.string().min(1),
title: z.string().min(1),
summary: z.string().nullable().optional(),
artifactRefs: z.array(z.string().min(1)),
relatedEventIds: z.array(z.string().min(1)),
actorType: z.enum(['user', 'agent', 'system', 'device']),
visibility: TimelineVisibilitySchema,
correlationId: z.string().min(1).nullable().optional(),
});
export type TimelineItem = z.infer<typeof TimelineItemSchema>;
type EventLike = Pick<
EcosystemEvent,
| 'eventId'
| 'eventName'
| 'occurredAt'
| 'productId'
| 'artifactId'
| 'actor'
| 'trace'
| 'payload'
>;
function titleForEvent(event: EventLike): string {
if (event.eventName === 'capture.transcript.created') {
return 'Transcript captured';
}
if (event.eventName === 'memory.entry.created') {
const kind = typeof event.payload.memoryKind === 'string' ? event.payload.memoryKind : 'memory';
return `${capitalize(kind)} memory proposed`;
}
if (event.eventName === 'artifact.created') {
const type =
typeof event.payload.artifactType === 'string' ? event.payload.artifactType : 'artifact';
const title =
typeof event.payload.title === 'string' && event.payload.title ? event.payload.title : null;
return title ? title : `${capitalize(type)} created`;
}
if (event.eventName === 'artifact.linked') {
const relation = typeof event.payload.relation === 'string' ? event.payload.relation : 'linked';
return `Artifact ${relation}`;
}
return event.eventName;
}
function summaryForEvent(event: EventLike): string | null {
if (event.eventName === 'capture.transcript.created') {
const duration =
typeof event.payload.durationMs === 'number'
? `${event.payload.durationMs}ms`
: 'unknown duration';
const source =
typeof event.payload.transcriptSource === 'string'
? event.payload.transcriptSource
: 'unknown source';
return `${source} transcript captured (${duration})`;
}
if (event.eventName === 'memory.entry.created') {
const sources = Array.isArray(event.payload.sourceArtifactIds)
? event.payload.sourceArtifactIds.length
: 0;
return `${sources} source artifact${sources === 1 ? '' : 's'} linked`;
}
if (event.eventName === 'artifact.created') {
const type =
typeof event.payload.artifactType === 'string' ? event.payload.artifactType : 'artifact';
const status = typeof event.payload.status === 'string' ? event.payload.status : 'created';
return `${type} status: ${status}`;
}
if (event.eventName === 'artifact.linked') {
const target =
typeof event.payload.targetArtifactId === 'string'
? event.payload.targetArtifactId
: 'unknown target';
return `Linked to ${target}`;
}
return null;
}
function relatedEventIdsForEvent(event: EventLike): string[] {
return [event.trace.parentEventId, event.trace.causationId].filter(
(value): value is string => typeof value === 'string' && value.length > 0
);
}
export function buildTimelineItem(event: EventLike): TimelineItem {
return TimelineItemSchema.parse({
itemId: `timeline_${event.eventId}`,
occurredAt: event.occurredAt,
eventName: event.eventName,
productId: event.productId,
title: titleForEvent(event),
summary: summaryForEvent(event),
artifactRefs: [event.artifactId].filter((value): value is string => Boolean(value)),
relatedEventIds: relatedEventIdsForEvent(event),
actorType: event.actor.actorType,
visibility: 'private',
correlationId: event.trace.correlationId ?? null,
});
}
export function buildTimelineItems(events: EventLike[]): TimelineItem[] {
return events
.map(buildTimelineItem)
.sort((left, right) => right.occurredAt.localeCompare(left.occurredAt));
}
function capitalize(value: string): string {
return value.length === 0 ? value : `${value[0]!.toUpperCase()}${value.slice(1)}`;
}