@dev-anywhere/proxy 0.1.9 → 0.2.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 (39) hide show
  1. package/dist/{chunk-BMVYMCKF.js → chunk-3ZUZ22V6.js} +2 -2
  2. package/dist/{chunk-7XMJMVIL.js → chunk-4YQ2JUM7.js} +41 -6
  3. package/dist/chunk-4YQ2JUM7.js.map +1 -0
  4. package/dist/chunk-7UOPAMX7.js +220 -0
  5. package/dist/chunk-7UOPAMX7.js.map +1 -0
  6. package/dist/chunk-NBRBO5GS.js +1032 -0
  7. package/dist/chunk-NBRBO5GS.js.map +1 -0
  8. package/dist/chunk-NQDJ6QAM.js +18 -0
  9. package/dist/chunk-NQDJ6QAM.js.map +1 -0
  10. package/dist/chunk-OBYEKZWC.js +104 -0
  11. package/dist/chunk-OBYEKZWC.js.map +1 -0
  12. package/dist/chunk-PWG6K5QB.js +204 -0
  13. package/dist/chunk-PWG6K5QB.js.map +1 -0
  14. package/dist/{chunk-DCDXAM76.js → chunk-RIQ6OL7X.js} +9 -6
  15. package/dist/chunk-RIQ6OL7X.js.map +1 -0
  16. package/dist/{chunk-6O6JTF24.js → chunk-WUBRUO3G.js} +1 -1
  17. package/dist/index.js +5 -5
  18. package/dist/{relay-token-Z4JZFPQ5.js → relay-token-RKAVVQHE.js} +5 -4
  19. package/dist/{relay-token-Z4JZFPQ5.js.map → relay-token-RKAVVQHE.js.map} +1 -1
  20. package/dist/serve.js +538 -431
  21. package/dist/serve.js.map +1 -1
  22. package/dist/session-worker.js +99 -32
  23. package/dist/session-worker.js.map +1 -1
  24. package/dist/{terminal-FJAIRC73.js → terminal-YO2D2OJU.js} +194 -151
  25. package/dist/terminal-YO2D2OJU.js.map +1 -0
  26. package/package.json +3 -3
  27. package/dist/chunk-2JUB4LDU.js +0 -84
  28. package/dist/chunk-2JUB4LDU.js.map +0 -1
  29. package/dist/chunk-7XMJMVIL.js.map +0 -1
  30. package/dist/chunk-DCDXAM76.js.map +0 -1
  31. package/dist/chunk-ORZTFYXR.js +0 -123
  32. package/dist/chunk-ORZTFYXR.js.map +0 -1
  33. package/dist/chunk-QFYI6AMN.js +0 -870
  34. package/dist/chunk-QFYI6AMN.js.map +0 -1
  35. package/dist/chunk-U5T7ZYXT.js +0 -346
  36. package/dist/chunk-U5T7ZYXT.js.map +0 -1
  37. package/dist/terminal-FJAIRC73.js.map +0 -1
  38. /package/dist/{chunk-BMVYMCKF.js.map → chunk-3ZUZ22V6.js.map} +0 -0
  39. /package/dist/{chunk-6O6JTF24.js.map → chunk-WUBRUO3G.js.map} +0 -0
