Files
makelore/electron/coding-runtime/contracts.ts

363 lines
8.9 KiB
TypeScript

export type ConversationThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high';
export interface ProductModelRef {
accountId: string;
modelId: string;
thinkingLevel: ConversationThinkingLevel;
}
export interface ConversationModelState {
model: ProductModelRef | null;
modelResolution: 'resolved' | 'required';
}
export interface PublicUsage {
inputTokens: number;
outputTokens: number;
cacheReadTokens?: number;
cacheWriteTokens?: number;
}
export type CodingRuntimeErrorCode =
| 'CODING_RUNTIME_START_FAILED'
| 'CODING_RUNTIME_READY_TIMEOUT'
| 'CODING_RUNTIME_PROTOCOL_ERROR'
| 'CODING_PROVIDER_AUTH_REQUIRED'
| 'CODING_MODEL_UNAVAILABLE'
| 'CODING_SESSION_UNREADABLE'
| 'CODING_STORAGE_WRITE_FAILED'
| 'CODING_REQUEST_UNCERTAIN'
| 'CODING_MIGRATION_MODEL_REQUIRED'
| 'CODING_CONVERSATION_NOT_FOUND';
export interface CodingRuntimePublicError {
code: CodingRuntimeErrorCode;
message: string;
recoverable: boolean;
}
export type ConversationRunStatus =
| 'idle'
| 'preparing'
| 'queued'
| 'running'
| 'retrying'
| 'compacting'
| 'aborting'
| 'error';
export type PromptMode = 'prompt' | 'steer' | 'follow-up';
export interface ConversationRunState {
status: ConversationRunStatus;
runId?: string;
mode?: PromptMode;
startedAt?: number;
settledAt?: number;
terminalReason?: 'completed' | 'aborted' | 'failed';
retry?: {
attempt: number;
delayMs: number;
};
error?: CodingRuntimePublicError;
}
export interface ConversationQueueItem {
id: string;
clientRequestId: string;
mode: 'steer' | 'follow-up';
text: string;
attachmentIds: string[];
}
export interface ConversationQueueState {
items: ConversationQueueItem[];
}
export interface ConversationContextState {
usedTokens: number;
contextWindow: number;
outputLimit?: number;
compaction: 'idle' | 'running';
lastCompactionId?: string;
}
export interface ConversationInteractionOption {
id: string;
label: string;
description?: string;
}
export interface ConversationInteraction {
id: string;
conversationId: string;
runId: string;
kind: 'select' | 'confirm' | 'input' | 'editor';
title: string;
message?: string;
options?: ConversationInteractionOption[];
status: 'pending' | 'answered' | 'rejected' | 'cancelled';
}
export interface PublicWorkerState {
status: 'stopped' | 'starting' | 'ready' | 'recovering' | 'error';
generation: number;
error?: CodingRuntimePublicError;
}
export type ConversationContentBlock =
| {
kind: 'text';
id: string;
text: string;
status: 'streaming' | 'complete';
}
| {
kind: 'thinking';
id: string;
text: string;
status: 'streaming' | 'complete';
}
| {
kind: 'image';
id: string;
attachmentId: string;
mime: string;
};
export interface ConversationMessageNode {
kind: 'message';
id: string;
sourceEntryId?: string;
clientRequestId?: string;
role: 'user' | 'assistant';
status: 'optimistic' | 'streaming' | 'complete' | 'error' | 'aborted';
blocks: ConversationContentBlock[];
usage?: PublicUsage;
stopReason?: 'stop' | 'length' | 'tool-use' | 'error' | 'aborted';
}
export interface ChangedFileDetailsV1 {
schema: 'changed-file.v1';
paths: string[];
}
export interface TaskStateDetailsV1 {
schema: 'task-state.v1';
tasks: Array<{
id: string;
title: string;
status: 'pending' | 'running' | 'complete' | 'error';
}>;
}
export interface WriteLeaseDetailsV1 {
schema: 'write-lease.v1';
status: 'waiting' | 'held' | 'released';
}
export interface SubagentDetailsV1 {
schema: 'subagent.v1';
dispatchId: string;
mode: 'single' | 'parallel' | 'chain';
tasks: Array<{
taskId: string;
agentId: string;
toolProfile: 'read-only' | 'coding';
status: 'queued' | 'running' | 'complete' | 'error' | 'aborted' | 'skipped';
summary?: string;
errorCode?: string;
usage?: PublicUsage;
}>;
}
export type KnownToolDetails =
| ChangedFileDetailsV1
| TaskStateDetailsV1
| WriteLeaseDetailsV1
| SubagentDetailsV1;
export interface ConversationToolNode {
kind: 'tool';
id: string;
toolCallId: string;
toolName: string;
title: string;
inputText: string;
status: 'declared' | 'waiting' | 'running' | 'complete' | 'error' | 'aborted';
output: ConversationContentBlock[];
details?: KnownToolDetails;
}
export interface ConversationCompactionNode {
kind: 'compaction';
id: string;
runId: string;
source: 'manual' | 'automatic';
status: 'running' | 'complete' | 'error';
willRetry: boolean;
summary?: string;
}
export interface ConversationBoundaryNode {
kind: 'boundary';
id: string;
runId: string;
boundary: 'turn-start' | 'turn-end' | 'retry';
attempt?: number;
delayMs?: number;
}
export interface ConversationSubagentNode {
kind: 'subagent';
id: string;
runId: string;
details: SubagentDetailsV1;
}
export interface ConversationNoticeNode {
kind: 'notice';
id: string;
code: string;
level: 'info' | 'warning' | 'error';
message: string;
}
export type ConversationNode =
| ConversationMessageNode
| ConversationToolNode
| ConversationCompactionNode
| ConversationBoundaryNode
| ConversationSubagentNode
| ConversationNoticeNode;
export interface ConversationSnapshot {
schemaVersion: 1;
conversation: {
id: string;
projectId: string;
agentId: string;
title: string;
model: ConversationModelState;
};
nodes: ConversationNode[];
run: ConversationRunState;
queue: ConversationQueueState;
context: ConversationContextState;
pendingInteractions: ConversationInteraction[];
worker: PublicWorkerState;
cursor: {
workerGeneration: number;
seq: number;
leafEntryId?: string;
};
}
export type ConversationPatch =
| { op: 'worker.state'; state: PublicWorkerState }
| { op: 'run.state'; run: ConversationRunState }
| { op: 'message.upsert'; node: ConversationMessageNode }
| { op: 'message.block-delta'; messageId: string; blockId: string; delta: string }
| { op: 'tool.upsert'; node: ConversationToolNode }
| { op: 'compaction.upsert'; node: ConversationCompactionNode }
| { op: 'subagent.upsert'; node: ConversationSubagentNode }
| { op: 'queue.replace'; queue: ConversationQueueState }
| { op: 'interaction.upsert'; interaction: ConversationInteraction }
| { op: 'interaction.remove'; interactionId: string }
| { op: 'context.replace'; context: ConversationContextState }
| { op: 'snapshot.invalidated'; reason: string };
export interface ConversationPatchEnvelope {
conversationId: string;
workerGeneration: number;
runId?: string;
seq: number;
at: number;
patch: ConversationPatch;
}
export interface PrepareConversationInput {
conversationId: string;
projectId: string;
agentId: string;
title: string;
model: ConversationModelState;
}
export interface ConversationRuntimeState {
conversationId: string;
status: PublicWorkerState['status'];
workerGeneration: number;
error?: CodingRuntimePublicError;
}
export interface PromptConversationInput {
clientRequestId: string;
conversationId: string;
mode: PromptMode;
text: string;
attachments: Array<{ attachmentId: string }>;
}
export interface QueueMessageInput {
clientRequestId: string;
conversationId: string;
text: string;
attachments: Array<{ attachmentId: string }>;
}
export interface PromptAcceptance {
accepted: true;
conversationId: string;
clientRequestId: string;
runId: string;
mode: PromptMode;
queuePosition?: number;
}
export interface QueueAcceptance {
accepted: true;
conversationId: string;
clientRequestId: string;
mode: 'steer' | 'follow-up';
queuePosition: number;
}
export interface SetConversationModelInput {
conversationId: string;
accountId: string;
modelId: string;
}
export interface SetThinkingLevelInput {
conversationId: string;
thinkingLevel: ConversationThinkingLevel;
}
export interface ForkConversationInput {
sourceConversationId: string;
sourceEntryId?: string;
conversation: PrepareConversationInput;
}
export interface ForkResult {
conversationId: string;
snapshot: ConversationSnapshot;
}
export interface CodingConversationRuntime {
prepare(input: PrepareConversationInput): Promise<ConversationRuntimeState>;
getSnapshot(conversationId: string): Promise<ConversationSnapshot>;
prompt(input: PromptConversationInput): Promise<PromptAcceptance>;
steer(input: QueueMessageInput): Promise<QueueAcceptance>;
followUp(input: QueueMessageInput): Promise<QueueAcceptance>;
abort(conversationId: string): Promise<void>;
setModel(input: SetConversationModelInput): Promise<ConversationModelState>;
setThinking(input: SetThinkingLevelInput): Promise<ConversationModelState>;
compact(conversationId: string): Promise<void>;
fork(input: ForkConversationInput): Promise<ForkResult>;
recover(conversationId: string): Promise<ConversationRuntimeState>;
dispose(conversationId: string): Promise<void>;
subscribe(listener: (patch: ConversationPatchEnvelope) => void): () => void;
}