135 lines
3.4 KiB
TypeScript
135 lines
3.4 KiB
TypeScript
// The JSON the watch app reads and sends. This is the contract between the gateway and the
|
|
// watch's Codable models (watch/WristCode/API/Models.swift). docs/api.md describes it for humans.
|
|
// Change both sides together.
|
|
|
|
import type { Phase } from "./awareness.ts";
|
|
import type { ApprovalDecision } from "./t3/types.ts";
|
|
import type { HostStatus } from "./t3/host.ts";
|
|
|
|
export interface HostSummary {
|
|
id: string;
|
|
label: string;
|
|
status: HostStatus;
|
|
error: string | null;
|
|
}
|
|
|
|
/** Something a thread is waiting on: an approval, or questions for the user. */
|
|
export interface PendingRequest {
|
|
id: string;
|
|
/** `command`, `file-change`, `permission`, `user_input`, ... */
|
|
kind: string;
|
|
/** What the agent wants to do, such as the command line. Null when the server gave none. */
|
|
prompt: string | null;
|
|
reason: string | null;
|
|
/** Approval choices, in the server's order. Empty for questions. */
|
|
options: Array<{ decision: ApprovalDecision; label: string }>;
|
|
/** Questions for the user. Empty for approvals. */
|
|
questions: Array<{
|
|
id: string;
|
|
header: string;
|
|
question: string;
|
|
options: Array<{ label: string; value: string }>;
|
|
allowCustomAnswer: boolean;
|
|
}>;
|
|
}
|
|
|
|
export interface FeedItem {
|
|
hostId: string;
|
|
hostLabel: string;
|
|
threadId: string;
|
|
projectId: string;
|
|
projectTitle: string;
|
|
title: string;
|
|
phase: Phase;
|
|
updatedAt: string;
|
|
/** The agent's latest message, trimmed for the watch. Null until the gateway has read it. */
|
|
lastMessage: string | null;
|
|
request: PendingRequest | null;
|
|
}
|
|
|
|
export interface Feed {
|
|
/** Waiting for approval or input. Oldest request first. */
|
|
needsYou: FeedItem[];
|
|
/** Starting or running. Most recently updated first. */
|
|
working: FeedItem[];
|
|
/** Completed or failed in the last 24 hours. Most recent first, at most 10. */
|
|
recent: FeedItem[];
|
|
hosts: HostSummary[];
|
|
}
|
|
|
|
export interface Message {
|
|
id: string;
|
|
role: "user" | "assistant" | "system";
|
|
text: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
export interface ThreadDetail {
|
|
item: FeedItem;
|
|
/** Oldest first, at most 20. */
|
|
messages: Message[];
|
|
/** True while a run is active, so Stop makes sense. */
|
|
canStop: boolean;
|
|
}
|
|
|
|
export interface ProjectsResponse {
|
|
hosts: Array<
|
|
HostSummary & {
|
|
projects: Array<{
|
|
id: string;
|
|
title: string;
|
|
/** The model a new thread will use, such as `claude-opus-5-5`. Null when none is configured. */
|
|
model: string | null;
|
|
}>;
|
|
}
|
|
>;
|
|
}
|
|
|
|
export interface PairRequest {
|
|
code: string;
|
|
deviceName: string;
|
|
}
|
|
|
|
export interface PairResponse {
|
|
deviceId: string;
|
|
deviceToken: string;
|
|
}
|
|
|
|
export interface PushRegistration {
|
|
apnsToken: string;
|
|
apnsEnvironment: "sandbox" | "production";
|
|
}
|
|
|
|
export interface SendMessageRequest {
|
|
text: string;
|
|
}
|
|
|
|
export type RespondRequest =
|
|
| { requestId: string; decision: ApprovalDecision }
|
|
| { requestId: string; answers: Record<string, string> };
|
|
|
|
export interface NewThreadRequest {
|
|
hostId: string;
|
|
projectId: string;
|
|
text: string;
|
|
}
|
|
|
|
export interface NewThreadResponse {
|
|
hostId: string;
|
|
threadId: string;
|
|
}
|
|
|
|
export interface ErrorResponse {
|
|
error: string;
|
|
}
|
|
|
|
/** Custom keys on every push notification, beside `aps`. */
|
|
export interface PushPayload {
|
|
hostId: string;
|
|
threadId: string;
|
|
requestId?: string;
|
|
}
|
|
|
|
/** Notification categories the watch registers actions for. */
|
|
export type PushCategory = "approval" | "finished" | "failed" | "input" | "host";
|