@zhanguym/chatroom 1.0.0 → 1.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/dist/app/application.d.ts +0 -1
  2. package/dist/app/application.js +8 -7
  3. package/dist/app/event-bus.d.ts +13 -10
  4. package/dist/app/external-access-registry.d.ts +1 -0
  5. package/dist/app/external-access-registry.js +3 -0
  6. package/dist/app/git-access.d.ts +50 -0
  7. package/dist/app/git-access.js +2 -0
  8. package/dist/app/service-registry.d.ts +11 -0
  9. package/dist/app/service-registry.js +17 -0
  10. package/dist/app/workspace-access.d.ts +24 -0
  11. package/dist/app/workspace-access.js +2 -0
  12. package/dist/auth/ingress-policy.d.ts +2 -0
  13. package/dist/auth/ingress-policy.js +14 -2
  14. package/dist/auth/passkey-service.js +1 -1
  15. package/dist/cli/run-cli.js +1 -1
  16. package/dist/core/fs/safe-directory.d.ts +9 -0
  17. package/dist/core/fs/safe-directory.js +129 -0
  18. package/dist/core/operations/repository.d.ts +2 -0
  19. package/dist/core/runtime/line-process.d.ts +19 -0
  20. package/dist/core/runtime/line-process.js +51 -0
  21. package/dist/infrastructure/database/operation-repository.js +8 -2
  22. package/dist/infrastructure/database/schema.d.ts +1 -1
  23. package/dist/infrastructure/database/schema.js +62 -0
  24. package/dist/infrastructure/http/http-server.js +1 -1
  25. package/dist/infrastructure/logging/system-log.js +2 -1
  26. package/dist/native/linux/chatroom-computer-helper +0 -0
  27. package/dist/native/macos/ChatRoomComputerHelper.app/Contents/MacOS/chatroom-computer-helper +0 -0
  28. package/dist/native/windows/chatroom-computer-helper.exe +0 -0
  29. package/dist/operations/operation-log.js +16 -4
  30. package/dist/plugins/agent/async-queue.d.ts +10 -0
  31. package/dist/plugins/agent/async-queue.js +49 -0
  32. package/dist/plugins/agent/mcp.d.ts +3 -0
  33. package/dist/plugins/agent/mcp.js +502 -0
  34. package/dist/plugins/agent/plugin.d.ts +4 -0
  35. package/dist/plugins/agent/plugin.js +35 -0
  36. package/dist/plugins/agent/provider.d.ts +132 -0
  37. package/dist/plugins/agent/providers/codex/mapping.d.ts +56 -0
  38. package/dist/plugins/agent/providers/codex/mapping.js +427 -0
  39. package/dist/plugins/agent/providers/codex/provider.d.ts +84 -0
  40. package/dist/plugins/agent/providers/codex/provider.js +828 -0
  41. package/dist/plugins/agent/providers/codex/rpc.d.ts +40 -0
  42. package/dist/plugins/agent/providers/codex/rpc.js +227 -0
  43. package/dist/plugins/agent/providers/common.d.ts +11 -0
  44. package/dist/plugins/agent/providers/common.js +75 -0
  45. package/dist/plugins/agent/providers/index.d.ts +3 -0
  46. package/dist/plugins/agent/providers/index.js +4 -0
  47. package/dist/plugins/agent/repository.d.ts +21 -0
  48. package/dist/plugins/agent/repository.js +226 -0
  49. package/dist/plugins/agent/runtime-config.d.ts +5 -0
  50. package/dist/plugins/agent/runtime-config.js +60 -0
  51. package/dist/plugins/agent/runtime-files.d.ts +8 -0
  52. package/dist/plugins/agent/runtime-files.js +170 -0
  53. package/dist/plugins/agent/runtime-state.d.ts +17 -0
  54. package/dist/plugins/agent/runtime-state.js +133 -0
  55. package/dist/plugins/agent/runtime.d.ts +60 -0
  56. package/dist/plugins/agent/runtime.js +928 -0
  57. package/dist/plugins/agent/store.d.ts +17 -0
  58. package/dist/plugins/agent/store.js +1 -0
  59. package/dist/plugins/agent/types.d.ts +320 -0
  60. package/dist/plugins/agent/types.js +13 -0
  61. package/dist/plugins/cloud/plugin.d.ts +1 -1
  62. package/dist/plugins/cloud/plugin.js +3 -3
  63. package/dist/plugins/cloud/tunnel-client.js +6 -7
  64. package/dist/plugins/computer/computer-native-backend.js +9 -1
  65. package/dist/plugins/computer/computer-native-host.js +21 -5
  66. package/dist/plugins/computer/computer-schemas.d.ts +7 -7
  67. package/dist/plugins/computer/computer-service.d.ts +3 -0
  68. package/dist/plugins/computer/computer-service.js +33 -1
  69. package/dist/plugins/computer/plugin.d.ts +1 -1
  70. package/dist/plugins/computer/plugin.js +1 -1
  71. package/dist/plugins/computer/types.d.ts +1 -0
  72. package/dist/plugins/git/git-service.d.ts +3 -2
  73. package/dist/plugins/git/git-service.js +37 -1
  74. package/dist/plugins/git/plugin.d.ts +0 -2
  75. package/dist/plugins/git/plugin.js +3 -3
  76. package/dist/plugins/process/plugin.d.ts +1 -1
  77. package/dist/plugins/process/plugin.js +3 -3
  78. package/dist/plugins/process/process-supervisor.d.ts +1 -0
  79. package/dist/plugins/process/process-supervisor.js +15 -4
  80. package/dist/plugins/types.d.ts +1 -11
  81. package/dist/plugins/types.js +1 -17
  82. package/dist/plugins/web/api-types.d.ts +20 -5
  83. package/dist/plugins/web/http/agent-api-router.d.ts +3 -0
  84. package/dist/plugins/web/http/agent-api-router.js +254 -0
  85. package/dist/plugins/web/http/api-router.js +9 -0
  86. package/dist/plugins/web/http/computer-api-router.js +21 -6
  87. package/dist/plugins/web/http/process-api-router.js +3 -0
  88. package/dist/plugins/web/http/workspace-api-router.js +198 -8
  89. package/dist/plugins/web/plugin.d.ts +1 -1
  90. package/dist/plugins/web/plugin.js +5 -4
  91. package/dist/plugins/web/runtime.d.ts +6 -3
  92. package/dist/plugins/web/runtime.js +6 -1
  93. package/dist/plugins/workspace/mcp.d.ts +1 -1
  94. package/dist/plugins/workspace/mcp.js +125 -1
  95. package/dist/plugins/workspace/metadata.d.ts +1 -1
  96. package/dist/plugins/workspace/plugin.d.ts +1 -1
  97. package/dist/plugins/workspace/plugin.js +9 -3
  98. package/dist/plugins/workspace/types.d.ts +1 -18
  99. package/dist/plugins/workspace/workspace-fs.d.ts +19 -3
  100. package/dist/plugins/workspace/workspace-fs.js +112 -120
  101. package/dist/plugins/workspace/workspace-root-policy.d.ts +9 -0
  102. package/dist/plugins/workspace/workspace-root-policy.js +56 -0
  103. package/dist/plugins/workspace/workspace-service.d.ts +13 -6
  104. package/dist/plugins/workspace/workspace-service.js +57 -49
  105. package/dist/web/assets/AgentView-BGLIBoxF.css +1 -0
  106. package/dist/web/assets/AgentView-BwL3S7sb.js +4 -0
  107. package/dist/web/assets/CloudView-DH4sOXJr.js +1 -0
  108. package/dist/web/assets/{CloudView-CHjVbp-5.css → CloudView-DVVvwuWW.css} +1 -1
  109. package/dist/web/assets/CodeViewer.vue_vue_type_script_setup_true_lang-BaC1eGzG.js +3 -0
  110. package/dist/web/assets/ComputerView-BJSjCxFr.js +1 -0
  111. package/dist/web/assets/ComputerView-DWzfSYJ7.css +1 -0
  112. package/dist/web/assets/MarkdownContent-AdAmmDn5.js +16 -0
  113. package/dist/web/assets/MarkdownContent-B_5zTG8c.css +1 -0
  114. package/dist/web/assets/McpToolsView-CPaWUG9h.js +1 -0
  115. package/dist/web/assets/McpToolsView-DjxPbTHj.css +1 -0
  116. package/dist/web/assets/OperationsView-BjTY2lIh.css +1 -0
  117. package/dist/web/assets/OperationsView-D2FtLkHn.js +4 -0
  118. package/dist/web/assets/ProcessesView-BHOsaM2H.js +4 -0
  119. package/dist/web/assets/ProcessesView-Ce6iVwjA.css +1 -0
  120. package/dist/web/assets/StateChip.vue_vue_type_script_setup_true_lang-iW1SYlX_.js +1 -0
  121. package/dist/web/assets/SystemLogsView-By5ijObd.js +1 -0
  122. package/dist/web/assets/SystemLogsView-CofP4Jvi.css +1 -0
  123. package/dist/web/assets/VSelect-CLnwhyWJ.js +1 -0
  124. package/dist/web/assets/VSpacer-dDRRKhUn.js +1 -0
  125. package/dist/web/assets/VSwitch-CGzxwZuj.js +1 -0
  126. package/dist/web/assets/VTabs-7aSwjrKs.js +1 -0
  127. package/dist/web/assets/VTextarea-D1_2FwMe.js +1 -0
  128. package/dist/web/assets/VTextarea-xiMOHEu-.css +1 -0
  129. package/dist/web/assets/WorkspaceDownloadPreview-BjuqUdB9.js +1 -0
  130. package/dist/web/assets/WorkspaceDownloadPreview-DnxhH5Q7.css +1 -0
  131. package/dist/web/assets/WorkspaceMediaPreview-D-igEnka.css +1 -0
  132. package/dist/web/assets/WorkspaceMediaPreview-LwXeVOY2.js +3 -0
  133. package/dist/web/assets/WorkspacesView-ClA6xcjn.css +1 -0
  134. package/dist/web/assets/WorkspacesView-DHl28eWf.js +2 -0
  135. package/dist/web/assets/entity-refresh-queue-wQii8Dl5.js +1 -0
  136. package/dist/web/assets/index-BzRlodie.js +19 -0
  137. package/dist/web/assets/index-CZ-4tJlF.css +1 -0
  138. package/dist/web/assets/{syntax-highlight-B5ArnyrC.js → syntax-highlight-C_fuMcwC.js} +1 -1
  139. package/dist/web/assets/useMasterDetailFocus-BQAutDO9.js +1 -0
  140. package/dist/web/assets/useOperationLabels-C-zgM_ET.js +1 -0
  141. package/dist/web/index.html +2 -2
  142. package/package.json +4 -2
  143. package/dist/plugins/git/types.d.ts +0 -32
  144. package/dist/web/assets/CloudView-CvX0dkgu.js +0 -1
  145. package/dist/web/assets/CodeViewer.vue_vue_type_script_setup_true_lang-B5TxGkUW.js +0 -3
  146. package/dist/web/assets/ComputerView-91Z9Cefw.css +0 -1
  147. package/dist/web/assets/ComputerView-OOyEqWml.js +0 -1
  148. package/dist/web/assets/McpToolsView-BTnolyS6.css +0 -1
  149. package/dist/web/assets/McpToolsView-DjXWTKrZ.js +0 -1
  150. package/dist/web/assets/OperationsView-DqTY51Cr.js +0 -4
  151. package/dist/web/assets/ProcessesView-C13BykIa.js +0 -4
  152. package/dist/web/assets/StateChip.vue_vue_type_script_setup_true_lang-DyOhJmR6.js +0 -1
  153. package/dist/web/assets/SystemLogsView-Ci0u4BTb.js +0 -1
  154. package/dist/web/assets/VSelect-DrRpKyYI.js +0 -1
  155. package/dist/web/assets/VSpacer-C3wAY3F0.js +0 -1
  156. package/dist/web/assets/VSwitch-CxusR4iO.js +0 -1
  157. package/dist/web/assets/VTabs-qBcuuXh3.js +0 -1
  158. package/dist/web/assets/WorkspacesView-BzQ0aH74.css +0 -1
  159. package/dist/web/assets/WorkspacesView-CijIvfsp.js +0 -2
  160. package/dist/web/assets/index-BegKQ3Yd.js +0 -19
  161. package/dist/web/assets/index-CkjqXRSj.css +0 -1
  162. package/dist/web/assets/useOperationLabels-BDjzGDkT.js +0 -1
  163. /package/dist/{plugins/process → core/runtime}/head-tail-buffer.d.ts +0 -0
  164. /package/dist/{plugins/process → core/runtime}/head-tail-buffer.js +0 -0
  165. /package/dist/plugins/{git/types.js → agent/provider.js} +0 -0
