@zhanguym/chatroom 1.0.0 → 1.1.0-beta.0

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 (150) 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/git-access.d.ts +50 -0
  5. package/dist/app/git-access.js +2 -0
  6. package/dist/app/service-registry.d.ts +11 -0
  7. package/dist/app/service-registry.js +17 -0
  8. package/dist/app/workspace-access.d.ts +24 -0
  9. package/dist/app/workspace-access.js +2 -0
  10. package/dist/auth/ingress-policy.d.ts +2 -0
  11. package/dist/auth/ingress-policy.js +14 -2
  12. package/dist/auth/passkey-service.js +1 -1
  13. package/dist/cli/run-cli.js +1 -1
  14. package/dist/core/fs/safe-directory.d.ts +9 -0
  15. package/dist/core/fs/safe-directory.js +129 -0
  16. package/dist/core/operations/repository.d.ts +2 -0
  17. package/dist/core/runtime/line-process.d.ts +19 -0
  18. package/dist/core/runtime/line-process.js +51 -0
  19. package/dist/infrastructure/database/operation-repository.js +8 -2
  20. package/dist/infrastructure/database/schema.d.ts +1 -1
  21. package/dist/infrastructure/database/schema.js +62 -0
  22. package/dist/infrastructure/http/http-server.js +1 -1
  23. package/dist/native/linux/chatroom-computer-helper +0 -0
  24. package/dist/native/macos/ChatRoomComputerHelper.app/Contents/MacOS/chatroom-computer-helper +0 -0
  25. package/dist/native/windows/chatroom-computer-helper.exe +0 -0
  26. package/dist/operations/operation-log.js +16 -4
  27. package/dist/plugins/agent/async-queue.d.ts +10 -0
  28. package/dist/plugins/agent/async-queue.js +49 -0
  29. package/dist/plugins/agent/mcp.d.ts +3 -0
  30. package/dist/plugins/agent/mcp.js +502 -0
  31. package/dist/plugins/agent/plugin.d.ts +4 -0
  32. package/dist/plugins/agent/plugin.js +35 -0
  33. package/dist/plugins/agent/provider.d.ts +132 -0
  34. package/dist/plugins/agent/providers/codex/mapping.d.ts +56 -0
  35. package/dist/plugins/agent/providers/codex/mapping.js +427 -0
  36. package/dist/plugins/agent/providers/codex/provider.d.ts +84 -0
  37. package/dist/plugins/agent/providers/codex/provider.js +828 -0
  38. package/dist/plugins/agent/providers/codex/rpc.d.ts +40 -0
  39. package/dist/plugins/agent/providers/codex/rpc.js +227 -0
  40. package/dist/plugins/agent/providers/common.d.ts +11 -0
  41. package/dist/plugins/agent/providers/common.js +75 -0
  42. package/dist/plugins/agent/providers/index.d.ts +3 -0
  43. package/dist/plugins/agent/providers/index.js +4 -0
  44. package/dist/plugins/agent/repository.d.ts +21 -0
  45. package/dist/plugins/agent/repository.js +226 -0
  46. package/dist/plugins/agent/runtime-config.d.ts +5 -0
  47. package/dist/plugins/agent/runtime-config.js +60 -0
  48. package/dist/plugins/agent/runtime-files.d.ts +8 -0
  49. package/dist/plugins/agent/runtime-files.js +170 -0
  50. package/dist/plugins/agent/runtime-state.d.ts +17 -0
  51. package/dist/plugins/agent/runtime-state.js +133 -0
  52. package/dist/plugins/agent/runtime.d.ts +60 -0
  53. package/dist/plugins/agent/runtime.js +928 -0
  54. package/dist/plugins/agent/store.d.ts +17 -0
  55. package/dist/plugins/agent/store.js +1 -0
  56. package/dist/plugins/agent/types.d.ts +320 -0
  57. package/dist/plugins/agent/types.js +13 -0
  58. package/dist/plugins/cloud/plugin.d.ts +1 -1
  59. package/dist/plugins/cloud/plugin.js +3 -3
  60. package/dist/plugins/cloud/tunnel-client.js +6 -7
  61. package/dist/plugins/computer/computer-schemas.d.ts +7 -7
  62. package/dist/plugins/computer/computer-service.d.ts +3 -0
  63. package/dist/plugins/computer/computer-service.js +33 -1
  64. package/dist/plugins/computer/plugin.d.ts +1 -1
  65. package/dist/plugins/computer/plugin.js +1 -1
  66. package/dist/plugins/git/git-service.d.ts +3 -2
  67. package/dist/plugins/git/git-service.js +37 -1
  68. package/dist/plugins/git/plugin.d.ts +0 -2
  69. package/dist/plugins/git/plugin.js +3 -3
  70. package/dist/plugins/process/plugin.d.ts +1 -1
  71. package/dist/plugins/process/plugin.js +3 -3
  72. package/dist/plugins/process/process-supervisor.d.ts +1 -0
  73. package/dist/plugins/process/process-supervisor.js +15 -4
  74. package/dist/plugins/types.d.ts +1 -11
  75. package/dist/plugins/types.js +1 -17
  76. package/dist/plugins/web/api-types.d.ts +20 -5
  77. package/dist/plugins/web/http/agent-api-router.d.ts +3 -0
  78. package/dist/plugins/web/http/agent-api-router.js +254 -0
  79. package/dist/plugins/web/http/api-router.js +9 -0
  80. package/dist/plugins/web/http/computer-api-router.js +21 -6
  81. package/dist/plugins/web/http/process-api-router.js +3 -0
  82. package/dist/plugins/web/http/workspace-api-router.js +79 -6
  83. package/dist/plugins/web/plugin.d.ts +1 -1
  84. package/dist/plugins/web/plugin.js +5 -4
  85. package/dist/plugins/web/runtime.d.ts +6 -3
  86. package/dist/plugins/web/runtime.js +6 -1
  87. package/dist/plugins/workspace/mcp.js +16 -0
  88. package/dist/plugins/workspace/metadata.d.ts +1 -1
  89. package/dist/plugins/workspace/plugin.d.ts +1 -1
  90. package/dist/plugins/workspace/plugin.js +5 -2
  91. package/dist/plugins/workspace/types.d.ts +1 -18
  92. package/dist/plugins/workspace/workspace-fs.d.ts +9 -3
  93. package/dist/plugins/workspace/workspace-fs.js +78 -125
  94. package/dist/plugins/workspace/workspace-root-policy.d.ts +9 -0
  95. package/dist/plugins/workspace/workspace-root-policy.js +56 -0
  96. package/dist/plugins/workspace/workspace-service.d.ts +11 -6
  97. package/dist/plugins/workspace/workspace-service.js +39 -49
  98. package/dist/web/assets/AgentView-DKuspiki.js +4 -0
  99. package/dist/web/assets/AgentView-DYJeMJLX.css +1 -0
  100. package/dist/web/assets/{CloudView-CHjVbp-5.css → CloudView-DVVvwuWW.css} +1 -1
  101. package/dist/web/assets/CloudView-PbREbJgz.js +1 -0
  102. package/dist/web/assets/CodeViewer.vue_vue_type_script_setup_true_lang-CiFNEpWo.js +3 -0
  103. package/dist/web/assets/ComputerView-BM0u3wSF.css +1 -0
  104. package/dist/web/assets/ComputerView-BRb2sE0Z.js +1 -0
  105. package/dist/web/assets/McpToolsView-B8NSFdf4.js +1 -0
  106. package/dist/web/assets/McpToolsView-C22ZbSuV.css +1 -0
  107. package/dist/web/assets/OperationsView-BjTY2lIh.css +1 -0
  108. package/dist/web/assets/OperationsView-Cavi-6SZ.js +4 -0
  109. package/dist/web/assets/ProcessesView-Ce6iVwjA.css +1 -0
  110. package/dist/web/assets/ProcessesView-UO48Nh2q.js +4 -0
  111. package/dist/web/assets/StateChip.vue_vue_type_script_setup_true_lang-Bvc9wRyA.js +1 -0
  112. package/dist/web/assets/SystemLogsView-BXmOrmu5.js +1 -0
  113. package/dist/web/assets/SystemLogsView-CofP4Jvi.css +1 -0
  114. package/dist/web/assets/VSelect-BPRXx8KM.js +1 -0
  115. package/dist/web/assets/VSpacer-Cl-QiwaM.js +1 -0
  116. package/dist/web/assets/VSwitch-C0XNj1lR.js +1 -0
  117. package/dist/web/assets/{VTabs-qBcuuXh3.js → VTabs-CHj39Ket.js} +1 -1
  118. package/dist/web/assets/VTextarea-BIcUWOU6.js +16 -0
  119. package/dist/web/assets/VTextarea-DG1zE1as.css +1 -0
  120. package/dist/web/assets/WorkspacesView-DPCt6kYy.css +1 -0
  121. package/dist/web/assets/WorkspacesView-rY6RXeiR.js +2 -0
  122. package/dist/web/assets/entity-refresh-queue-wQii8Dl5.js +1 -0
  123. package/dist/web/assets/{index-CkjqXRSj.css → index-BPpl3-sP.css} +1 -1
  124. package/dist/web/assets/index-Dt-pWiW1.js +19 -0
  125. package/dist/web/assets/{syntax-highlight-B5ArnyrC.js → syntax-highlight-C_fuMcwC.js} +1 -1
  126. package/dist/web/assets/useMasterDetailFocus-D0j-KcXv.js +1 -0
  127. package/dist/web/assets/useOperationLabels-DR8r6Vrl.js +1 -0
  128. package/dist/web/index.html +2 -2
  129. package/package.json +4 -2
  130. package/dist/plugins/git/types.d.ts +0 -32
  131. package/dist/web/assets/CloudView-CvX0dkgu.js +0 -1
  132. package/dist/web/assets/CodeViewer.vue_vue_type_script_setup_true_lang-B5TxGkUW.js +0 -3
  133. package/dist/web/assets/ComputerView-91Z9Cefw.css +0 -1
  134. package/dist/web/assets/ComputerView-OOyEqWml.js +0 -1
  135. package/dist/web/assets/McpToolsView-BTnolyS6.css +0 -1
  136. package/dist/web/assets/McpToolsView-DjXWTKrZ.js +0 -1
  137. package/dist/web/assets/OperationsView-DqTY51Cr.js +0 -4
  138. package/dist/web/assets/ProcessesView-C13BykIa.js +0 -4
  139. package/dist/web/assets/StateChip.vue_vue_type_script_setup_true_lang-DyOhJmR6.js +0 -1
  140. package/dist/web/assets/SystemLogsView-Ci0u4BTb.js +0 -1
  141. package/dist/web/assets/VSelect-DrRpKyYI.js +0 -1
  142. package/dist/web/assets/VSpacer-C3wAY3F0.js +0 -1
  143. package/dist/web/assets/VSwitch-CxusR4iO.js +0 -1
  144. package/dist/web/assets/WorkspacesView-BzQ0aH74.css +0 -1
  145. package/dist/web/assets/WorkspacesView-CijIvfsp.js +0 -2
  146. package/dist/web/assets/index-BegKQ3Yd.js +0 -19
  147. package/dist/web/assets/useOperationLabels-BDjzGDkT.js +0 -1
  148. /package/dist/{plugins/process → core/runtime}/head-tail-buffer.d.ts +0 -0
  149. /package/dist/{plugins/process → core/runtime}/head-tail-buffer.js +0 -0
  150. /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([
@@ -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";
@@ -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>;
@@ -1,4 +1,4 @@
1
- import { mkdtemp, open, rm, stat } from "node:fs/promises";
1
+ import { lstat, mkdtemp, open, rm, stat } from "node:fs/promises";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { ChatRoomError } from "#core/errors/chatroom-error";
@@ -21,6 +21,42 @@ export class GitService {
21
21
  ]);
22
22
  return parseStatus(result.stdout);
23
23
  }
