import { z } from 'zod'; export const EcosystemArtifactTypeSchema = z.enum([ 'transcript', 'note', 'memory', 'plan', 'routine', 'habit', 'habit-checkin', 'trail-report', 'route-session', 'agent-output', 'document', 'digest', ]); export const ArtifactLinkRelationSchema = z.enum([ 'derived-from', 'summarizes', 'generated-task', 'generated-routine', 'generated-habit', 'generated-memory', 'evidence-for', 'review-of', 'attached-to', ]); export const ArtifactLinkSchema = z.object({ relation: ArtifactLinkRelationSchema, targetArtifactId: z.string().min(1), }); export const ArtifactCreatedBySchema = z.object({ actorType: z.enum(['user', 'agent', 'system', 'mixed']), actorId: z.string().min(1).nullable(), }); export const ArtifactOwnershipSchema = z.object({ userId: z.string().min(1), orgId: z.string().min(1).nullable().optional(), }); export const ArtifactVisibilitySchema = z.object({ scope: z.enum(['private', 'org', 'shared', 'local-only']), allowedProducts: z.array(z.string().min(1)).optional(), }); export const ArtifactLineageStepSchema = z.object({ stepType: z.string().min(1), productId: z.string().min(1), actorType: z.enum(['user', 'agent', 'system']), timestamp: z.string().datetime(), }); export const ArtifactProvenanceSchema = z.object({ originProductId: z.string().min(1), originActionId: z.string().min(1).nullable().optional(), sessionId: z.string().min(1).nullable().optional(), runId: z.string().min(1).nullable().optional(), approvalId: z.string().min(1).nullable().optional(), correlationId: z.string().min(1).nullable().optional(), lineage: z.array(ArtifactLineageStepSchema).min(1), }); export const BaseArtifactEnvelopeSchema = z.object({ id: z.string().min(1), artifactType: EcosystemArtifactTypeSchema, schemaVersion: z.literal(1), productId: z.string().min(1), sourceSurface: z.string().min(1), title: z.string().min(1).nullable(), summary: z.string().min(1).nullable(), createdAt: z.string().datetime(), updatedAt: z.string().datetime(), createdBy: ArtifactCreatedBySchema, ownership: ArtifactOwnershipSchema, visibility: ArtifactVisibilitySchema, status: z.string().min(1), tags: z.array(z.string().min(1)), links: z.array(ArtifactLinkSchema), provenance: ArtifactProvenanceSchema, payload: z.record(z.unknown()), }); export const TranscriptPayloadSchema = z.object({ transcriptText: z.string().min(1), transcriptSource: z.enum(['microphone', 'upload', 'call', 'browser', 'other']), language: z.string().min(1), durationMs: z.number().int().nonnegative(), segments: z .array( z.object({ speaker: z.string().min(1).nullable().optional(), startedAtMs: z.number().int().nonnegative(), endedAtMs: z.number().int().nonnegative(), text: z.string().min(1), }) ) .default([]), }); export const NotePayloadSchema = z.object({ noteFormat: z.enum(['markdown', 'plain-text', 'rich-text']), body: z.string().min(1), excerpt: z.string().min(1).nullable().optional(), }); export const MemoryPayloadSchema = z.object({ memoryKind: z.enum(['fact', 'preference', 'person', 'project', 'insight', 'todo']), text: z.string().min(1), confidence: z.number().min(0).max(1), sourceArtifactIds: z.array(z.string().min(1)).min(1), reviewState: z.enum(['proposed', 'accepted', 'rejected']), }); export const PlanPayloadSchema = z.object({ weekOf: z.string().min(1), taskCount: z.number().int().nonnegative(), scheduledEntryCount: z.number().int().nonnegative(), totalScheduledMinutes: z.number().int().nonnegative(), entries: z.array( z.object({ taskTitle: z.string().min(1), scheduledDate: z.string().min(1), startTime: z.string().min(1), endTime: z.string().min(1), durationMinutes: z.number().int().nonnegative(), flowName: z.string().min(1).nullable(), zoneName: z.string().min(1).nullable(), priority: z.string().min(1), }) ), }); export const RoutinePayloadSchema = z.object({ routineId: z.string().min(1), stepCount: z.number().int().nonnegative(), totalDurationMinutes: z.number().nonnegative(), status: z.string().min(1), isTemplate: z.boolean(), category: z.string().min(1).nullable().optional(), steps: z.array( z.object({ label: z.string().min(1), durationMinutes: z.number().nonnegative(), transition: z.string().min(1), status: z.string().min(1), }) ), }); export const HabitPayloadSchema = z.object({ habitId: z.string().min(1), identityId: z.string().min(1), frequency: z.enum(['daily', 'weekly', 'custom']), customDays: z.array(z.number().int().min(0).max(6)).optional(), targetCount: z.number().int().positive(), reminderTime: z.string().min(1).nullable().optional(), isActive: z.boolean(), sourceRoutineId: z.string().min(1), }); export const TrailReportPayloadSchema = z.object({ sourceProduct: z.literal('claw-cowork'), sourceTaskId: z.string().min(1).nullable().optional(), generatedFrom: z.enum(['audit-export-json', 'audit-query-json']), reportGeneratedAt: z.string().datetime(), actionCount: z.number().int().nonnegative(), toolCallCount: z.number().int().nonnegative(), approvalCount: z.number().int().nonnegative(), failureCount: z.number().int().nonnegative(), safetySignalCount: z.number().int().nonnegative(), tasks: z.array(z.string().min(1)), actionBreakdown: z.array( z.object({ action: z.string().min(1), count: z.number().int().positive(), }) ), entries: z.array( z.object({ timestamp: z.string().datetime(), taskId: z.string().min(1).nullable(), action: z.string().min(1), tool: z.string().min(1).nullable().optional(), result: z.string().min(1).nullable().optional(), approval: z.string().min(1).nullable().optional(), inputSummary: z.string().min(1).nullable().optional(), metadata: z.record(z.unknown()).nullable().optional(), }) ), }); export const TranscriptArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({ artifactType: z.literal('transcript'), payload: TranscriptPayloadSchema, }); export const NoteArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({ artifactType: z.literal('note'), payload: NotePayloadSchema, }); export const MemoryArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({ artifactType: z.literal('memory'), payload: MemoryPayloadSchema, }); export const PlanArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({ artifactType: z.literal('plan'), payload: PlanPayloadSchema, }); export const RoutineArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({ artifactType: z.literal('routine'), payload: RoutinePayloadSchema, }); export const HabitArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({ artifactType: z.literal('habit'), payload: HabitPayloadSchema, }); export const TrailReportArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({ artifactType: z.literal('trail-report'), payload: TrailReportPayloadSchema, }); export const Phase1ArtifactEnvelopeSchema = z.discriminatedUnion('artifactType', [ TranscriptArtifactEnvelopeSchema, NoteArtifactEnvelopeSchema, MemoryArtifactEnvelopeSchema, ]); export const EcosystemEventActorSchema = z.object({ actorType: z.enum(['user', 'agent', 'system', 'device']), actorId: z.string().min(1).nullable().optional(), }); export const EcosystemEventTraceSchema = z.object({ correlationId: z.string().min(1).nullable(), causationId: z.string().min(1).nullable(), parentEventId: z.string().min(1).nullable(), }); export const BaseEcosystemEventSchema = z.object({ eventId: z.string().min(1), eventName: z.string().min(1), eventVersion: z.literal(1), occurredAt: z.string().datetime(), productId: z.string().min(1), sourceSurface: z.string().min(1), userId: z.string().min(1).nullable().optional(), orgId: z.string().min(1).nullable().optional(), sessionId: z.string().min(1).nullable().optional(), runId: z.string().min(1).nullable().optional(), artifactId: z.string().min(1).nullable().optional(), actor: EcosystemEventActorSchema, trace: EcosystemEventTraceSchema, payload: z.record(z.unknown()), }); export const CaptureTranscriptCreatedPayloadSchema = z.object({ artifactId: z.string().min(1), durationMs: z.number().int().nonnegative(), language: z.string().min(1), transcriptSource: z.enum(['microphone', 'upload', 'call', 'browser', 'other']), }); export const ArtifactCreatedPayloadSchema = z.object({ artifactType: z.enum([ 'transcript', 'note', 'memory', 'plan', 'routine', 'habit', 'trail-report', ]), title: z.string().min(1).nullable(), status: z.string().min(1), }); export const ArtifactLinkedPayloadSchema = z.object({ sourceArtifactId: z.string().min(1), targetArtifactId: z.string().min(1), relation: z.enum([ 'summarizes', 'generated-memory', 'generated-routine', 'generated-habit', 'derived-from', ]), }); export const MemoryEntryCreatedPayloadSchema = z.object({ artifactId: z.string().min(1), memoryKind: MemoryPayloadSchema.shape.memoryKind, reviewState: MemoryPayloadSchema.shape.reviewState, confidence: MemoryPayloadSchema.shape.confidence, sourceArtifactIds: z.array(z.string().min(1)).min(1), }); export const CaptureTranscriptCreatedEventSchema = BaseEcosystemEventSchema.extend({ eventName: z.literal('capture.transcript.created'), payload: CaptureTranscriptCreatedPayloadSchema, }); export const ArtifactCreatedEventSchema = BaseEcosystemEventSchema.extend({ eventName: z.literal('artifact.created'), payload: ArtifactCreatedPayloadSchema, }); export const ArtifactLinkedEventSchema = BaseEcosystemEventSchema.extend({ eventName: z.literal('artifact.linked'), payload: ArtifactLinkedPayloadSchema, }); export const MemoryEntryCreatedEventSchema = BaseEcosystemEventSchema.extend({ eventName: z.literal('memory.entry.created'), payload: MemoryEntryCreatedPayloadSchema, }); export const Phase1EcosystemEventSchema = z.discriminatedUnion('eventName', [ CaptureTranscriptCreatedEventSchema, ArtifactCreatedEventSchema, ArtifactLinkedEventSchema, MemoryEntryCreatedEventSchema, ]); export const Phase1EcosystemEventSchemas = { 'capture.transcript.created': CaptureTranscriptCreatedEventSchema, 'artifact.created': ArtifactCreatedEventSchema, 'artifact.linked': ArtifactLinkedEventSchema, 'memory.entry.created': MemoryEntryCreatedEventSchema, } as const; export type ArtifactEnvelope = z.infer; export type TranscriptArtifactEnvelope = z.infer; export type NoteArtifactEnvelope = z.infer; export type MemoryArtifactEnvelope = z.infer; export type PlanArtifactEnvelope = z.infer; export type RoutineArtifactEnvelope = z.infer; export type HabitArtifactEnvelope = z.infer; export type Phase1ArtifactEnvelope = z.infer; export type EcosystemEvent = z.infer; export type Phase1EcosystemEvent = z.infer;