@@ -1,870 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/common/paths.ts
4
- import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
5
- import { homedir } from "os";
6
- import { dirname, resolve } from "path";
7
- import { fileURLToPath } from "url";
8
- var HOME = homedir();
9
- var MODULE_DIR = dirname(fileURLToPath(import.meta.url));
10
- var SOURCE_FONT_ASSETS_DIR = resolve(MODULE_DIR, "../../assets/fonts");
11
- var DIST_FONT_ASSETS_DIR = resolve(MODULE_DIR, "../assets/fonts");
12
- var DEFAULT_FONT_FAMILY = "sarasa-fixed-sc";
13
- var DEFAULT_PROXY_PROFILE = "default";
14
- function normalizeProxyProfileName(value) {
15
- const normalized = value?.trim() || DEFAULT_PROXY_PROFILE;
16
- if (normalized === "." || normalized === ".." || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$/.test(normalized)) {
17
- throw new Error(
18
- `Invalid dev-anywhere profile "${normalized}". Use 1-64 letters, numbers, ".", "_" or "-".`
19
- );
20
- }
21
- return normalized;
22
- }
23
- function readProxyProfileNameFromArgv(argv) {
24
- const args = [...argv];
25
- while (args[0] === "--") args.shift();
26
- for (let i = 0; i < args.length; i++) {
27
- const arg = args[i];
28
- if (arg === "claude" || arg === "codex") return void 0;
29
- if (arg === "--profile") {
30
- const next = args[i + 1];
31
- return next && !next.startsWith("-") ? next : void 0;
32
- }
33
- if (arg.startsWith("--profile=")) {
34
- return arg.slice("--profile=".length);
35
- }
36
- }
37
- return void 0;
38
- }
39
- function resolveProxyProfileName(argv = process.argv.slice(2), home = HOME) {
40
- return normalizeProxyProfileName(
41
- readProxyProfileNameFromArgv(argv) ?? readDefaultProfileFromConfig(home)
42
- );
43
- }
44
- function readDefaultProfileFromConfig(home) {
45
- try {
46
- const parsed = JSON.parse(readFileSync(`${home}/.dev-anywhere/config.json`, "utf-8"));
47
- return typeof parsed.defaultProfile === "string" ? parsed.defaultProfile : void 0;
48
- } catch {
49
- return void 0;
50
- }
51
- }
52
- function buildProxyProfilePaths(home, profileName) {
53
- const normalizedProfile = normalizeProxyProfileName(profileName);
54
- const appDir = `${home}/.dev-anywhere`;
55
- const isDefaultProfile = normalizedProfile === DEFAULT_PROXY_PROFILE;
56
- const profileDir = isDefaultProfile ? appDir : `${appDir}/profiles/${normalizedProfile}`;
57
- const runDir = isDefaultProfile ? `${appDir}/run` : `${profileDir}/run`;
58
- const stateDir = isDefaultProfile ? `${appDir}/state` : `${profileDir}/state`;
59
- const dataDir = isDefaultProfile ? `${appDir}/data` : `${profileDir}/data`;
60
- const logDir = isDefaultProfile ? `${appDir}/logs` : `${profileDir}/logs`;
61
- const relayDataDir = `${appDir}/relay-data`;
62
- return {
63
- profileName: normalizedProfile,
64
- isDefaultProfile,
65
- appDir,
66
- profileDir,
67
- configPath: `${appDir}/config.json`,
68
- runDir,
69
- sockPath: `${runDir}/dev-anywhere.sock`,
70
- pidPath: `${runDir}/dev-anywhere.pid`,
71
- stoppedPath: `${runDir}/stopped`,
72
- desiredRelayPath: `${runDir}/desired-relay`,
73
- stateDir,
74
- sessionsPath: `${stateDir}/sessions.json`,
75
- hookRegistryPath: `${stateDir}/hooks.json`,
76
- dataDir,
77
- proxyIdPath: isDefaultProfile ? `${appDir}/proxy-id` : `${profileDir}/proxy-id`,
78
- logDir,
79
- serviceLogPath: `${logDir}/service.log`,
80
- relayDataDir,
81
- fontDir: `${relayDataDir}/fonts`
82
- };
83
- }
84
- function defaultHookPortForProfile(profileName) {
85
- const normalizedProfile = normalizeProxyProfileName(profileName);
86
- if (normalizedProfile === DEFAULT_PROXY_PROFILE) return 17654;
87
- let hash = 0;
88
- for (const char of normalizedProfile) {
89
- hash = (hash * 31 + char.charCodeAt(0)) % 1e3;
90
- }
91
- return 17655 + hash;
92
- }
93
- var PROFILE_NAME = resolveProxyProfileName();
94
- var PROFILE_PATHS = buildProxyProfilePaths(HOME, PROFILE_NAME);
95
- function tildify(cwd) {
96
- return HOME ? cwd.replace(HOME, "~") : cwd;
97
- }
98
- var CONFIG_PATH = PROFILE_PATHS.configPath;
99
- var RUN_DIR = PROFILE_PATHS.runDir;
100
- var SOCK_PATH = PROFILE_PATHS.sockPath;
101
- var PID_PATH = PROFILE_PATHS.pidPath;
102
- var STOPPED_PATH = PROFILE_PATHS.stoppedPath;
103
- var DESIRED_RELAY_PATH = PROFILE_PATHS.desiredRelayPath;
104
- var STATE_DIR = PROFILE_PATHS.stateDir;
105
- var SESSIONS_PATH = PROFILE_PATHS.sessionsPath;
106
- var HOOK_REGISTRY_PATH = PROFILE_PATHS.hookRegistryPath;
107
- var DATA_DIR = PROFILE_PATHS.dataDir;
108
- var PROXY_ID_PATH = PROFILE_PATHS.proxyIdPath;
109
- var RELAY_DATA_DIR = PROFILE_PATHS.relayDataDir;
110
- var FONT_DIR = PROFILE_PATHS.fontDir;
111
- var LOG_DIR = PROFILE_PATHS.logDir;
112
- var SERVICE_LOG_PATH = PROFILE_PATHS.serviceLogPath;
113
- function sessionDir(sessionId) {
114
- return `${DATA_DIR}/${sessionId}`;
115
- }
116
- function sessionPaths(sessionId) {
117
- const dir = sessionDir(sessionId);
118
- return {
119
- dir,
120
- workerSock: `${dir}/worker.sock`
121
- };
122
- }
123
- function isInitialized() {
124
- return existsSync(CONFIG_PATH);
125
- }
126
- var DEFAULT_CONFIG = `{
127
- "defaultProfile": "default",
128
- "profiles": {
129
- "default": {
130
- "relay": "cloud"
131
- },
132
- "local": {
133
- "relay": "local"
134
- }
135
- },
136
- "relays": {
137
- "cloud": {
138
- "url": "wss://dev-anywhere.example.com",
139
- "proxyToken": ""
140
- },
141
- "local": {
142
- "url": "ws://localhost:3100"
143
- }
144
- }
145
- }
146
- `;
147
- function copyFontFamilyIfMissing(targetFontsDir, source) {
148
- const family = source.family ?? DEFAULT_FONT_FAMILY;
149
- const sourceFamilyDir = `${source.dir}/${family}`;
150
- const targetFamilyDir = `${targetFontsDir}/${family}`;
151
- if (existsSync(targetFamilyDir) || !existsSync(sourceFamilyDir)) return false;
152
- mkdirSync(targetFontsDir, { recursive: true });
153
- cpSync(sourceFamilyDir, targetFamilyDir, { recursive: true });
154
- return true;
155
- }
156
- function installFontAssetsFromSources(targetFontsDir, sources) {
157
- for (const source of sources) {
158
- if (copyFontFamilyIfMissing(targetFontsDir, source)) return true;
159
- }
160
- return false;
161
- }
162
- function installFontAssets() {
163
- installFontAssetsFromSources(FONT_DIR, [
164
- { dir: SOURCE_FONT_ASSETS_DIR, family: DEFAULT_FONT_FAMILY },
165
- { dir: DIST_FONT_ASSETS_DIR, family: DEFAULT_FONT_FAMILY }
166
- ]);
167
- }
168
- function initWorkspace() {
169
- ensureProfileWorkspace();
170
- mkdirSync(RELAY_DATA_DIR, { recursive: true });
171
- installFontAssets();
172
- if (!existsSync(CONFIG_PATH)) {
173
- writeFileSync(CONFIG_PATH, DEFAULT_CONFIG);
174
- }
175
- }
176
- function ensureProfileWorkspace() {
177
- mkdirSync(RUN_DIR, { recursive: true });
178
- mkdirSync(STATE_DIR, { recursive: true });
179
- mkdirSync(DATA_DIR, { recursive: true });
180
- mkdirSync(LOG_DIR, { recursive: true });
181
- }
182
-
183
- // ../../packages/shared/dist/schemas/envelope.js
184
- import { z as z5 } from "zod";
185
-
186
- // ../../packages/shared/dist/schemas/chat.js
187
- import { z } from "zod";
188
- var UserInputPayloadSchema = z.object({
189
- text: z.string().min(1),
190
- messageId: z.string().min(1).optional()
191
- });
192
- var AssistantMessagePayloadSchema = z.object({
193
- text: z.string(),
194
- isPartial: z.boolean()
195
- });
196
- var ThinkingPayloadSchema = z.object({
197
- text: z.string()
198
- });
199
-
200
- // ../../packages/shared/dist/schemas/tool.js
201
- import { z as z2 } from "zod";
202
- var ToolUseRequestPayloadSchema = z2.object({
203
- toolName: z2.string(),
204
- toolId: z2.string(),
205
- parameters: z2.record(z2.string(), z2.unknown())
206
- });
207
- var ToolApprovePayloadSchema = z2.object({
208
- toolId: z2.string(),
209
- whitelistTool: z2.boolean().optional()
210
- });
211
- var ToolDenyPayloadSchema = z2.object({
212
- toolId: z2.string(),
213
- reason: z2.string().optional()
214
- });
215
- var ToolResultPayloadSchema = z2.object({
216
- toolId: z2.string(),
217
- result: z2.unknown(),
218
- isError: z2.boolean()
219
- });
220
-
221
- // ../../packages/shared/dist/schemas/session.js
222
- import { z as z3 } from "zod";
223
- var sessionStateValues = ["idle", "working", "waiting_approval", "error", "terminated"];
224
- var providerValues = ["claude", "codex"];
225
- var ptyOwnerValues = ["local-terminal", "proxy-hosted"];
226
- var agentStatusPhaseValues = [
227
- "idle",
228
- "thinking",
229
- "tool_use",
230
- "outputting",
231
- "waiting_permission",
232
- "error"
233
- ];
234
- var SessionInfoSchema = z3.object({
235
- sessionId: z3.string(),
236
- name: z3.string().optional(),
237
- state: z3.enum(sessionStateValues),
238
- mode: z3.enum(["pty", "json"]).optional(),
239
- provider: z3.enum(providerValues),
240
- // PTY 尺寸所有权:
241
- // - local-terminal: 本地 terminal 进程持有真实 PTY,Web 只按原始 cols/rows 展示
242
- // - proxy-hosted: serve 内托管 PTY,Web 可按视口请求 resize
243
- ptyOwner: z3.enum(ptyOwnerValues).optional(),
244
- lastActive: z3.number().optional()
245
- });
246
- var SessionCreatePayloadSchema = z3.object({
247
- name: z3.string().optional(),
248
- cwd: z3.string().optional(),
249
- streamDelta: z3.boolean().optional()
250
- });
251
- var SessionListPayloadSchema = z3.object({
252
- sessions: z3.array(SessionInfoSchema)
253
- });
254
- var SessionSwitchPayloadSchema = z3.object({
255
- sessionId: z3.string()
256
- });
257
- var SessionTerminatePayloadSchema = z3.object({
258
- sessionId: z3.string()
259
- });
260
- var SessionStatusPayloadSchema = z3.object({
261
- sessionId: z3.string(),
262
- state: z3.enum(sessionStateValues),
263
- lastActive: z3.number()
264
- });
265
- var PtyStatePayloadSchema = z3.object({
266
- state: z3.enum(["working", "turn_complete", "approval_wait", "mid_pause"]),
267
- title: z3.string().optional(),
268
- tool: z3.string().optional()
269
- });
270
- var AgentStatusPayloadSchema = z3.object({
271
- provider: z3.enum(providerValues),
272
- phase: z3.enum(agentStatusPhaseValues),
273
- seq: z3.number().int().nonnegative(),
274
- updatedAt: z3.number(),
275
- toolName: z3.string().optional(),
276
- toolInput: z3.record(z3.string(), z3.unknown()).optional(),
277
- permissionRequest: z3.object({
278
- requestId: z3.string(),
279
- toolName: z3.string(),
280
- input: z3.record(z3.string(), z3.unknown())
281
- }).optional(),
282
- permissionResolution: z3.object({
283
- requestId: z3.string(),
284
- outcome: z3.enum(["allow", "deny"])
285
- }).optional(),
286
- summary: z3.string().optional()
287
- });
288
-
289
- // ../../packages/shared/dist/schemas/system.js
290
- import { z as z4 } from "zod";
291
- var HeartbeatPayloadSchema = z4.object({});
292
- var AuthPayloadSchema = z4.object({
293
- pairingCode: z4.string().optional(),
294
- token: z4.string().optional()
295
- });
296
- var SyncRequestPayloadSchema = z4.object({
297
- lastSeq: z4.number().int().nonnegative()
298
- });
299
- var SyncResponsePayloadSchema = z4.object({
300
- messages: z4.array(z4.record(z4.string(), z4.unknown()))
301
- });
302
-
303
- // ../../packages/shared/dist/schemas/envelope.js
304
- var BaseEnvelopeFields = {
305
- seq: z5.number().int().nonnegative(),
306
- sessionId: z5.string(),
307
- timestamp: z5.number(),
308
- source: z5.enum(["proxy", "client"]),
309
- version: z5.string()
310
- };
311
- var MessageEnvelopeSchema = z5.discriminatedUnion("type", [
312
- // chat (3)
313
- z5.object({
314
- ...BaseEnvelopeFields,
315
- type: z5.literal("user_input"),
316
- payload: UserInputPayloadSchema
317
- }),
318
- z5.object({
319
- ...BaseEnvelopeFields,
320
- type: z5.literal("assistant_message"),
321
- payload: AssistantMessagePayloadSchema
322
- }),
323
- z5.object({
324
- ...BaseEnvelopeFields,
325
- type: z5.literal("thinking"),
326
- payload: ThinkingPayloadSchema
327
- }),
328
- // tool (4): 工具审批决策属于 relay control,不进入会话消息信封。
329
- // tool_use_request: 审批流请求(proxy → client),toolId 是 approval requestId
330
- z5.object({
331
- ...BaseEnvelopeFields,
332
- type: z5.literal("tool_use_request"),
333
- payload: ToolUseRequestPayloadSchema
334
- }),
335
- // tool_result: 工具执行结果(proxy → client),toolId 对应 assistant_tool_use / tool_use_request 的 toolId
336
- z5.object({
337
- ...BaseEnvelopeFields,
338
- type: z5.literal("tool_result"),
339
- payload: ToolResultPayloadSchema
340
- }),
341
- // assistant_tool_use: 纯展示型工具调用(proxy → client),区别于 tool_use_request 无审批语义
342
- // payload 结构复用 ToolUseRequestPayloadSchema;toolId 是 Claude 分配的 tool_use id
343
- z5.object({
344
- ...BaseEnvelopeFields,
345
- type: z5.literal("assistant_tool_use"),
346
- payload: ToolUseRequestPayloadSchema
347
- }),
348
- // session (5)
349
- z5.object({
350
- ...BaseEnvelopeFields,
351
- type: z5.literal("session_create"),
352
- payload: SessionCreatePayloadSchema
353
- }),
354
- z5.object({
355
- ...BaseEnvelopeFields,
356
- type: z5.literal("session_list"),
357
- payload: SessionListPayloadSchema
358
- }),
359
- z5.object({
360
- ...BaseEnvelopeFields,
361
- type: z5.literal("session_switch"),
362
- payload: SessionSwitchPayloadSchema
363
- }),
364
- z5.object({
365
- ...BaseEnvelopeFields,
366
- type: z5.literal("session_terminate"),
367
- payload: SessionTerminatePayloadSchema
368
- }),
369
- z5.object({
370
- ...BaseEnvelopeFields,
371
- type: z5.literal("session_status"),
372
- payload: SessionStatusPayloadSchema
373
- }),
374
- // system (5)
375
- z5.object({
376
- ...BaseEnvelopeFields,
377
- type: z5.literal("heartbeat"),
378
- payload: HeartbeatPayloadSchema
379
- }),
380
- z5.object({
381
- ...BaseEnvelopeFields,
382
- type: z5.literal("auth"),
383
- payload: AuthPayloadSchema
384
- }),
385
- z5.object({
386
- ...BaseEnvelopeFields,
387
- type: z5.literal("sync_request"),
388
- payload: SyncRequestPayloadSchema
389
- }),
390
- z5.object({
391
- ...BaseEnvelopeFields,
392
- type: z5.literal("sync_response"),
393
- payload: SyncResponsePayloadSchema
394
- })
395
- ]);
396
-
397
- // ../../packages/shared/dist/builders/index.js
398
- function buildMessage(type, sessionId, seq, payload, source) {
399
- const envelope = {
400
- seq,
401
- sessionId,
402
- type,
403
- payload,
404
- timestamp: Date.now(),
405
- source,
406
- version: "1.0"
407
- };
408
- return MessageEnvelopeSchema.parse(envelope);
409
- }
410
-
411
- // ../../packages/shared/dist/schemas/relay-control.js
412
- import { z as z6 } from "zod";
413
-
414
- // ../../packages/shared/dist/constants/relay-errors.js
415
- var RelayErrorCode = {
416
- NOT_REGISTERED: "NOT_REGISTERED",
417
- NOT_BOUND: "NOT_BOUND",
418
- PROXY_OFFLINE: "PROXY_OFFLINE",
419
- INVALID_MESSAGE: "INVALID_MESSAGE",
420
- UNSUPPORTED: "UNSUPPORTED",
421
- INVALID_RANGE: "INVALID_RANGE"
422
- };
423
-
424
- // ../../packages/shared/dist/constants/control-errors.js
425
- var ControlErrorCode = {
426
- INVALID_PATH: "INVALID_PATH",
427
- PATH_NOT_FOUND: "PATH_NOT_FOUND",
428
- PATH_NOT_DIRECTORY: "PATH_NOT_DIRECTORY",
429
- PATH_ACCESS_DENIED: "PATH_ACCESS_DENIED",
430
- PROXY_OFFLINE: "PROXY_OFFLINE",
431
- SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
432
- PROVIDER_UNSUPPORTED: "PROVIDER_UNSUPPORTED",
433
- WORKER_START_FAILED: "WORKER_START_FAILED",
434
- PROCESS_START_FAILED: "PROCESS_START_FAILED",
435
- UNKNOWN: "UNKNOWN"
436
- };
437
-
438
- // ../../packages/shared/dist/schemas/relay-control.js
439
- var ProxyInfoSchema = z6.object({
440
- proxyId: z6.string(),
441
- name: z6.string().optional(),
442
- online: z6.boolean(),
443
- sessions: z6.array(z6.string()).optional()
444
- });
445
- var AgentCliAvailabilitySchema = z6.object({
446
- available: z6.boolean(),
447
- command: z6.string().optional(),
448
- error: z6.string().optional(),
449
- suggestions: z6.array(z6.string()).optional()
450
- });
451
- var AgentCliStatusSchema = z6.object({
452
- claude: AgentCliAvailabilitySchema,
453
- codex: AgentCliAvailabilitySchema
454
- });
455
- var DirEntrySchema = z6.object({ name: z6.string(), isDir: z6.boolean() });
456
- var FileTreeGroupSchema = z6.object({
457
- path: z6.string(),
458
- entries: z6.array(DirEntrySchema)
459
- });
460
- var CommandEntrySchema = z6.object({
461
- name: z6.string(),
462
- description: z6.string(),
463
- argumentHint: z6.string().optional(),
464
- source: z6.string()
465
- });
466
- var HistorySessionSchema = z6.object({
467
- id: z6.string(),
468
- title: z6.string(),
469
- projectDir: z6.string(),
470
- updatedAt: z6.number(),
471
- provider: z6.enum(["claude", "codex"]).optional()
472
- });
473
- var SessionHistoryMessageSchema = z6.object({
474
- role: z6.enum(["user", "assistant"]),
475
- text: z6.string(),
476
- timestamp: z6.number().optional(),
477
- cursor: z6.string().optional()
478
- });
479
- var RequestIdShape = { requestId: z6.string().min(1).optional() };
480
- var ControlErrorCodeSchema = z6.enum(Object.values(ControlErrorCode));
481
- var RequestErrorShape = {
482
- error: z6.string().optional(),
483
- errorCode: ControlErrorCodeSchema.optional()
484
- };
485
- var ClipboardImageMimeTypeSchema = z6.enum(["image/png", "image/jpeg", "image/webp", "image/gif"]);
486
- function control(type, shape, directions) {
487
- return {
488
- type,
489
- directions: new Set(Array.isArray(directions) ? directions : directions ? [directions] : []),
490
- schema: z6.object({
491
- type: z6.literal(type),
492
- ...shape ?? {}
493
- })
494
- };
495
- }
496
- var relayControlDefinitions = [
497
- control("proxy_register", {
498
- proxyId: z6.string().min(1),
499
- name: z6.string().optional()
500
- }),
501
- control("proxy_register_response", {
502
- status: z6.enum(["new", "reconnected"])
503
- }),
504
- control("proxy_list_request", RequestIdShape),
505
- control("proxy_list_response", {
506
- ...RequestIdShape,
507
- proxies: z6.array(ProxyInfoSchema)
508
- }),
509
- control("proxy_select", { ...RequestIdShape, proxyId: z6.string().min(1) }),
510
- control("proxy_select_response", {
511
- ...RequestIdShape,
512
- success: z6.boolean(),
513
- proxyId: z6.string().optional(),
514
- ...RequestErrorShape
515
- }),
516
- control("relay_error", {
517
- code: z6.enum(Object.values(RelayErrorCode)),
518
- message: z6.string()
519
- }),
520
- // 客户端注册协议
521
- control("client_register", {
522
- clientId: z6.string().min(1)
523
- }),
524
- control("client_register_response", {
525
- status: z6.enum(["restored", "proxy_offline", "new"]),
526
- proxyId: z6.string().optional()
527
- }),
528
- // Proxy 离线通知
529
- control("proxy_offline", {
530
- proxyId: z6.string()
531
- }),
532
- // Proxy 主动断开,relay 立即清理资源
533
- control("proxy_disconnect", {
534
- proxyId: z6.string().min(1)
535
- }),
536
- // Proxy 重连后通知 client 恢复
537
- control("proxy_online", {
538
- proxyId: z6.string().min(1)
539
- }),
540
- // 目录列表请求与响应
541
- control("dir_list_request", {
542
- proxyId: z6.string().min(1).optional(),
543
- ...RequestIdShape,
544
- path: z6.string()
545
- }, "client_to_proxy"),
546
- control("dir_list_response", { ...RequestIdShape, ...RequestErrorShape, entries: z6.array(DirEntrySchema), path: z6.string() }, "proxy_to_client"),
547
- // 目录创建请求与响应
548
- control("dir_create_request", { ...RequestIdShape, path: z6.string() }, "client_to_proxy"),
549
- control("dir_create_response", {
550
- ...RequestIdShape,
551
- ...RequestErrorShape,
552
- path: z6.string(),
553
- success: z6.boolean()
554
- }, "proxy_to_client"),
555
- // 命令列表推送,proxy 将可用命令列表推给 client
556
- control("command_list_push", { commands: z6.array(CommandEntrySchema) }, "proxy_to_client"),
557
- // 文件树推送: 按目录分组, 首组 path 即为 session cwd
558
- // 前端直接把每组写入 tree[path], 与 dir_list_response 共享 cache slot
559
- control("file_tree_push", {
560
- groups: z6.array(FileTreeGroupSchema)
561
- }, "proxy_to_client"),
562
- // 会话列表请求与权限模式变更
563
- control("session_list", void 0, ["client_to_proxy", "proxy_to_client"]),
564
- control("permission_mode_change", {
565
- mode: z6.enum(["default", "auto_accept", "plan"]),
566
- // sessionId 可选:传入时 proxy 按该会话的 mode 分叉(PTY 发 Tab ANSI),未传走全局日志行为
567
- sessionId: z6.string().optional()
568
- }, "client_to_proxy"),
569
- // 会话历史浏览
570
- control("session_history_request", RequestIdShape, "client_to_proxy"),
571
- control("session_history_response", { ...RequestIdShape, sessions: z6.array(HistorySessionSchema) }, "proxy_to_client"),
572
- // PTY 语义状态,从 Envelope 迁移到 Control 层
573
- control("pty_state", { sessionId: z6.string(), payload: PtyStatePayloadSchema }, "proxy_to_client"),
574
- // Provider 语义状态,来自 Claude/Codex hook 等结构化事件,不从 PTY 字节推断
575
- control("agent_status", { sessionId: z6.string(), payload: AgentStatusPayloadSchema }, "proxy_to_client"),
576
- // 终端标题变化,proxy -> client
577
- control("terminal_title", { sessionId: z6.string(), title: z6.string() }, "proxy_to_client"),
578
- // 终端尺寸变化,proxy -> client
579
- control("terminal_resize", { sessionId: z6.string(), cols: z6.number().int().positive(), rows: z6.number().int().positive() }, "proxy_to_client"),
580
- control("terminal_resize_request", { sessionId: z6.string(), cols: z6.number().int().positive(), rows: z6.number().int().positive() }, "client_to_proxy"),
581
- // 远程终止 JSON 会话,client -> proxy
582
- control("session_terminate", { sessionId: z6.string() }, "client_to_proxy"),
583
- // 中断当前 turn,client -> proxy,SIGINT 到 worker 进程让 claude CLI abort 当前流
584
- control("session_worker_abort", { sessionId: z6.string() }, "client_to_proxy"),
585
- // turn 完成信号,proxy -> client,对应 claude stream-json 的 result 事件
586
- control("turn_result", {
587
- sessionId: z6.string(),
588
- success: z6.boolean(),
589
- isError: z6.boolean(),
590
- // stream-json result.result 是本轮最终文本。assistant_message 流丢失或 CLI 未发增量时,
591
- // Web 用它作为 JSON 模式兜底展示,避免 turn 已结束但界面空白。
592
- result: z6.string().optional()
593
- }, "proxy_to_client"),
594
- // 客户端发送到 PTY 的原始字节(ANSI 序列),不追加换行
595
- control("remote_input_raw", { sessionId: z6.string().min(1), data: z6.string() }, "client_to_proxy"),
596
- control("clipboard_image_upload", {
597
- ...RequestIdShape,
598
- sessionId: z6.string().min(1),
599
- mimeType: ClipboardImageMimeTypeSchema,
600
- dataBase64: z6.string().min(1),
601
- fileName: z6.string().optional()
602
- }, "client_to_proxy"),
603
- control("clipboard_image_upload_response", {
604
- ...RequestIdShape,
605
- ...RequestErrorShape,
606
- sessionId: z6.string().min(1),
607
- success: z6.boolean(),
608
- path: z6.string()
609
- }, "proxy_to_client"),
610
- control("image_preview_request", {
611
- ...RequestIdShape,
612
- sessionId: z6.string().min(1),
613
- path: z6.string().min(1)
614
- }, "client_to_proxy"),
615
- control("image_preview_response", {
616
- ...RequestIdShape,
617
- ...RequestErrorShape,
618
- sessionId: z6.string().min(1),
619
- success: z6.boolean(),
620
- path: z6.string(),
621
- mimeType: ClipboardImageMimeTypeSchema.optional(),
622
- dataBase64: z6.string().optional(),
623
- size: z6.number().int().nonnegative().optional()
624
- }, "proxy_to_client"),
625
- // 客户端询问 proxy 的环境信息 (home 路径等), client -> proxy -> response
626
- // FilePathPicker 用 homePath 作为 select 模式下的默认起点, 新建会话时打开即可浏览
627
- control("proxy_info_request", RequestIdShape, "client_to_proxy"),
628
- control("proxy_info", { ...RequestIdShape, homePath: z6.string(), agentCli: AgentCliStatusSchema }, "proxy_to_client"),
629
- control("agent_cli_config_update", { ...RequestIdShape, provider: z6.enum(["claude", "codex"]), path: z6.string().min(1) }, "client_to_proxy"),
630
- control("agent_cli_config_update_response", {
631
- ...RequestIdShape,
632
- provider: z6.enum(["claude", "codex"]),
633
- agentCli: AgentCliStatusSchema.optional(),
634
- ...RequestErrorShape
635
- }, "proxy_to_client"),
636
- // 远程创建 JSON 会话,client -> proxy -> response
637
- control("session_create", {
638
- ...RequestIdShape,
639
- cwd: z6.string(),
640
- provider: z6.enum(["claude", "codex"]),
641
- mode: z6.enum(["json", "pty"]).optional(),
642
- resumeSessionId: z6.string().optional(),
643
- // 透传给 claude CLI 的 --permission-mode, undefined 时 proxy 兜底为 "default"
644
- permissionMode: z6.enum(["default", "auto", "acceptEdits", "plan", "bypassPermissions", "dontAsk"]).optional()
645
- }, "client_to_proxy"),
646
- control("session_create_response", {
647
- ...RequestIdShape,
648
- sessionId: z6.string(),
649
- mode: z6.enum(["json", "pty"]).optional(),
650
- provider: z6.enum(["claude", "codex"]).optional(),
651
- ptyOwner: z6.enum(["local-terminal", "proxy-hosted"]).optional(),
652
- ...RequestErrorShape
653
- }, "proxy_to_client"),
654
- // 客户端请求会话历史消息,client -> proxy
655
- control("session_messages_request", {
656
- ...RequestIdShape,
657
- sessionId: z6.string(),
658
- limit: z6.number().int().min(1).max(200).optional(),
659
- before: z6.string().optional()
660
- }, "client_to_proxy"),
661
- // 客户端请求会话资源(命令列表 + 文件树),client -> proxy
662
- control("session_resources_request", { ...RequestIdShape, sessionId: z6.string() }, "client_to_proxy"),
663
- control("session_resources_response", {
664
- ...RequestIdShape,
665
- ...RequestErrorShape,
666
- sessionId: z6.string(),
667
- commands: z6.array(CommandEntrySchema),
668
- groups: z6.array(FileTreeGroupSchema)
669
- }, "proxy_to_client"),
670
- // 客户端请求当前 provider 语义状态;不经 relay 缓存,由 proxy 返回当前值
671
- control("agent_status_request", { ...RequestIdShape, sessionId: z6.string().optional() }, "client_to_proxy"),
672
- control("agent_status_response", {
673
- ...RequestIdShape,
674
- statuses: z6.array(z6.object({ sessionId: z6.string(), payload: AgentStatusPayloadSchema }))
675
- }, "proxy_to_client"),
676
- // 客户端确认已收到审批请求;proxy 只记录送达状态,不把它当成用户决策
677
- control("permission_request_delivered", { sessionId: z6.string(), requestId: z6.string() }, "client_to_proxy"),
678
- control("tool_approve", { sessionId: z6.string(), payload: ToolApprovePayloadSchema }, "client_to_proxy"),
679
- control("tool_deny", { sessionId: z6.string(), payload: ToolDenyPayloadSchema }, "client_to_proxy"),
680
- // proxy 确认用户决策已进入 provider/worker 路径;web 用它更新审批卡片状态
681
- control("permission_decision_result", {
682
- sessionId: z6.string(),
683
- requestId: z6.string(),
684
- outcome: z6.enum(["allow", "deny"]),
685
- delivered: z6.boolean(),
686
- message: z6.string().optional()
687
- }, "proxy_to_client"),
688
- // proxy 推送当前 pending 的工具审批列表,client 据此恢复审批卡片
689
- control("pending_approvals_push", {
690
- sessionId: z6.string(),
691
- approvals: z6.array(z6.object({
692
- requestId: z6.string(),
693
- toolName: z6.string(),
694
- input: z6.record(z6.string(), z6.unknown())
695
- }))
696
- }, "proxy_to_client"),
697
- // 恢复会话时推送历史消息,proxy -> client
698
- control("session_history_messages", {
699
- ...RequestIdShape,
700
- sessionId: z6.string(),
701
- before: z6.string().optional(),
702
- messages: z6.array(SessionHistoryMessageSchema),
703
- hasMore: z6.boolean().optional(),
704
- nextBefore: z6.string().optional()
705
- }, "proxy_to_client"),
706
- // proxy 重连后同步活跃 session 列表给 relay
707
- control("session_sync", {
708
- sessions: z6.array(z6.object({
709
- id: z6.string(),
710
- mode: z6.enum(["pty", "json"]),
711
- provider: z6.enum(["claude", "codex"]),
712
- ptyOwner: z6.enum(["local-terminal", "proxy-hosted"]).optional(),
713
- state: z6.string()
714
- }))
715
- }),
716
- // PTY 会话订阅,client -> proxy,触发 terminal serialize() 返回当前状态
717
- control("session_subscribe", { sessionId: z6.string(), requestId: z6.string().optional() }, "client_to_proxy"),
718
- // PTY 会话快照,proxy -> client,serialize() 的全量终端状态
719
- control("session_snapshot", {
720
- sessionId: z6.string(),
721
- cols: z6.number().int().positive(),
722
- rows: z6.number().int().positive(),
723
- data: z6.string(),
724
- outputSeq: z6.number().int().nonnegative(),
725
- requestId: z6.string().optional()
726
- }, "proxy_to_client")
727
- ];
728
- var relayControlSchemas = relayControlDefinitions.map((definition) => definition.schema);
729
- var RelayControlSchema = z6.discriminatedUnion("type", relayControlSchemas);
730
- var ProxyToClientRelayControlTypes = new Set(relayControlDefinitions.filter((definition) => definition.directions.has("proxy_to_client")).map((definition) => definition.type));
731
- var ClientToProxyRelayControlTypes = new Set(relayControlDefinitions.filter((definition) => definition.directions.has("client_to_proxy")).map((definition) => definition.type));
732
-
733
- // ../../packages/shared/dist/constants/session.js
734
- var SessionState = {
735
- IDLE: "idle",
736
- WORKING: "working",
737
- WAITING_APPROVAL: "waiting_approval",
738
- ERROR: "error",
739
- TERMINATED: "terminated"
740
- };
741
-
742
- // ../../packages/shared/dist/logger.js
743
- import { lstatSync, mkdirSync as mkdirSync2, readdirSync, renameSync, statSync, symlinkSync, unlinkSync } from "fs";
744
- import { homedir as homedir2 } from "os";
745
- import { basename, join } from "path";
746
- import pino from "pino";
747
- var DEFAULT_LOG_DIR = `${homedir2()}/.dev-anywhere/logs`;
748
- var DEFAULT_LOG_RETENTION = 50;
749
- var PROCESS_LOG_RUN_ID = sanitizeRunId(`${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-${process.pid}`);
750
- function sanitizeRunId(runId) {
751
- return runId.replace(/[^a-zA-Z0-9._-]/g, "_");
752
- }
753
- function linkLatestLog(logDir, name, filePath, runId) {
754
- const latestPath = join(logDir, `${name}.log`);
755
- try {
756
- const stat = lstatSync(latestPath);
757
- if (stat.isSymbolicLink()) {
758
- unlinkSync(latestPath);
759
- } else {
760
- renameSync(latestPath, join(logDir, `${name}-legacy-${runId}.log`));
761
- }
762
- } catch (err) {
763
- const code = err.code;
764
- if (code !== "ENOENT")
765
- return;
766
- }
767
- try {
768
- symlinkSync(basename(filePath), latestPath);
769
- } catch {
770
- }
771
- }
772
- function resolveRetention(retention) {
773
- if (retention === void 0)
774
- return DEFAULT_LOG_RETENTION;
775
- return Number.isFinite(retention) && retention >= 0 ? Math.floor(retention) : DEFAULT_LOG_RETENTION;
776
- }
777
- function pruneOldLogs(logDir, name, currentFilePath, retention) {
778
- const keep = resolveRetention(retention);
779
- if (keep === 0)
780
- return;
781
- const currentFileName = basename(currentFilePath);
782
- const prefix = `${name}-`;
783
- const candidates = readdirSync(logDir).filter((entry) => entry.startsWith(prefix) && entry.endsWith(".log") && entry !== currentFileName).map((entry) => {
784
- const path = join(logDir, entry);
785
- try {
786
- return { path, mtimeMs: statSync(path).mtimeMs };
787
- } catch {
788
- return null;
789
- }
790
- }).filter((entry) => entry !== null).sort((a, b) => b.mtimeMs - a.mtimeMs);
791
- for (const stale of candidates.slice(Math.max(0, keep - 1))) {
792
- try {
793
- unlinkSync(stale.path);
794
- } catch {
795
- }
796
- }
797
- }
798
- function buildPinoLogger(options) {
799
- const { name, level = "info", logDir = DEFAULT_LOG_DIR, retention, stdout = false, silent = false, sync = false } = options;
800
- if (silent) {
801
- return pino({ level: "silent" });
802
- }
803
- mkdirSync2(logDir, { recursive: true });
804
- const runId = PROCESS_LOG_RUN_ID;
805
- const filePath = join(logDir, `${name}-${runId}.log`);
806
- linkLatestLog(logDir, name, filePath, runId);
807
- pruneOldLogs(logDir, name, filePath, retention);
808
- const streams = [
809
- { stream: pino.destination({ dest: filePath, sync }) }
810
- ];
811
- if (stdout) {
812
- streams.unshift({ stream: process.stdout });
813
- }
814
- return pino({ level }, pino.multistream(streams));
815
- }
816
- function createLogger(options) {
817
- let real = null;
818
- const ensure = () => {
819
- if (!real)
820
- real = buildPinoLogger(options);
821
- return real;
822
- };
823
- return new Proxy(/* @__PURE__ */ Object.create(null), {
824
- get(_target, prop) {
825
- const target = ensure();
826
- const value = Reflect.get(target, prop, target);
827
- return typeof value === "function" ? value.bind(target) : value;
828
- },
829
- set(_target, prop, value) {
830
- return Reflect.set(ensure(), prop, value);
831
- },
832
- has(_target, prop) {
833
- return Reflect.has(ensure(), prop);
834
- },
835
- ownKeys() {
836
- return Reflect.ownKeys(ensure());
837
- },
838
- getOwnPropertyDescriptor(_target, prop) {
839
- return Reflect.getOwnPropertyDescriptor(ensure(), prop);
840
- }
841
- });
842
- }
843
-
844
- export {
845
- DEFAULT_PROXY_PROFILE,
846
- defaultHookPortForProfile,
847
- PROFILE_NAME,
848
- tildify,
849
- CONFIG_PATH,
850
- SOCK_PATH,
851
- PID_PATH,
852
- STOPPED_PATH,
853
- DESIRED_RELAY_PATH,
854
- SESSIONS_PATH,
855
- HOOK_REGISTRY_PATH,
856
- DATA_DIR,
857
- PROXY_ID_PATH,
858
- LOG_DIR,
859
- SERVICE_LOG_PATH,
860
- sessionPaths,
861
- isInitialized,
862
- initWorkspace,
863
- ensureProfileWorkspace,
864
- MessageEnvelopeSchema,
865
- buildMessage,
866
- ControlErrorCode,
867
- SessionState,
868
- createLogger
869
- };
870
- //# sourceMappingURL=chunk-QFYI6AMN.js.map