24
+ async projectFiles(cwd, maxFiles = 5000) {
25
+ const root = await this.repositoryRoot(cwd);
26
+ if (!root)
27
+ return null;
28
+ const limit = Math.min(Math.max(Math.trunc(maxFiles), 1), 10_000);
29
+ const result = await this.run(root, [
30
+ "ls-files",
31
+ "-z",
32
+ "--cached",
33
+ "--others",
34
+ "--exclude-standard",
35
+ "--",
36
+ ".",
37
+ ":(exclude).git",
38
+ ":(exclude).git/**",
39
+ ":(exclude).chatroom",
40
+ ":(exclude).chatroom/**",
41
+ ]);
42
+ const output = [];
43
+ for (const record of result.stdout.split("\0")) {
44
+ if (!record)
45
+ continue;
46
+ if (output.length >= limit)
47
+ break;
48
+ const filePath = normalizePath(record);
49
+ try {
50
+ if ((await lstat(path.join(root, filePath))).isFile())
51
+ output.push(filePath);
52
+ }
53
+ catch (error) {
54
+ if (error.code !== "ENOENT")
55
+ throw error;
56
+ }
57
+ }
58
+ return output;
59
+ }
24
60
  async diff(cwd, filePath, maxPreviewBytes = 2 * 1024 * 1024) {
25
61
  const root = await this.requireRepository(cwd);
26
62
  await this.requireHead(root);
@@ -1,4 +1,2 @@
1
1
  import type { InternalPlugin } from "#plugins/types";
2
- import { GitService } from "./git-service.js";
3
- export declare const GitServiceToken: import("#plugins/types").ServiceToken<GitService>;
4
2
  export declare function createGitPlugin(): InternalPlugin;
@@ -1,12 +1,12 @@
1
+ import { GitAccessToken } from "#app/git-access";
1
2
  import { CommandRunner } from "#core/runtime/command-runner";
2
- import { createServiceToken } from "#plugins/types";
3
3
  import { GitService } from "./git-service.js";
4
- export const GitServiceToken = createServiceToken("git");
5
4
  export function createGitPlugin() {
6
5
  return {
7
6
  id: "git",
8
7
  activate(context) {
9
- context.services.provide(GitServiceToken, new GitService(new CommandRunner()));
8
+ const service = new GitService(new CommandRunner());
9
+ context.services.provide(GitAccessToken, service);
10
10
  },
11
11
  };
12
12
  }
@@ -1,4 +1,4 @@
1
1
  import type { InternalPlugin } from "#plugins/types";
2
2
  import { ProcessSupervisor } from "./process-supervisor.js";
3
- export declare const ProcessService: import("#plugins/types").ServiceToken<ProcessSupervisor>;
3
+ export declare const ProcessServiceToken: import("#app/service-registry").ServiceToken<ProcessSupervisor>;
4
4
  export declare function createProcessPlugin(): InternalPlugin;