@@ -0,0 +1,17 @@
1
+ import type { AgentHistory, AgentHistoryUpdate, AgentItem, AgentProviderSessionState, AgentSession, AgentTurn } from "./types.js";
2
+ export interface AgentStore {
3
+ reconcileInterrupted(now: string): void;
4
+ insertSession(session: AgentSession): void;
5
+ updateSession(session: AgentSession): void;
6
+ getSession(id: string): AgentSession | null;
7
+ listSessions(): AgentSession[];
8
+ deleteSession(id: string): void;
9
+ getProviderState(sessionId: string, provider: AgentProviderSessionState["provider"]): AgentProviderSessionState | null;
10
+ upsertProviderState(state: AgentProviderSessionState): void;
11
+ insertTurn(turn: AgentTurn): void;
12
+ updateTurn(turn: AgentTurn): void;
13
+ insertItem(item: AgentItem): void;
14
+ updateItem(item: AgentItem): void;
15
+ history(sessionId: string): AgentHistory | null;
16
+ historyUpdate(sessionId: string, turnIds: readonly string[], itemIds: readonly string[]): AgentHistoryUpdate | null;
17
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,320 @@
1
+ export type AgentProviderId = string;
2
+ export declare const AGENT_PROVIDER_ID_PATTERN: RegExp;
3
+ export declare function isAgentProviderId(value: unknown): value is AgentProviderId;
4
+ export type AgentSessionStatus = "idle" | "running" | "waiting_input" | "error";
5
+ export type AgentTurnStatus = "running" | "completed" | "interrupted" | "failed";
6
+ export type AgentTurnSource = "human" | "mcp";
7
+ export type AgentItemStatus = "running" | "completed" | "waiting" | "interrupted" | "failed";
8
+ export type AgentReasoningSummary = "auto" | "concise" | "detailed" | "none";
9
+ export interface CodexGranularApprovalPolicy {
10
+ sandbox_approval: boolean;
11
+ rules: boolean;
12
+ skill_approval: boolean;
13
+ request_permissions: boolean;
14
+ mcp_elicitations: boolean;
15
+ }
16
+ export type CodexApprovalPolicy = "untrusted" | "on-request" | {
17
+ granular: CodexGranularApprovalPolicy;
18
+ } | "never";
19
+ export type CodexApprovalsReviewer = "user" | "auto_review" | "guardian_subagent";
20
+ export type CodexSandboxMode = "read-only" | "workspace-write" | "danger-full-access";
21
+ export declare const AGENT_PERMISSION_MODES: readonly ["read-only", "workspace-write", "danger-full-access"];
22
+ export declare function isAgentPermissionMode(value: unknown): value is CodexSandboxMode;
23
+ export interface AgentProviderNativeSetting {
24
+ id: "approvalPolicy" | "approvalsReviewer" | "permissionMode";
25
+ defaultValue: string;
26
+ options: readonly {
27
+ id: string;
28
+ description: string | null;
29
+ }[];
30
+ granularFields: readonly {
31
+ id: string;
32
+ description: string | null;
33
+ }[];
34
+ }
35
+ export interface AgentSessionConfig {
36
+ model: string | null;
37
+ reasoningEffort: string | null;
38
+ reasoningSummary: AgentReasoningSummary | null;
39
+ serviceTier: string | null;
40
+ approvalPolicy: CodexApprovalPolicy | null;
41
+ approvalsReviewer: CodexApprovalsReviewer | null;
42
+ permissionMode: CodexSandboxMode | null;
43
+ }
44
+ export interface TokenUsageBreakdown {
45
+ totalTokens: number;
46
+ inputTokens: number;
47
+ cachedInputTokens: number;
48
+ cacheWriteInputTokens: number;
49
+ outputTokens: number;
50
+ reasoningOutputTokens: number;
51
+ }
52
+ export interface AgentTokenUsage {
53
+ total: TokenUsageBreakdown;
54
+ last: TokenUsageBreakdown;
55
+ modelContextWindow: number | null;
56
+ }
57
+ export interface AgentPlanStep {
58
+ step: string;
59
+ status: "pending" | "inProgress" | "completed";
60
+ }
61
+ export interface AgentModel {
62
+ id: string;
63
+ model: string;
64
+ displayName: string;
65
+ description: string;
66
+ modelSpecialty: string | null;
67
+ isDefault: boolean;
68
+ upgrade: string | null;
69
+ upgradeInfo: unknown | null;
70
+ availabilityMessage: string | null;
71
+ reasoningEfforts: Array<{
72
+ id: string;
73
+ description: string;
74
+ }>;
75
+ defaultReasoningEffort: string | null;
76
+ reasoningSummaries: AgentReasoningSummary[];
77
+ defaultReasoningSummary: AgentReasoningSummary | null;
78
+ inputModalities: Array<"text" | "image" | "audio">;
79
+ multiAgentVersion: string | null;
80
+ serviceTiers: Array<{
81
+ id: string;
82
+ name: string;
83
+ description: string;
84
+ }>;
85
+ defaultServiceTier: string | null;
86
+ availableAccessPrograms: {
87
+ cyber: string[];
88
+ [program: string]: string[];
89
+ } | null;
90
+ }
91
+ export interface AgentProviderQuotaWindow {
92
+ id: string;
93
+ label: string | null;
94
+ utilization: number | null;
95
+ resetsAt: string | null;
96
+ }
97
+ export interface AgentProviderExtraUsage {
98
+ enabled: boolean;
99
+ monthlyLimit: number | null;
100
+ usedCredits: number | null;
101
+ utilization: number | null;
102
+ currency: string | null;
103
+ }
104
+ export interface AgentProviderAccountUsage {
105
+ subscriptionType: string | null;
106
+ windows: AgentProviderQuotaWindow[];
107
+ extraUsage: AgentProviderExtraUsage | null;
108
+ updatedAt: string;
109
+ }
110
+ export interface AgentProviderDetails {
111
+ configRequirements: unknown | null;
112
+ rateLimits: unknown | null;
113
+ accountUsage: AgentProviderAccountUsage | null;
114
+ }
115
+ export type AgentReviewTarget = {
116
+ type: "uncommittedChanges";
117
+ } | {
118
+ type: "baseBranch";
119
+ branch: string;
120
+ } | {
121
+ type: "commit";
122
+ sha: string;
123
+ title: string | null;
124
+ } | {
125
+ type: "custom";
126
+ instructions: string;
127
+ };
128
+ export interface AgentProviderFeatures {
129
+ nativeReview: boolean;
130
+ steering: boolean;
131
+ [feature: string]: boolean;
132
+ }
133
+ export interface AgentProviderProbe {
134
+ installed: boolean;
135
+ authenticated: boolean;
136
+ version: string | null;
137
+ error: string | null;
138
+ capabilities: {
139
+ namespaceTools: boolean;
140
+ imageGeneration: boolean;
141
+ webSearch: boolean;
142
+ [capability: string]: boolean;
143
+ } | null;
144
+ }
145
+ export interface AgentProviderStatus extends AgentProviderProbe {
146
+ id: AgentProviderId;
147
+ displayName: string;
148
+ icon: string | null;
149
+ features: AgentProviderFeatures;
150
+ nativeSettings: readonly AgentProviderNativeSetting[];
151
+ }
152
+ export interface AgentSessionAttention {
153
+ kind: "approval" | "input";
154
+ count: number;
155
+ }
156
+ export interface AgentSession extends AgentSessionConfig {
157
+ id: string;
158
+ workspaceRoot: string;
159
+ provider: AgentProviderId;
160
+ status: AgentSessionStatus;
161
+ attention: AgentSessionAttention | null;
162
+ createdAt: string;
163
+ tokenUsage: AgentTokenUsage | null;
164
+ updatedAt: string;
165
+ }
166
+ export interface AgentProviderSessionState extends AgentSessionConfig {
167
+ sessionId: string;
168
+ provider: AgentProviderId;
169
+ providerSessionId: string;
170
+ continuityContext: string;
171
+ syncedThroughTurnId: string | null;
172
+ createdAt: string;
173
+ tokenUsage: AgentTokenUsage | null;
174
+ updatedAt: string;
175
+ }
176
+ export interface AgentError {
177
+ message: string;
178
+ details: string | null;
179
+ providerData: unknown | null;
180
+ }
181
+ export interface AgentTurn extends AgentSessionConfig {
182
+ id: string;
183
+ sessionId: string;
184
+ providerTurnId: string | null;
185
+ provider: AgentProviderId;
186
+ source: AgentTurnSource;
187
+ status: AgentTurnStatus;
188
+ error: AgentError | null;
189
+ usage: TokenUsageBreakdown | null;
190
+ startedAt: string;
191
+ completedAt: string | null;
192
+ }
193
+ export interface AgentAttachment {
194
+ kind: "image" | "audio" | "skill" | "file";
195
+ name: string;
196
+ path: string;
197
+ mimeType: string | null;
198
+ }
199
+ export interface AgentArtifact {
200
+ kind: "image" | "file";
201
+ name: string;
202
+ path: string;
203
+ mimeType: string | null;
204
+ }
205
+ export interface AgentFileChange {
206
+ path: string;
207
+ kind: string;
208
+ movePath: string | null;
209
+ diff: string;
210
+ }
211
+ export interface AgentInteractionOption {
212
+ id: string;
213
+ label: string;
214
+ description: string | null;
215
+ }
216
+ export interface AgentInputQuestion {
217
+ id: string;
218
+ label: string;
219
+ question: string;
220
+ options: AgentInteractionOption[];
221
+ multiSelect: boolean;
222
+ allowFreeText: boolean;
223
+ secret: boolean;
224
+ }
225
+ export type AgentInteractionResponse = {
226
+ type: "approval";
227
+ decision: string;
228
+ } | {
229
+ type: "input";
230
+ answers: Record<string, string[]>;
231
+ };
232
+ export type AgentItem = AgentItemBase & ({
233
+ type: "user_message";
234
+ source?: AgentTurnSource;
235
+ text: string;
236
+ attachments: AgentAttachment[];
237
+ } | {
238
+ type: "assistant_message";
239
+ text: string;
240
+ phase: "commentary" | "final_answer" | null;
241
+ } | {
242
+ type: "command";
243
+ command: string;
244
+ cwd: string | null;
245
+ output: string;
246
+ exitCode: number | null;
247
+ } | {
248
+ type: "tool";
249
+ progress: string | null;
250
+ name: string;
251
+ server: string | null;
252
+ input: unknown;
253
+ output: unknown;
254
+ error: string | null;
255
+ } | {
256
+ type: "turn_diff";
257
+ diff: string;
258
+ } | {
259
+ type: "file_change";
260
+ changes: AgentFileChange[];
261
+ } | {
262
+ type: "plan";
263
+ text: string;
264
+ steps: AgentPlanStep[];
265
+ } | {
266
+ type: "reasoning_summary";
267
+ text: string;
268
+ } | {
269
+ type: "artifact";
270
+ artifact: AgentArtifact;
271
+ } | {
272
+ type: "interaction";
273
+ interaction: {
274
+ kind: "approval" | "input";
275
+ title: string;
276
+ description: string | null;
277
+ questions: AgentInputQuestion[];
278
+ approvalOptions: AgentInteractionOption[];
279
+ response: AgentInteractionResponse | null;
280
+ };
281
+ } | {
282
+ type: "context_compaction";
283
+ trigger: "auto" | "manual" | null;
284
+ error: string | null;
285
+ } | {
286
+ type: "notice";
287
+ level: "info" | "warning" | "error";
288
+ text: string;
289
+ });
290
+ export interface AgentItemBase {
291
+ id: string;
292
+ turnId: string;
293
+ providerItemId: string | null;
294
+ sequence: number;
295
+ status: AgentItemStatus;
296
+ createdAt: string;
297
+ updatedAt: string;
298
+ }
299
+ export interface AgentHistory {
300
+ session: AgentSession;
301
+ turns: Array<{
302
+ turn: AgentTurn;
303
+ items: AgentItem[];
304
+ }>;
305
+ }
306
+ export interface AgentHistoryUpdate {
307
+ session: AgentSession;
308
+ turns: AgentTurn[];
309
+ items: AgentItem[];
310
+ }
311
+ export interface AgentTurnInput {
312
+ outputSchema: unknown | null;
313
+ text: string;
314
+ attachments: AgentAttachment[];
315
+ }
316
+ export interface CreateAgentSessionInput extends Partial<AgentSessionConfig> {
317
+ workspaceRoot: string;
318
+ provider: AgentProviderId;
319
+ model: string | null;
320
+ }
@@ -0,0 +1,13 @@
1
+ export const AGENT_PROVIDER_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;
2
+ export function isAgentProviderId(value) {
3
+ return typeof value === "string" && AGENT_PROVIDER_ID_PATTERN.test(value);
4
+ }
5
+ export const AGENT_PERMISSION_MODES = [
6
+ "read-only",
7
+ "workspace-write",
8
+ "danger-full-access",
9
+ ];
10
+ export function isAgentPermissionMode(value) {
11
+ return (typeof value === "string" &&
12
+ AGENT_PERMISSION_MODES.some((mode) => mode === value));
13
+ }
@@ -1,4 +1,4 @@
1
1
  import type { InternalPlugin } from "#plugins/types";
2
2
  import { CloudController } from "./controller.js";
3
- export declare const CloudService: import("#plugins/types").ServiceToken<CloudController>;
3
+ export declare const CloudServiceToken: import("#app/service-registry").ServiceToken<CloudController>;
4
4
  export declare function createCloudPlugin(): InternalPlugin;
@@ -1,13 +1,13 @@
1
- import { createServiceToken } from "#plugins/types";
1
+ import { createServiceToken } from "#app/service-registry";
2
2
  import { CloudController } from "./controller.js";
3
- export const CloudService = createServiceToken("cloud");
3
+ export const CloudServiceToken = createServiceToken("cloud");
4
4
  export function createCloudPlugin() {
5
5
  let controller = null;
6
6
  return {
7
7
  id: "cloud",
8
8
  async activate(context) {
9
9
  controller = await CloudController.create(context.config, context.logs, context.externalAccess);
10
- context.services.provide(CloudService, controller);
10
+ context.services.provide(CloudServiceToken, controller);
11
11
  },
12
12
  async deactivate() {
13
13
  await controller?.stop();
@@ -395,14 +395,13 @@ function publicHost(lease, service) {
395
395
  return new URL(baseUrl).host;
396
396
  }
397
397
  function allowedPath(service, value) {
398
- const pathname = new URL(value, "http://localhost").pathname;
398
+ const pathname = new URL(value, "http://localhost").pathname.toLowerCase();
399
+ const mcpPath = pathname === "/mcp" || pathname.startsWith("/mcp/");
400
+ const oauthPath = pathname.startsWith("/oauth/") ||
401
+ pathname.startsWith("/.well-known/oauth-");
399
402
  if (service === "mcp")
400
- return (pathname === "/mcp" ||
401
- pathname.startsWith("/.well-known/oauth-") ||
402
- pathname.startsWith("/oauth/"));
403
- return (pathname !== "/mcp" &&
404
- !pathname.startsWith("/oauth/") &&
405
- !pathname.startsWith("/.well-known/oauth-"));
403
+ return mcpPath || oauthPath;
404
+ return !mcpPath && !oauthPath;
406
405
  }
407
406
  function sanitizeHeaders(headers) {
408
407
  const blocked = new Set([
@@ -5,9 +5,17 @@ export class NativeComputerBackend {
5
5
  host = new ComputerNativeHost();
6
6
  restartWhenGranted = new Set();
7
7
  async status() {
8
- const value = await this.readStatus().catch(() => ({
8
+ const value = await this.readStatus().catch((error) => ({
9
9
  platform: this.host.platform,
10
10
  helper: "unavailable",
11
+ ...(error instanceof ChatRoomError &&
12
+ error.code === "UNSUPPORTED" &&
13
+ error.details &&
14
+ typeof error.details === "object" &&
15
+ "reason" in error.details &&
16
+ error.details.reason === "no_x11_session"
17
+ ? { unavailableReason: "no_x11_session" }
18
+ : {}),
11
19
  permissions: {
12
20
  accessibility: "unknown",
13
21
  screenRecording: "unknown",
@@ -62,8 +62,17 @@ export class ComputerNativeHost {
62
62
  const child = this.child;
63
63
  if (!child || child.killed || child.stdin.destroyed)
64
64
  this.rejectRequest(id, transportError);
65
- else
66
- child.stdin.write(line);
65
+ else {
66
+ try {
67
+ child.stdin.write(line, (error) => {
68
+ if (error)
69
+ this.failTransport(child, error);
70
+ });
71
+ }
72
+ catch (error) {
73
+ this.failTransport(child, error instanceof Error ? error : new Error(String(error)));
74
+ }
75
+ }
67
76
  }
68
77
  return promise;
69
78
  }
@@ -104,8 +113,12 @@ export class ComputerNativeHost {
104
113
  return this.startMacHelper(generation);
105
114
  case "windows":
106
115
  return this.startPipeHelper(windowsHelperPath(), "Windows", process.env, generation);
107
- case "linux":
108
- return this.startPipeHelper(linuxHelperPath(), "Linux X11", linuxDesktopEnvironment(), generation);
116
+ case "linux": {
117
+ const env = linuxDesktopEnvironment();
118
+ if (!env.DISPLAY)
119
+ return Promise.reject(new ChatRoomError("UNSUPPORTED", "Linux Computer Use requires an active X11 graphical session", { reason: "no_x11_session" }));
120
+ return this.startPipeHelper(linuxHelperPath(), "Linux X11", env, generation);
121
+ }
109
122
  case "unsupported":
110
123
  return Promise.reject(new ChatRoomError("UNSUPPORTED", "Computer Use is supported only on macOS, Windows, and Linux X11"));
111
124
  }
@@ -182,6 +195,7 @@ export class ComputerNativeHost {
182
195
  env,
183
196
  });
184
197
  this.child = child;
198
+ child.stdin.on("error", (error) => this.failTransport(child, error));
185
199
  this.lines = createInterface({ input: child.stdout });
186
200
  this.lines.on("line", (line) => this.handleLine(line));
187
201
  child.stderr.on("data", (chunk) => console.error("[computer-helper]", String(chunk).trimEnd()));
@@ -204,8 +218,10 @@ export class ComputerNativeHost {
204
218
  cancelStarting?.(error);
205
219
  if (isCurrentSocket)
206
220
  this.socket = null;
207
- if (isCurrentChild)
221
+ if (isCurrentChild) {
222
+ this.child?.kill();
208
223
  this.child = null;
224
+ }
209
225
  this.lines?.close();
210
226
  this.lines = null;
211
227
  this.cleanupSocketPath();
@@ -1,9 +1,9 @@
1
1
  import { z } from "zod";
2
2
  export declare const computerNativeStatusSchema: z.ZodObject<{
3
3
  platform: z.ZodEnum<{
4
+ linux: "linux";
4
5
  macos: "macos";
5
6
  windows: "windows";
6
- linux: "linux";
7
7
  unsupported: "unsupported";
8
8
  }>;
9
9
  helper: z.ZodEnum<{
@@ -13,15 +13,15 @@ export declare const computerNativeStatusSchema: z.ZodObject<{
13
13
  }>;
14
14
  permissions: z.ZodObject<{
15
15
  accessibility: z.ZodEnum<{
16
+ unknown: "unknown";
16
17
  granted: "granted";
17
18
  denied: "denied";
18
- unknown: "unknown";
19
19
  "not-required": "not-required";
20
20
  }>;
21
21
  screenRecording: z.ZodEnum<{
22
+ unknown: "unknown";
22
23
  granted: "granted";
23
24
  denied: "denied";
24
- unknown: "unknown";
25
25
  "not-required": "not-required";
26
26
  }>;
27
27
  }, z.core.$strip>;
@@ -72,6 +72,8 @@ export declare const computerSnapshotSchema: z.ZodObject<{
72
72
  }, z.core.$strip>>;
73
73
  }, z.core.$strip>;
74
74
  export declare const computerSnapshotMetadataSchema: z.ZodObject<{
75
+ snapshotId: z.ZodString;
76
+ revision: z.ZodNumber;
75
77
  display: z.ZodNullable<z.ZodObject<{
76
78
  id: z.ZodString;
77
79
  name: z.ZodString;
@@ -80,8 +82,6 @@ export declare const computerSnapshotMetadataSchema: z.ZodObject<{
80
82
  scale: z.ZodNumber;
81
83
  primary: z.ZodBoolean;
82
84
  }, z.core.$strip>>;
83
- snapshotId: z.ZodString;
84
- revision: z.ZodNumber;
85
85
  activeApp: z.ZodNullable<z.ZodString>;
86
86
  activeWindow: z.ZodNullable<z.ZodString>;
87
87
  cursor: z.ZodNullable<z.ZodObject<{
@@ -234,6 +234,8 @@ export declare const computerActionMetadataSchema: z.ZodObject<{
234
234
  }>;
235
235
  focusChanged: z.ZodBoolean;
236
236
  snapshot: z.ZodOptional<z.ZodObject<{
237
+ snapshotId: z.ZodString;
238
+ revision: z.ZodNumber;
237
239
  display: z.ZodNullable<z.ZodObject<{
238
240
  id: z.ZodString;
239
241
  name: z.ZodString;
@@ -242,8 +244,6 @@ export declare const computerActionMetadataSchema: z.ZodObject<{
242
244
  scale: z.ZodNumber;
243
245
  primary: z.ZodBoolean;
244
246
  }, z.core.$strip>>;
245
- snapshotId: z.ZodString;
246
- revision: z.ZodNumber;
247
247
  activeApp: z.ZodNullable<z.ZodString>;
248
248
  activeWindow: z.ZodNullable<z.ZodString>;
249
249
  cursor: z.ZodNullable<z.ZodObject<{
@@ -10,17 +10,20 @@ export declare class ComputerService {
10
10
  private currentSnapshotId;
11
11
  private latestSnapshotValue;
12
12
  private latestSnapshotCapturedAt;
13
+ private readonly recentScreenshots;
13
14
  private queue;
14
15
  constructor(backend: ComputerBackend, settingsRepository: ComputerSettingsStore, events: RuntimeEventBus);
15
16
  settings(): ComputerSettings;
16
17
  latestSnapshot(scope: ComputerAccessScope): ComputerSnapshot | null;
17
18
  latestSnapshotTimestamp(): string | null;
19
+ screenshot(scope: ComputerAccessScope, snapshotId: string): NonNullable<ComputerSnapshot["screenshot"]> | null;
18
20
  requestPermission(permission: ComputerPermission): Promise<ComputerStatus>;
19
21
  status(): Promise<ComputerStatus>;
20
22
  setSettings(patch: Partial<Pick<ComputerSettings, "enabled" | "remoteAccess">>): ComputerSettings;
21
23
  snapshot(scope: ComputerAccessScope, request: ComputerSnapshotRequest): Promise<ComputerSnapshot>;
22
24
  action(scope: ComputerAccessScope, request: ComputerActionRequest): Promise<ComputerActionResult>;
23
25
  shutdown(): Promise<void>;
26
+ private rememberScreenshot;
24
27
  private assertActionBudget;
25
28
  private assertAllowed;
26
29
  private assertScopeAllowed;
@@ -8,6 +8,7 @@ export class ComputerService {
8
8
  currentSnapshotId = null;
9
9
  latestSnapshotValue = null;
10
10
  latestSnapshotCapturedAt = null;
11
+ recentScreenshots = new Map();
11
12
  queue = Promise.resolve();
12
13
  constructor(backend, settingsRepository, events) {
13
14
  this.backend = backend;
@@ -27,6 +28,13 @@ export class ComputerService {
27
28
  latestSnapshotTimestamp() {
28
29
  return this.latestSnapshotValue ? this.latestSnapshotCapturedAt : null;
29
30
  }
31
+ screenshot(scope, snapshotId) {
32
+ const settings = this.settings();
33
+ if (!settings.enabled)
34
+ return null;
35
+ this.assertScopeAllowed(scope, settings);
36
+ return this.recentScreenshots.get(snapshotId) ?? null;
37
+ }
30
38
  requestPermission(permission) {
31
39
  return this.serial(async () => {
32
40
  const base = await this.backend.requestPermission(permission);
@@ -43,9 +51,10 @@ export class ComputerService {
43
51
  this.currentSnapshotId = null;
44
52
  this.latestSnapshotValue = null;
45
53
  this.latestSnapshotCapturedAt = null;
54
+ this.recentScreenshots.clear();
46
55
  void this.backend.dispose().catch(() => undefined);
47
56
  }
48
- this.events.emit({ type: "computer-settings", settings: next });
57
+ this.events.emit({ type: "computer-settings" });
49
58
  return next;
50
59
  }
51
60
  snapshot(scope, request) {
@@ -58,6 +67,11 @@ export class ComputerService {
58
67
  value.revision = this.revision;
59
68
  this.latestSnapshotValue = value;
60
69
  this.latestSnapshotCapturedAt = new Date().toISOString();
70
+ this.rememberScreenshot(value);
71
+ this.events.emit({
72
+ type: "computer-snapshot",
73
+ snapshotId: value.snapshotId,
74
+ });
61
75
  return value;
62
76
  });
63
77
  }
@@ -76,6 +90,11 @@ export class ComputerService {
76
90
  if (result.snapshot) {
77
91
  this.latestSnapshotValue = result.snapshot;
78
92
  this.latestSnapshotCapturedAt = new Date().toISOString();
93
+ this.rememberScreenshot(result.snapshot);
94
+ this.events.emit({
95
+ type: "computer-snapshot",
96
+ snapshotId: result.snapshot.snapshotId,
97
+ });
79
98
  }
80
99
  return result;
81
100
  });
@@ -84,8 +103,21 @@ export class ComputerService {
84
103
  this.currentSnapshotId = null;
85
104
  this.latestSnapshotValue = null;
86
105
  this.latestSnapshotCapturedAt = null;
106
+ this.recentScreenshots.clear();
87
107
  await this.backend.dispose();
88
108
  }
109
+ rememberScreenshot(snapshot) {
110
+ if (!snapshot.screenshot)
111
+ return;
112
+ this.recentScreenshots.delete(snapshot.snapshotId);
113
+ this.recentScreenshots.set(snapshot.snapshotId, snapshot.screenshot);
114
+ while (this.recentScreenshots.size > 2) {
115
+ const oldest = this.recentScreenshots.keys().next().value;
116
+ if (typeof oldest !== "string")
117
+ break;
118
+ this.recentScreenshots.delete(oldest);
119
+ }
120
+ }
89
121
  assertActionBudget(request) {
90
122
  const durationMs = request.actions.reduce((total, action) => {
91
123
  if (action.type === "wait")
@@ -1,4 +1,4 @@
1
1
  import type { InternalPlugin } from "#plugins/types";
2
2
  import { ComputerService } from "./computer-service.js";
3
- export declare const ComputerServiceToken: import("#plugins/types").ServiceToken<ComputerService>;
3
+ export declare const ComputerServiceToken: import("#app/service-registry").ServiceToken<ComputerService>;
4
4
  export declare function createComputerPlugin(): InternalPlugin;
@@ -1,4 +1,4 @@
1
- import { createServiceToken } from "#plugins/types";
1
+ import { createServiceToken } from "#app/service-registry";
2
2
  import { NativeComputerBackend } from "./computer-native-backend.js";
3
3
  import { ComputerService } from "./computer-service.js";
4
4
  import { ComputerSettingsRepository } from "./computer-settings-repository.js";
@@ -23,6 +23,7 @@ export interface ComputerDisplay {
23
23
  export interface ComputerStatus {
24
24
  platform: ComputerPlatform;
25
25
  helper: ComputerHelperState;
26
+ unavailableReason?: "no_x11_session";
26
27
  permissions: ComputerPermissions;
27
28
  displays: ComputerDisplay[];
28
29
  settings: ComputerSettings;
@@ -1,9 +1,10 @@
1
1
  import type { CommandRunner } from "#core/runtime/command-runner";
2
- import type { GitBranch, GitCommit, GitDiff, GitStatus } from "./types.js";
3
- export declare class GitService {
2
+ import type { GitAccess, GitBranch, GitCommit, GitDiff, GitStatus } from "#app/git-access";
3
+ export declare class GitService implements GitAccess {
4
4
  private readonly commands;
5
5
  constructor(commands: CommandRunner);
6
6
  status(cwd: string): Promise<GitStatus | null>;
7
+ projectFiles(cwd: string, maxFiles?: number): Promise<string[] | null>;
7
8
  diff(cwd: string, filePath?: string, maxPreviewBytes?: number): Promise<GitDiff>;
8
9
  stage(cwd: string, paths: string[]): Promise<GitStatus>;
9
10
  unstage(cwd: string, paths: string[]): Promise<GitStatus>;