Also includes pending workspace changes: unsaved-change guard, keep-alive cache and live message store, knowledge workspace dialogs and perf driver updates.
269 lines
11 KiB
TypeScript
269 lines
11 KiB
TypeScript
import { z } from 'zod'
|
|
import { heartbeatScopeSchema } from './assistant-contracts'
|
|
|
|
export const supervisionTriggerSchema = z.enum(['manual', 'heartbeat'])
|
|
export type SupervisionTrigger = z.infer<typeof supervisionTriggerSchema>
|
|
|
|
export const supervisionTimeRangeSchema = z
|
|
.object({
|
|
from: z.string().datetime({ offset: true }),
|
|
to: z.string().datetime({ offset: true })
|
|
})
|
|
.strict()
|
|
.refine((value) => Date.parse(value.from) <= Date.parse(value.to), {
|
|
message: '监督者时间范围无效'
|
|
})
|
|
|
|
export const supervisionRunRequestSchema = z
|
|
.object({
|
|
trigger: supervisionTriggerSchema,
|
|
scope: heartbeatScopeSchema,
|
|
timeRange: supervisionTimeRangeSchema,
|
|
// Reviews skip processed, unchanged sources by default. Only an explicit
|
|
// user re-analysis reads the whole interval again; it never moves progress.
|
|
reanalyze: z.boolean().optional()
|
|
})
|
|
.strict()
|
|
|
|
export type SupervisionRunRequest = z.infer<typeof supervisionRunRequestSchema>
|
|
|
|
/** Whether a review reads and advances the shared incremental progress. */
|
|
export function isIncrementalReview(request: Pick<SupervisionRunRequest, 'trigger' | 'reanalyze'>): boolean {
|
|
return request.trigger === 'heartbeat' || request.reanalyze !== true
|
|
}
|
|
|
|
export const supervisionSuggestionKindSchema = z.enum(['open_item', 'conflict', 'convention', 'revision', 'stalled', 'experience'])
|
|
export type SupervisionSuggestionKind = z.infer<typeof supervisionSuggestionKindSchema>
|
|
export type SupervisionSuggestion = {
|
|
id: string
|
|
resultId: string | null
|
|
heartbeatRunId: string | null
|
|
scope: SupervisionRunRequest['scope']
|
|
kind: SupervisionSuggestionKind
|
|
title: string
|
|
detail: string
|
|
sourceIds: string[]
|
|
entityId: string | null
|
|
relationId: string | null
|
|
taskId: string | null
|
|
status: 'pending' | 'accepted' | 'dismissed'
|
|
createdAt: string
|
|
/** Story the suggestion is about (stalled story, or where an experience may apply). */
|
|
storyId?: string | null
|
|
experienceId?: string | null
|
|
}
|
|
export const supervisionSuggestionListRequestSchema = z.object({
|
|
status: z.enum(['pending', 'all']).default('pending'),
|
|
limit: z.number().int().min(1).max(100).default(50),
|
|
offset: z.number().int().min(0).max(100_000).default(0)
|
|
}).strict()
|
|
export const supervisionSuggestionActionSchema = z.object({
|
|
id: z.string().uuid(),
|
|
action: z.enum(['accept', 'dismiss'])
|
|
}).strict()
|
|
export type SupervisionSuggestionAction = z.infer<typeof supervisionSuggestionActionSchema>
|
|
export const supervisionSuggestionRetrySchema = z.object({ heartbeatRunId: z.string().min(1).max(256) }).strict()
|
|
|
|
export const supervisionActivityRequestSchema = z.object({
|
|
configId: z.string().min(1).max(256).optional(),
|
|
limit: z.number().int().min(1).max(100).default(50),
|
|
offset: z.number().int().min(0).max(100_000).default(0)
|
|
}).strict()
|
|
export type SupervisionActivityRequest = z.input<typeof supervisionActivityRequestSchema>
|
|
export type SupervisionActivity = {
|
|
id: string
|
|
kind: 'supervision' | 'heartbeat'
|
|
trigger: 'manual' | 'scheduled' | 'heartbeat'
|
|
status: 'running' | 'completed' | 'failed' | 'skipped' | 'no_change' | 'paused' | 'cancelled'
|
|
reviewProgress?: import('./supervision-review-contracts').SupervisionReviewProgress
|
|
scope: SupervisionRunRequest['scope'] | null
|
|
startedAt: string
|
|
completedAt: string | null
|
|
timeRange: SupervisionRunRequest['timeRange'] | null
|
|
error: string | null
|
|
summary: string | null
|
|
resultId: string | null
|
|
heartbeatStatus: 'claimed' | 'completed' | 'failed' | 'skipped' | 'no_change' | null
|
|
supervisionStatus: 'running' | 'completed' | 'failed' | 'no_change' | 'paused' | 'cancelled' | null
|
|
/** Intervention after an automatic review; null when not applicable. */
|
|
suggestionStatus?: 'running' | 'completed' | 'failed' | 'skipped' | null
|
|
suggestionError?: string | null
|
|
suggestionCount?: number
|
|
}
|
|
|
|
export const supervisionEvidenceSchema = z
|
|
.object({
|
|
id: z.string().min(1).max(256),
|
|
sourceType: z.enum(['conversation', 'task', 'note', 'memory', 'knowledge']),
|
|
sourceId: z.string().min(1).max(256),
|
|
title: z.string().max(500),
|
|
content: z.string().max(8_000),
|
|
occurredAt: z.string().datetime({ offset: true }),
|
|
locator: z.record(z.string(), z.unknown()).optional()
|
|
})
|
|
.strict()
|
|
|
|
export type SupervisionEvidence = z.infer<typeof supervisionEvidenceSchema>
|
|
|
|
const sourceReferenceIdsSchema = z.array(z.string().min(1).max(256))
|
|
|
|
export const supervisionEventSchema = z
|
|
.object({
|
|
title: z.string().min(1),
|
|
description: z.string(),
|
|
occurredAt: z.string().datetime({ offset: true }),
|
|
eventType: z.enum(['decision', 'change', 'discussion', 'milestone']),
|
|
entityIds: z.array(z.string().regex(/^[a-zA-Z0-9_-]{1,120}$/)),
|
|
sourceReferenceIds: sourceReferenceIdsSchema
|
|
})
|
|
.strict()
|
|
|
|
export const supervisionEntitySchema = z
|
|
.object({
|
|
id: z.string().regex(/^[a-zA-Z0-9_-]{1,120}$/),
|
|
persistedId: z.string().uuid().optional(),
|
|
label: z.string().min(1),
|
|
description: z.string(),
|
|
sourceReferenceIds: sourceReferenceIdsSchema
|
|
})
|
|
.strict()
|
|
|
|
export const supervisionRelationSchema = z
|
|
.object({
|
|
fromEntityId: z.string().regex(/^[a-zA-Z0-9_-]{1,120}$/),
|
|
toEntityId: z.string().regex(/^[a-zA-Z0-9_-]{1,120}$/),
|
|
relationType: z.enum(['supports', 'depends-on', 'contrasts', 'related']),
|
|
reason: z.string(),
|
|
sourceReferenceIds: sourceReferenceIdsSchema
|
|
})
|
|
.strict()
|
|
|
|
export const supervisionEntityChangeSchema = z.object({
|
|
entityId: z.string().regex(/^[a-zA-Z0-9_-]{1,120}$/),
|
|
changeType: z.enum(['proposed', 'added', 'verified', 'revised']),
|
|
description: z.string(),
|
|
sourceReferenceIds: sourceReferenceIdsSchema
|
|
}).strict()
|
|
|
|
export const supervisionSummaryOutputSchema = z
|
|
.object({
|
|
summary: z.string().min(1),
|
|
changeDigest: z.string(),
|
|
openItems: z.array(z.string().min(1)),
|
|
events: z.array(supervisionEventSchema),
|
|
entities: z.array(supervisionEntitySchema),
|
|
entityChanges: z.array(supervisionEntityChangeSchema),
|
|
relations: z.array(supervisionRelationSchema)
|
|
})
|
|
.strict()
|
|
|
|
export type SupervisionSummaryOutput = z.infer<
|
|
typeof supervisionSummaryOutputSchema
|
|
>
|
|
|
|
// Navigation combines saved summaries; it cannot create or replace leaf facts.
|
|
export const supervisionNavigationOutputSchema = supervisionSummaryOutputSchema.pick({
|
|
summary: true, changeDigest: true, openItems: true
|
|
}).extend({
|
|
events: z.array(z.never()).max(0).optional(),
|
|
entities: z.array(z.never()).max(0).optional(),
|
|
entityChanges: z.array(z.never()).max(0).optional(),
|
|
relations: z.array(z.never()).max(0).optional()
|
|
}).strict()
|
|
|
|
export const supervisionEntityActionSchema = z
|
|
.object({
|
|
resultId: z.string().min(1).optional(),
|
|
entityId: z.string().regex(/^[a-zA-Z0-9_-]{1,120}$/),
|
|
action: z.enum(['confirm', 'revise', 'revoke']),
|
|
label: z.string().trim().min(1).optional(),
|
|
description: z.string().optional()
|
|
})
|
|
.strict()
|
|
|
|
export const supervisionRelationActionSchema = z
|
|
.object({
|
|
resultId: z.string().min(1).optional(),
|
|
relationId: z.string().uuid(),
|
|
action: z.enum(['confirm', 'revoke'])
|
|
})
|
|
.strict()
|
|
|
|
export const supervisionSourceRequestSchema = z
|
|
.object({ sourceId: z.string().min(1).max(256) })
|
|
.strict()
|
|
|
|
export const supervisionContinueContextRequestSchema = z.object({
|
|
sourceId: z.string().min(1).max(256),
|
|
resultId: z.string().min(1).max(256)
|
|
}).strict()
|
|
export type SupervisionContinueContextRequest = z.infer<typeof supervisionContinueContextRequestSchema>
|
|
|
|
export const supervisionContinueRequestSchema = z.object({
|
|
conversationId: z.string().min(1).max(128),
|
|
prompt: z.string().trim().min(1).max(12_000),
|
|
runtimeSelection: z.unknown().optional(),
|
|
projectId: z.string().min(1).max(128).optional()
|
|
}).strict()
|
|
export type SupervisionContinueRequest = z.infer<typeof supervisionContinueRequestSchema>
|
|
|
|
export const supervisionKnowledgePreviewRequestSchema = z.object({
|
|
operation: z.enum(['create-entity', 'update-entity']),
|
|
libraryId: z.string().uuid(),
|
|
entityId: z.string().uuid().optional(),
|
|
label: z.string().trim().min(1).max(120),
|
|
type: z.string().trim().min(1).max(120),
|
|
description: z.string().trim().max(2_000),
|
|
aliases: z.array(z.string().trim().min(1).max(120)).max(50),
|
|
sourceId: z.string().min(1).max(256)
|
|
}).strict().superRefine((value, context) => {
|
|
if (value.operation === 'update-entity' && !value.entityId) {
|
|
context.addIssue({ code: 'custom', path: ['entityId'], message: 'update-entity requires entityId' })
|
|
}
|
|
})
|
|
export type SupervisionKnowledgePreviewRequest = z.infer<typeof supervisionKnowledgePreviewRequestSchema>
|
|
|
|
export const supervisionKnowledgeCommitRequestSchema = z.object({
|
|
previewId: z.string().uuid()
|
|
}).strict()
|
|
export type SupervisionKnowledgeCommitRequest = z.infer<typeof supervisionKnowledgeCommitRequestSchema>
|
|
|
|
export type SupervisionEntityAction = z.infer<typeof supervisionEntityActionSchema>
|
|
export type SupervisionRelationAction = z.infer<typeof supervisionRelationActionSchema>
|
|
|
|
export const supervisionResultViewSchema = z.object({
|
|
runId: z.string().optional(),
|
|
coverage: z.record(z.string(), z.unknown()).optional(),
|
|
storyLineId: z.string(),
|
|
sourceId: z.string().nullable(),
|
|
id: z.string(), summary: z.string(), changeDigest: z.string(), createdAt: z.string(),
|
|
scope: heartbeatScopeSchema, timeRange: supervisionTimeRangeSchema,
|
|
openItems: z.array(z.string())
|
|
})
|
|
export type SupervisionResultView = z.infer<typeof supervisionResultViewSchema>
|
|
|
|
export const supervisionTargetSchema = z.discriminatedUnion('type', [
|
|
z.object({ type: z.literal('conversation'), conversationId: z.string().min(1).max(128) }).strict(),
|
|
z.object({ type: z.literal('task'), taskId: z.string().min(1).max(128) }).strict()
|
|
])
|
|
export type SupervisionTarget = z.infer<typeof supervisionTargetSchema>
|
|
export const supervisionOverviewRequestSchema = z.object({ target: supervisionTargetSchema.optional(), resultId: z.string().min(1).max(256).optional() }).strict()
|
|
export const supervisionGraphRequestSchema = z.object({
|
|
resultId: z.string().min(1).optional(), storyLineId: z.string().min(1).optional()
|
|
}).strict()
|
|
export type SupervisionGraphRequest = z.infer<typeof supervisionGraphRequestSchema>
|
|
|
|
export const supervisionGraphViewSchema = z.object({
|
|
storyLine: z.object({ id: z.string(), scope_json: z.string() }).nullable(),
|
|
events: z.array(z.object({ id: z.string(), title: z.string(), description: z.string(), occurred_at: z.string(),
|
|
project_id: z.string().nullish(), started_at: z.string().nullish(), ended_at: z.string().nullish() })),
|
|
entities: z.array(z.object({ id: z.string(), canonical_label: z.string(), description: z.string(), confirmation_state: z.string() })),
|
|
relations: z.array(z.object({ id: z.string(), from_entity_id: z.string(), to_entity_id: z.string(), relation_type: z.string(), reason: z.string(), confirmation_state: z.string() })),
|
|
sources: z.array(z.object({ id: z.string(), title: z.string(), occurred_at: z.string() })),
|
|
eventEntities: z.array(z.object({ event_id: z.string(), entity_id: z.string() })),
|
|
eventSources: z.array(z.object({ event_id: z.string(), source_id: z.string() })),
|
|
attention: z.array(z.object({ start: z.string(), turns: z.number(), characters: z.number() })).optional()
|
|
})
|
|
export type SupervisionAttentionSlot = { start: string; turns: number; characters: number }
|
|
export type SupervisionGraphView = z.infer<typeof supervisionGraphViewSchema>
|