snapkitty
hardware
erlang
File size: 3,288 Bytes
b8a03fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
export interface DesktopFileEntry {
  readonly name: string;
  readonly relativePath: string;
  readonly kind: 'file' | 'directory';
  readonly size: number;
}

export interface DesktopFileSnapshot {
  readonly relativePath: string;
  readonly content: string;
  readonly language: string;
}

export interface DesktopCommandRequest {
  readonly command: string;
}

export interface DesktopCommandChunk {
  readonly runId: string;
  readonly stream: 'stdout' | 'stderr' | 'system';
  readonly text: string;
}

export interface DesktopCommandResult {
  readonly runId: string;
  readonly command: string;
  readonly allowed: boolean;
  readonly exitCode: number | null;
  readonly signal: NodeJS.Signals | null;
  readonly stdout: string;
  readonly stderr: string;
  readonly reason?: string;
  readonly seal?: string;
  readonly trace: ReadonlyArray<{
    readonly phase: string;
    readonly summary: string;
  }>;
}

export type ModelProviderId =
  | 'local'
  | 'ollama'
  | 'anthropic'
  | 'openrouter'
  | 'openai-compatible';

export interface ModelProviderSummary {
  readonly providerId: ModelProviderId;
  readonly label: string;
  readonly model: string;
  readonly baseUrl: string;
  readonly hasApiKey: boolean;
  readonly isActive: boolean;
  readonly updatedAt?: string;
}

export interface ModelProviderUpdate {
  readonly providerId: ModelProviderId;
  readonly model?: string;
  readonly baseUrl?: string;
  readonly apiKey?: string;
  readonly clearApiKey?: boolean;
  readonly setActive?: boolean;
}

export interface DesktopToolSummary {
  readonly name: string;
  readonly description: string;
  readonly inputSchema: Record<string, unknown>;
}

export interface DesktopToolEvent {
  readonly name: string;
  readonly ok: boolean;
  readonly output: string;
}

export interface BobChatMessage {
  readonly role: 'user' | 'bob' | 'tool';
  readonly content: string;
  readonly timestamp: string;
  readonly seal?: string;
  readonly provider?: ModelProviderId;
}

export interface BobChatRequest {
  readonly prompt: string;
  readonly messages: ReadonlyArray<BobChatMessage>;
  readonly toolsEnabled: boolean;
}

export interface BobChatResponse {
  readonly message: BobChatMessage;
  readonly seal: string;
  readonly verdict: string;
  readonly provider: ModelProviderId;
  readonly toolEvents: ReadonlyArray<DesktopToolEvent>;
  readonly trace: ReadonlyArray<{
    readonly phase: string;
    readonly summary: string;
  }>;
}

export interface WorkspaceOverview {
  readonly root: string;
  readonly entries: ReadonlyArray<DesktopFileEntry>;
}

export interface ShadowDesktopApi {
  workspace(): Promise<WorkspaceOverview>;
  list(path?: string): Promise<ReadonlyArray<DesktopFileEntry>>;
  readFile(path: string): Promise<DesktopFileSnapshot>;
  saveFile(path: string, content: string): Promise<DesktopFileSnapshot>;
  runCommand(request: DesktopCommandRequest): Promise<DesktopCommandResult>;
  listModelProviders(): Promise<ReadonlyArray<ModelProviderSummary>>;
  saveModelProvider(update: ModelProviderUpdate): Promise<ReadonlyArray<ModelProviderSummary>>;
  listTools(): Promise<ReadonlyArray<DesktopToolSummary>>;
  bobChat(request: BobChatRequest): Promise<BobChatResponse>;
  onCommandChunk(listener: (chunk: DesktopCommandChunk) => void): () => void;
}