Clean up types (#9057)
Signed-off-by: Douwe Osinga <douwe@squareup.com> Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
@@ -239,7 +239,7 @@ describe("acpNotificationHandler", () => {
|
||||
type: "toolRequest",
|
||||
id: "tool-b",
|
||||
name: "grep",
|
||||
status: "executing",
|
||||
status: "in_progress",
|
||||
});
|
||||
expect(message.content[2]).toMatchObject({
|
||||
type: "toolResponse",
|
||||
|
||||
@@ -65,7 +65,7 @@ describe("ACP tool call status handling", () => {
|
||||
expect(assistant?.content[0]).toMatchObject({
|
||||
type: "toolRequest",
|
||||
id: "tool-1",
|
||||
status: "error",
|
||||
status: "failed",
|
||||
});
|
||||
expect(assistant?.content[1]).toMatchObject({
|
||||
type: "toolResponse",
|
||||
@@ -114,7 +114,7 @@ describe("ACP tool call status handling", () => {
|
||||
expect(message.content[0]).toMatchObject({
|
||||
type: "toolRequest",
|
||||
id: "tool-1",
|
||||
status: "error",
|
||||
status: "failed",
|
||||
});
|
||||
expect(message.content[1]).toMatchObject({
|
||||
type: "toolResponse",
|
||||
|
||||
@@ -7,7 +7,6 @@ import { useChatSessionStore } from "@/features/chat/stores/chatSessionStore";
|
||||
import { getBufferedMessage } from "@/features/chat/hooks/replayBuffer";
|
||||
import type {
|
||||
ToolCallLocation,
|
||||
ToolCallStatus,
|
||||
ToolKind,
|
||||
ToolRequestContent,
|
||||
ToolResponseContent,
|
||||
@@ -51,9 +50,6 @@ interface LivePerf {
|
||||
}
|
||||
const livePerf = new Map<string, LivePerf>();
|
||||
|
||||
const toolCallStatusFromUpdate = (status: string): ToolCallStatus =>
|
||||
status === "failed" ? "error" : "completed";
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||
}
|
||||
@@ -90,7 +86,7 @@ function locationsFromUpdate(
|
||||
|
||||
function toolCallUpdatePatch(
|
||||
update: SessionUpdate,
|
||||
): Partial<ToolRequestContent> {
|
||||
): Pick<Partial<ToolRequestContent>, "toolKind" | "locations"> {
|
||||
const toolKind = toolKindFromUpdate(update);
|
||||
const locations = locationsFromUpdate(update);
|
||||
|
||||
@@ -226,7 +222,7 @@ function handleReplay(sessionId: string, update: SessionUpdate): void {
|
||||
name: update.title,
|
||||
...identity,
|
||||
arguments: rawInputToArguments(update.rawInput),
|
||||
status: "executing",
|
||||
status: "in_progress",
|
||||
...toolCallUpdatePatch(update),
|
||||
startedAt: created ?? Date.now(),
|
||||
...(chainSummary ? { chainSummary } : {}),
|
||||
@@ -276,7 +272,6 @@ function handleReplay(sessionId: string, update: SessionUpdate): void {
|
||||
}
|
||||
}
|
||||
if (update.status === "completed" || update.status === "failed") {
|
||||
const toolCallStatus = toolCallStatusFromUpdate(update.status);
|
||||
const tc = msg.content.find(
|
||||
(c) => c.type === "toolRequest" && c.id === update.toolCallId,
|
||||
);
|
||||
@@ -287,7 +282,7 @@ function handleReplay(sessionId: string, update: SessionUpdate): void {
|
||||
...tc,
|
||||
...identity,
|
||||
...toolCallUpdatePatch(update),
|
||||
status: toolCallStatus,
|
||||
status: update.status,
|
||||
} as ToolRequestContent;
|
||||
}
|
||||
}
|
||||
@@ -356,7 +351,7 @@ function handleLive(sessionId: string, update: SessionUpdate): void {
|
||||
name: update.title,
|
||||
...identity,
|
||||
arguments: rawInputToArguments(update.rawInput),
|
||||
status: "executing",
|
||||
status: "in_progress",
|
||||
...toolCallUpdatePatch(update),
|
||||
startedAt: Date.now(),
|
||||
...(chainSummary ? { chainSummary } : {}),
|
||||
@@ -403,7 +398,7 @@ function handleLive(sessionId: string, update: SessionUpdate): void {
|
||||
}
|
||||
|
||||
if (update.status === "completed" || update.status === "failed") {
|
||||
const toolCallStatus = toolCallStatusFromUpdate(update.status);
|
||||
const { status: resolvedStatus } = update;
|
||||
const ownerMessage = store.messagesBySession[sessionId]?.find(
|
||||
(m) => m.id === messageId,
|
||||
);
|
||||
@@ -425,7 +420,7 @@ function handleLive(sessionId: string, update: SessionUpdate): void {
|
||||
...block,
|
||||
...identity,
|
||||
...toolCallUpdatePatch(update),
|
||||
status: toolCallStatus,
|
||||
status: resolvedStatus,
|
||||
}
|
||||
: block,
|
||||
),
|
||||
|
||||
@@ -59,7 +59,7 @@ export async function listDictationLocalModels(): Promise<
|
||||
> {
|
||||
const client = await getClient();
|
||||
const response = await client.goose.GooseDictationModelsList({});
|
||||
return response.models as unknown as WhisperModelStatus[];
|
||||
return response.models;
|
||||
}
|
||||
|
||||
export async function downloadDictationLocalModel(
|
||||
@@ -76,7 +76,7 @@ export async function getDictationLocalModelDownloadProgress(
|
||||
const response = await client.goose.GooseDictationModelsDownloadProgress({
|
||||
modelId,
|
||||
});
|
||||
return (response.progress ?? null) as DictationDownloadProgress | null;
|
||||
return response.progress ?? null;
|
||||
}
|
||||
|
||||
export async function cancelDictationLocalModelDownload(
|
||||
|
||||
@@ -26,7 +26,9 @@ import type {
|
||||
const textBlock: TextContent = { type: "text", text: "hello" };
|
||||
const imageBlock: ImageContent = {
|
||||
type: "image",
|
||||
source: { type: "url", url: "https://img.png" },
|
||||
data: "",
|
||||
mimeType: "image/png",
|
||||
uri: "https://img.png",
|
||||
};
|
||||
const toolRequestBlock: ToolRequestContent = {
|
||||
type: "toolRequest",
|
||||
|
||||
@@ -3,24 +3,6 @@
|
||||
// a narrow union.
|
||||
export type ProviderType = string;
|
||||
|
||||
export interface ProviderConfig {
|
||||
type: ProviderType;
|
||||
name: string;
|
||||
description?: string;
|
||||
models: ModelInfo[];
|
||||
requiresApiKey: boolean;
|
||||
apiKeyEnvVar?: string;
|
||||
}
|
||||
|
||||
export interface ModelInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
contextWindow: number;
|
||||
supportsTools: boolean;
|
||||
supportsVision: boolean;
|
||||
supportsThinking: boolean;
|
||||
}
|
||||
|
||||
// Avatar type — either a remote URL or a local file in ~/.goose/avatars/
|
||||
export type Avatar =
|
||||
| { type: "url"; value: string }
|
||||
@@ -86,4 +68,4 @@ export interface CreateAgentRequest {
|
||||
acpEndpoint?: string;
|
||||
}
|
||||
|
||||
// Session, TokenState, ChatState, and MessageEventType are defined in ./chat.ts
|
||||
// Session, TokenState, and ChatState are defined in ./chat.ts
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import type { Message } from "./messages";
|
||||
import type { Agent } from "./agents";
|
||||
|
||||
// Chat state machine
|
||||
export type ChatState =
|
||||
| "idle"
|
||||
@@ -67,61 +64,3 @@ export interface Session {
|
||||
messageCount: number;
|
||||
userSetName?: boolean;
|
||||
}
|
||||
|
||||
// SSE event types (from goosed server)
|
||||
export type MessageEventType =
|
||||
| "message"
|
||||
| "error"
|
||||
| "finish"
|
||||
| "modelChange"
|
||||
| "notification"
|
||||
| "updateConversation"
|
||||
| "ping";
|
||||
|
||||
export interface MessageEvent {
|
||||
type: "message";
|
||||
message: Message;
|
||||
tokenState: TokenState;
|
||||
}
|
||||
|
||||
export interface ErrorEvent {
|
||||
type: "error";
|
||||
error: string;
|
||||
}
|
||||
|
||||
export interface FinishEvent {
|
||||
type: "finish";
|
||||
reason: string;
|
||||
tokenState: TokenState;
|
||||
}
|
||||
|
||||
export interface ModelChangeEvent {
|
||||
type: "modelChange";
|
||||
model: string;
|
||||
mode: string;
|
||||
}
|
||||
|
||||
export type StreamEvent =
|
||||
| MessageEvent
|
||||
| ErrorEvent
|
||||
| FinishEvent
|
||||
| ModelChangeEvent;
|
||||
|
||||
// Chat request
|
||||
export interface ChatRequest {
|
||||
userMessage: Message;
|
||||
sessionId: string;
|
||||
recipeName?: string;
|
||||
overrideConversation?: Message[];
|
||||
}
|
||||
|
||||
// Active chat context
|
||||
export interface ChatContext {
|
||||
sessionId: string;
|
||||
agent: Agent;
|
||||
messages: Message[];
|
||||
chatState: SessionChatRuntime["chatState"];
|
||||
tokenState: SessionChatRuntime["tokenState"];
|
||||
streamingMessageId: SessionChatRuntime["streamingMessageId"];
|
||||
error: SessionChatRuntime["error"];
|
||||
}
|
||||
|
||||
@@ -1,47 +1,16 @@
|
||||
export type {
|
||||
DictationModelOption,
|
||||
DictationProviderStatusEntry as DictationProviderStatus,
|
||||
DictationTranscribeResponse,
|
||||
DictationLocalModelStatus as WhisperModelStatus,
|
||||
DictationDownloadProgress,
|
||||
} from "@aaif/goose-sdk";
|
||||
|
||||
export type DictationProvider = "openai" | "groq" | "elevenlabs" | "local";
|
||||
|
||||
export interface DictationModelOption {
|
||||
id: string;
|
||||
label: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface DictationProviderStatus {
|
||||
configured: boolean;
|
||||
host?: string | null;
|
||||
description: string;
|
||||
usesProviderConfig: boolean;
|
||||
settingsPath?: string | null;
|
||||
configKey?: string | null;
|
||||
modelConfigKey?: string | null;
|
||||
defaultModel?: string | null;
|
||||
selectedModel?: string | null;
|
||||
availableModels: DictationModelOption[];
|
||||
}
|
||||
|
||||
export interface DictationTranscribeResponse {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export type MicrophonePermissionStatus =
|
||||
| "not_determined"
|
||||
| "authorized"
|
||||
| "denied"
|
||||
| "restricted"
|
||||
| "unsupported";
|
||||
|
||||
export interface WhisperModelStatus {
|
||||
id: string;
|
||||
sizeMb: number;
|
||||
description: string;
|
||||
downloaded: boolean;
|
||||
downloadInProgress: boolean;
|
||||
}
|
||||
|
||||
export interface DictationDownloadProgress {
|
||||
bytesDownloaded: number;
|
||||
totalBytes: number;
|
||||
progressPercent: number;
|
||||
status: string;
|
||||
error?: string | null;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,48 @@ import type {
|
||||
GooseReadResourceResult,
|
||||
GooseToolMetadata,
|
||||
} from "@aaif/goose-sdk";
|
||||
import type {
|
||||
Annotations,
|
||||
ImageContent as AcpImageContent,
|
||||
Role,
|
||||
TextContent as AcpTextContent,
|
||||
ToolCallLocation as AcpToolCallLocation,
|
||||
ToolCallStatus as AcpToolCallStatus,
|
||||
ToolKind,
|
||||
} from "@agentclientprotocol/sdk";
|
||||
|
||||
// ── Wire types (re-exported from ACP SDK) ─────────────────────────────
|
||||
//
|
||||
// These are the exact types that come off the ACP WebSocket. We re-export
|
||||
// them so feature code imports everything from this module. Aliases exist
|
||||
// only for readability — no reshaping, no field-dropping.
|
||||
|
||||
export type { Annotations, Role, ToolKind };
|
||||
export type ToolCallLocation = AcpToolCallLocation;
|
||||
|
||||
/** ACP TextContent with discriminator. */
|
||||
export type TextContent = AcpTextContent & { type: "text" };
|
||||
|
||||
/** ACP ImageContent with discriminator. */
|
||||
export type ImageContent = AcpImageContent & { type: "image" };
|
||||
|
||||
/**
|
||||
* Tool call execution status.
|
||||
*
|
||||
* The four ACP wire values plus `"stopped"`, a renderer-only extension
|
||||
* for user-cancelled tool calls.
|
||||
*/
|
||||
export type ToolCallStatus = AcpToolCallStatus | "stopped";
|
||||
|
||||
// ── Message role ──────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* ACP defines `Role = "user" | "assistant"`. The renderer adds `"system"`
|
||||
* for locally-synthesized notification messages.
|
||||
*/
|
||||
export type MessageRole = Role | "system";
|
||||
|
||||
// ── Composer attachment drafts ────────────────────────────────────────
|
||||
|
||||
export type ChatAttachmentKind = "image" | "file" | "directory";
|
||||
|
||||
@@ -35,55 +77,11 @@ export type ChatAttachmentDraft =
|
||||
| ChatFileAttachmentDraft
|
||||
| ChatDirectoryAttachmentDraft;
|
||||
|
||||
// Message roles
|
||||
export type MessageRole = "user" | "assistant" | "system";
|
||||
|
||||
/** ACP audience restriction — which roles may see a content block. */
|
||||
export type Audience = ("user" | "assistant")[];
|
||||
|
||||
/** ACP content-block annotations (mirrors the SDK's Annotations shape). */
|
||||
export interface ContentAnnotations {
|
||||
audience?: Audience;
|
||||
}
|
||||
|
||||
// Content block types
|
||||
export interface TextContent {
|
||||
type: "text";
|
||||
text: string;
|
||||
annotations?: ContentAnnotations;
|
||||
}
|
||||
|
||||
export interface ImageContent {
|
||||
type: "image";
|
||||
source:
|
||||
| { type: "base64"; mediaType: string; data: string }
|
||||
| { type: "url"; url: string };
|
||||
annotations?: ContentAnnotations;
|
||||
}
|
||||
|
||||
export type ToolCallStatus =
|
||||
| "pending"
|
||||
| "executing"
|
||||
| "completed"
|
||||
| "error"
|
||||
| "stopped";
|
||||
|
||||
export type ToolKind =
|
||||
| "read"
|
||||
| "edit"
|
||||
| "delete"
|
||||
| "move"
|
||||
| "search"
|
||||
| "execute"
|
||||
| "think"
|
||||
| "fetch"
|
||||
| "switch_mode"
|
||||
| "other";
|
||||
|
||||
export interface ToolCallLocation {
|
||||
path: string;
|
||||
line?: number | null;
|
||||
}
|
||||
// ── Renderer-only content block types ─────────────────────────────────
|
||||
//
|
||||
// These types have no ACP equivalent. They are synthesized by the
|
||||
// notification handler from _meta payloads, tool call reductions, or
|
||||
// local UI events.
|
||||
|
||||
export type MessageCompletionStatus =
|
||||
| "inProgress"
|
||||
@@ -92,9 +90,7 @@ export type MessageCompletionStatus =
|
||||
| "stopped";
|
||||
|
||||
export interface ToolChainSummary {
|
||||
/** Lowercase phrase covering the chain's tool calls (e.g. "applied dark mode polish"). */
|
||||
summary: string;
|
||||
/** Number of tool calls the summary covers. */
|
||||
count: number;
|
||||
}
|
||||
|
||||
@@ -107,15 +103,9 @@ export interface ToolRequestContent {
|
||||
arguments: Record<string, unknown>;
|
||||
status: ToolCallStatus;
|
||||
toolKind?: ToolKind;
|
||||
locations?: ToolCallLocation[];
|
||||
/** Epoch ms when the tool call started executing (set on event receipt). */
|
||||
locations?: AcpToolCallLocation[];
|
||||
startedAt?: number;
|
||||
annotations?: ContentAnnotations;
|
||||
/**
|
||||
* Server-generated summary of a multi-tool chain that starts at this tool
|
||||
* call. Only set on the FIRST tool call of a chain (>= 2 tools); the rest of
|
||||
* the chain has this field undefined.
|
||||
*/
|
||||
annotations?: Annotations;
|
||||
chainSummary?: ToolChainSummary;
|
||||
}
|
||||
|
||||
@@ -126,7 +116,7 @@ export interface ToolResponseContent {
|
||||
result: string;
|
||||
structuredContent?: unknown;
|
||||
isError: boolean;
|
||||
annotations?: ContentAnnotations;
|
||||
annotations?: Annotations;
|
||||
}
|
||||
|
||||
export interface McpAppPayload {
|
||||
@@ -155,18 +145,18 @@ export interface McpAppContent {
|
||||
export interface ThinkingContent {
|
||||
type: "thinking";
|
||||
text: string;
|
||||
annotations?: ContentAnnotations;
|
||||
annotations?: Annotations;
|
||||
}
|
||||
|
||||
export interface RedactedThinkingContent {
|
||||
type: "redactedThinking";
|
||||
annotations?: ContentAnnotations;
|
||||
annotations?: Annotations;
|
||||
}
|
||||
|
||||
export interface ReasoningContent {
|
||||
type: "reasoning";
|
||||
text: string;
|
||||
annotations?: ContentAnnotations;
|
||||
annotations?: Annotations;
|
||||
}
|
||||
|
||||
export interface ActionRequiredContent {
|
||||
@@ -177,16 +167,18 @@ export interface ActionRequiredContent {
|
||||
toolName?: string;
|
||||
arguments?: Record<string, unknown>;
|
||||
schema?: Record<string, unknown>;
|
||||
annotations?: ContentAnnotations;
|
||||
annotations?: Annotations;
|
||||
}
|
||||
|
||||
export interface SystemNotificationContent {
|
||||
type: "systemNotification";
|
||||
notificationType: "compaction" | "info" | "warning" | "error";
|
||||
text: string;
|
||||
annotations?: ContentAnnotations;
|
||||
annotations?: Annotations;
|
||||
}
|
||||
|
||||
// ── Message ───────────────────────────────────────────────────────────
|
||||
|
||||
export type MessageContent =
|
||||
| TextContent
|
||||
| ImageContent
|
||||
@@ -217,11 +209,9 @@ export interface MessageMetadata {
|
||||
agentVisible?: boolean;
|
||||
attachments?: MessageAttachment[];
|
||||
chips?: MessageChip[];
|
||||
/** Persona that generated this assistant message (set on send). */
|
||||
personaId?: string;
|
||||
personaName?: string;
|
||||
providerId?: string;
|
||||
/** Which persona this user message is addressed to. */
|
||||
targetPersonaId?: string;
|
||||
targetPersonaName?: string;
|
||||
completionStatus?: MessageCompletionStatus;
|
||||
@@ -235,7 +225,8 @@ export interface Message {
|
||||
metadata?: MessageMetadata;
|
||||
}
|
||||
|
||||
// Type guards for content blocks
|
||||
// ── Type guards ───────────────────────────────────────────────────────
|
||||
|
||||
export function isTextContent(c: MessageContent): c is TextContent {
|
||||
return c.type === "text";
|
||||
}
|
||||
@@ -265,7 +256,8 @@ export function isSystemNotification(
|
||||
return c.type === "systemNotification";
|
||||
}
|
||||
|
||||
// Helpers
|
||||
// ── Helpers ───────────────────────────────────────────────────────────
|
||||
|
||||
export function getTextContent(message: Message): string {
|
||||
return message.content
|
||||
.filter(isTextContent)
|
||||
|
||||
@@ -11,13 +11,7 @@ export type ProviderSetupMethod = ProviderSetupMethodDto;
|
||||
export type ProviderGroup = ProviderSetupGroupDto;
|
||||
export type ProviderField = ProviderSetupFieldDto;
|
||||
|
||||
export interface ProviderFieldValue {
|
||||
key: string;
|
||||
value: string | null;
|
||||
isSet: boolean;
|
||||
isSecret: boolean;
|
||||
required: boolean;
|
||||
}
|
||||
export type { ProviderConfigFieldValueDto as ProviderFieldValue } from "@aaif/goose-sdk";
|
||||
|
||||
export type ProviderCatalogEntry = Omit<
|
||||
ProviderSetupCatalogEntryDto,
|
||||
|
||||
Reference in New Issue
Block a user