@myerscarpenter/quest-dev 1.4.0 → 2.0.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 (151) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.github/workflows/docs.yml +45 -0
  3. package/.github/workflows/publish.yml +11 -1
  4. package/README.md +27 -0
  5. package/build/cast/decoder.d.ts +48 -0
  6. package/build/cast/decoder.d.ts.map +1 -0
  7. package/build/cast/decoder.js +152 -0
  8. package/build/cast/decoder.js.map +1 -0
  9. package/build/cast/session.d.ts +87 -0
  10. package/build/cast/session.d.ts.map +1 -0
  11. package/build/cast/session.js +565 -0
  12. package/build/cast/session.js.map +1 -0
  13. package/build/commands/logcat.d.ts.map +1 -1
  14. package/build/commands/logcat.js +7 -6
  15. package/build/commands/logcat.js.map +1 -1
  16. package/build/commands/open.d.ts.map +1 -1
  17. package/build/commands/open.js +9 -4
  18. package/build/commands/open.js.map +1 -1
  19. package/build/commands/screenshot.d.ts.map +1 -1
  20. package/build/commands/screenshot.js +17 -20
  21. package/build/commands/screenshot.js.map +1 -1
  22. package/build/commands/stay-awake.d.ts +2 -15
  23. package/build/commands/stay-awake.d.ts.map +1 -1
  24. package/build/commands/stay-awake.js +14 -77
  25. package/build/commands/stay-awake.js.map +1 -1
  26. package/build/daemon/cast-manager.d.ts +42 -0
  27. package/build/daemon/cast-manager.d.ts.map +1 -0
  28. package/build/daemon/cast-manager.js +243 -0
  29. package/build/daemon/cast-manager.js.map +1 -0
  30. package/build/daemon/client.d.ts +40 -0
  31. package/build/daemon/client.d.ts.map +1 -0
  32. package/build/daemon/client.js +133 -0
  33. package/build/daemon/client.js.map +1 -0
  34. package/build/daemon/daemon.d.ts +20 -0
  35. package/build/daemon/daemon.d.ts.map +1 -0
  36. package/build/daemon/daemon.js +130 -0
  37. package/build/daemon/daemon.js.map +1 -0
  38. package/build/daemon/deploy.d.ts +44 -0
  39. package/build/daemon/deploy.d.ts.map +1 -0
  40. package/build/daemon/deploy.js +230 -0
  41. package/build/daemon/deploy.js.map +1 -0
  42. package/build/daemon/logcat-manager.d.ts +39 -0
  43. package/build/daemon/logcat-manager.d.ts.map +1 -0
  44. package/build/daemon/logcat-manager.js +194 -0
  45. package/build/daemon/logcat-manager.js.map +1 -0
  46. package/build/daemon/server.d.ts +19 -0
  47. package/build/daemon/server.d.ts.map +1 -0
  48. package/build/daemon/server.js +482 -0
  49. package/build/daemon/server.js.map +1 -0
  50. package/build/daemon/stay-awake-manager.d.ts +22 -0
  51. package/build/daemon/stay-awake-manager.d.ts.map +1 -0
  52. package/build/daemon/stay-awake-manager.js +74 -0
  53. package/build/daemon/stay-awake-manager.js.map +1 -0
  54. package/build/index.js +285 -45
  55. package/build/index.js.map +1 -1
  56. package/build/public/dashboard.js +749 -0
  57. package/build/public/index.html +12 -0
  58. package/build/public/style.css +106 -0
  59. package/build/utils/adb.d.ts +12 -0
  60. package/build/utils/adb.d.ts.map +1 -1
  61. package/build/utils/adb.js +116 -51
  62. package/build/utils/adb.js.map +1 -1
  63. package/build/utils/casting-apk.d.ts +40 -0
  64. package/build/utils/casting-apk.d.ts.map +1 -0
  65. package/build/utils/casting-apk.js +252 -0
  66. package/build/utils/casting-apk.js.map +1 -0
  67. package/build/utils/config.d.ts +5 -3
  68. package/build/utils/config.d.ts.map +1 -1
  69. package/build/utils/config.js +18 -38
  70. package/build/utils/config.js.map +1 -1
  71. package/build/utils/exec.d.ts +5 -0
  72. package/build/utils/exec.d.ts.map +1 -1
  73. package/build/utils/exec.js +17 -0
  74. package/build/utils/exec.js.map +1 -1
  75. package/build/utils/filename.d.ts +7 -1
  76. package/build/utils/filename.d.ts.map +1 -1
  77. package/build/utils/filename.js +17 -2
  78. package/build/utils/filename.js.map +1 -1
  79. package/build/utils/filename.test.js +33 -1
  80. package/build/utils/filename.test.js.map +1 -1
  81. package/build/utils/jpeg-comment.d.ts +14 -0
  82. package/build/utils/jpeg-comment.d.ts.map +1 -0
  83. package/build/utils/jpeg-comment.js +28 -0
  84. package/build/utils/jpeg-comment.js.map +1 -0
  85. package/build/utils/test-properties.d.ts +34 -0
  86. package/build/utils/test-properties.d.ts.map +1 -0
  87. package/build/utils/test-properties.js +73 -0
  88. package/build/utils/test-properties.js.map +1 -0
  89. package/build/utils/verbose.d.ts +3 -0
  90. package/build/utils/verbose.d.ts.map +1 -0
  91. package/build/utils/verbose.js +13 -0
  92. package/build/utils/verbose.js.map +1 -0
  93. package/package.json +11 -5
  94. package/packages/cast2-protocol/README.md +86 -0
  95. package/packages/cast2-protocol/docs/_config.yml +4 -0
  96. package/packages/cast2-protocol/docs/feature-flags.md +102 -0
  97. package/packages/cast2-protocol/docs/index.md +24 -0
  98. package/packages/cast2-protocol/docs/open-investigations.md +149 -0
  99. package/packages/cast2-protocol/docs/protocol.md +602 -0
  100. package/packages/cast2-protocol/package.json +46 -0
  101. package/packages/cast2-protocol/src/constants.ts +65 -0
  102. package/packages/cast2-protocol/src/index.ts +7 -0
  103. package/packages/cast2-protocol/src/mgik.ts +69 -0
  104. package/packages/cast2-protocol/src/mud.ts +294 -0
  105. package/packages/cast2-protocol/src/pose.ts +99 -0
  106. package/packages/cast2-protocol/src/resolutions.ts +34 -0
  107. package/packages/cast2-protocol/src/types.ts +64 -0
  108. package/packages/cast2-protocol/src/xrsp.ts +73 -0
  109. package/packages/cast2-protocol/tests/mgik.test.ts +80 -0
  110. package/packages/cast2-protocol/tests/mud.test.ts +295 -0
  111. package/packages/cast2-protocol/tests/pose.test.ts +173 -0
  112. package/packages/cast2-protocol/tests/xrsp.test.ts +90 -0
  113. package/packages/cast2-protocol/tsconfig.json +20 -0
  114. package/pnpm-workspace.yaml +2 -0
  115. package/src/cast/decoder.ts +178 -0
  116. package/src/cast/session.ts +708 -0
  117. package/src/commands/logcat.ts +6 -5
  118. package/src/commands/open.ts +10 -3
  119. package/src/commands/screenshot.ts +19 -13
  120. package/src/commands/stay-awake.ts +22 -91
  121. package/src/daemon/adbkit-apkreader.d.ts +14 -0
  122. package/src/daemon/cast-manager.ts +282 -0
  123. package/src/daemon/client.ts +166 -0
  124. package/src/daemon/daemon.ts +169 -0
  125. package/src/daemon/deploy.ts +307 -0
  126. package/src/daemon/logcat-manager.ts +229 -0
  127. package/src/daemon/server.ts +595 -0
  128. package/src/daemon/stay-awake-manager.ts +83 -0
  129. package/src/index.ts +340 -56
  130. package/src/public/dashboard.js +288 -0
  131. package/src/public/index.html +12 -0
  132. package/src/public/style.css +106 -0
  133. package/src/utils/adb.ts +129 -42
  134. package/src/utils/casting-apk.ts +276 -0
  135. package/src/utils/config.ts +18 -36
  136. package/src/utils/exec.ts +20 -0
  137. package/src/utils/filename.test.ts +41 -1
  138. package/src/utils/filename.ts +18 -2
  139. package/src/utils/jpeg-comment.ts +30 -0
  140. package/src/utils/test-properties.ts +94 -0
  141. package/src/utils/verbose.ts +14 -0
  142. package/tests/cast/auto-layer.test.ts +87 -0
  143. package/tests/cast/decoder.test.ts +82 -0
  144. package/tests/cast/session-restart.test.ts +107 -0
  145. package/tests/config.test.ts +17 -22
  146. package/tests/daemon/api-status.test.ts +82 -0
  147. package/tests/daemon/cast-manager.test.ts +69 -0
  148. package/tests/daemon/mjpeg-stream.test.ts +144 -0
  149. package/tests/daemon/pose-endpoint.test.ts +63 -0
  150. package/tests/daemon/start-guard.test.ts +77 -0
  151. package/vitest.config.ts +10 -0
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Deploy handler for the daemon.
3
+ * Extracts package name from APK, installs, launches, checks for crashes.
4
+ */
5
+ import { resolve } from "node:path";
6
+ import { existsSync, statSync } from "node:fs";
7
+ import { spawn } from "node:child_process";
8
+ import { execCommand, execCommandFull } from "../utils/exec.js";
9
+ import { verbose } from "../utils/verbose.js";
10
+ import { adbArgs } from "../utils/adb.js";
11
+ /**
12
+ * Extract package name from APK using aapt2 or aapt
13
+ */
14
+ async function extractPackageName(apkPath) {
15
+ // Try aapt2 first, then aapt
16
+ for (const tool of ["aapt2", "aapt"]) {
17
+ try {
18
+ const output = await execCommand(tool, ["dump", "badging", apkPath]);
19
+ const match = output.match(/package:\s*name='([^']+)'/);
20
+ if (match) {
21
+ return match[1];
22
+ }
23
+ }
24
+ catch {
25
+ verbose(`${tool} not found or failed, trying next`);
26
+ }
27
+ }
28
+ // Fallback: use adb shell to parse via pm on device (after install)
29
+ // But we need it before install, so try apkreader
30
+ try {
31
+ const ApkReader = (await import("adbkit-apkreader")).default;
32
+ const reader = await ApkReader.open(apkPath);
33
+ const manifest = await reader.readManifest();
34
+ return manifest.package;
35
+ }
36
+ catch {
37
+ throw new Error("Cannot extract package name from APK. Install aapt2 (Android build-tools) or adbkit-apkreader.");
38
+ }
39
+ }
40
+ async function installWithProgress(absPath, adbArgsList, hasIdsig) {
41
+ if (!hasIdsig) {
42
+ const result = await execCommandFull("adb", adbArgsList);
43
+ return { ...result, blocksTransferred: 0, totalBlocks: 0 };
44
+ }
45
+ return new Promise((resolve) => {
46
+ const env = { ...process.env, ADB_TRACE: "incremental" };
47
+ const proc = spawn("adb", adbArgsList, { stdio: "pipe", env });
48
+ let stdout = "";
49
+ let stderr = "";
50
+ let totalBlocks = 0;
51
+ let lastReported = 0;
52
+ let blocksTransferred = 0;
53
+ if (proc.stdout) {
54
+ proc.stdout.on("data", (data) => {
55
+ stdout += data.toString();
56
+ });
57
+ }
58
+ if (proc.stderr) {
59
+ proc.stderr.on("data", (data) => {
60
+ const chunk = data.toString();
61
+ stderr += chunk;
62
+ // Parse incremental progress: "in priority: 37904 of 52096"
63
+ const matches = chunk.matchAll(/in priority: (\d+) of (\d+)/g);
64
+ for (const match of matches) {
65
+ const current = parseInt(match[1], 10);
66
+ totalBlocks = parseInt(match[2], 10);
67
+ blocksTransferred++;
68
+ // Report every 10% or every 5000 blocks
69
+ if (totalBlocks > 0 && current - lastReported >= totalBlocks * 0.1) {
70
+ const pct = Math.round((current / totalBlocks) * 100);
71
+ process.stdout.write(`\r Streaming: ${current}/${totalBlocks} blocks (${pct}%)`);
72
+ lastReported = current;
73
+ }
74
+ }
75
+ });
76
+ }
77
+ proc.on("close", (code) => {
78
+ if (totalBlocks > 0) {
79
+ const kbTransferred = Math.round((blocksTransferred * 4096) / 1024);
80
+ console.log(`\r Transferred: ${blocksTransferred} blocks (~${kbTransferred}KB)`);
81
+ }
82
+ resolve({ stdout, stderr, code: code ?? 1, blocksTransferred, totalBlocks });
83
+ });
84
+ proc.on("error", (err) => {
85
+ resolve({ stdout, stderr: err.message, code: 1, blocksTransferred: 0, totalBlocks: 0 });
86
+ });
87
+ });
88
+ }
89
+ /**
90
+ * Run the full deploy sequence.
91
+ */
92
+ export async function deploy(options, stayAwake, logcat) {
93
+ const { apkPath, crashWaitMs = 5000, pin } = options;
94
+ const absPath = resolve(apkPath);
95
+ // Keep Quest awake FIRST — before anything else touches ADB.
96
+ // Large APK uploads over WiFi ADB fail if the Quest sleeps mid-transfer.
97
+ if (!stayAwake.isEnabled && pin) {
98
+ try {
99
+ await stayAwake.enable(pin);
100
+ }
101
+ catch (error) {
102
+ console.warn("Failed to enable stay-awake:", error.message);
103
+ }
104
+ }
105
+ // Validate APK exists
106
+ if (!existsSync(absPath)) {
107
+ return { ok: false, package: "", crashed: false, error: `APK not found: ${absPath}` };
108
+ }
109
+ // Warn if APK is stale (older than 1 minute — probably deploying old code)
110
+ const apkAge = Date.now() - statSync(absPath).mtimeMs;
111
+ if (apkAge > 60_000) {
112
+ const mins = Math.floor(apkAge / 60_000);
113
+ const secs = Math.floor((apkAge % 60_000) / 1000);
114
+ console.warn(`\n⚠️ APK is ${mins}m${secs}s old — you may be deploying stale code!\n`);
115
+ }
116
+ // Extract package name
117
+ let packageName;
118
+ try {
119
+ packageName = await extractPackageName(absPath);
120
+ console.log(`Package: ${packageName}`);
121
+ }
122
+ catch (error) {
123
+ return {
124
+ ok: false,
125
+ package: "",
126
+ crashed: false,
127
+ error: error.message,
128
+ };
129
+ }
130
+ // Force-stop existing app
131
+ try {
132
+ await execCommand("adb", adbArgs("shell", "am", "force-stop", packageName));
133
+ verbose(`Force-stopped ${packageName}`);
134
+ }
135
+ catch {
136
+ // App might not be running
137
+ }
138
+ // Install APK
139
+ const apkSizeMB = (statSync(absPath).size / 1_048_576).toFixed(1);
140
+ const hasIdsig = existsSync(`${absPath}.idsig`);
141
+ console.log(`Installing APK (${apkSizeMB} MB)${hasIdsig ? " [incremental]" : ""}...`);
142
+ const installStart = Date.now();
143
+ const installResult = await installWithProgress(absPath, adbArgs("install", "-r", absPath), hasIdsig);
144
+ const installSecs = ((Date.now() - installStart) / 1000).toFixed(1);
145
+ verbose("Install stdout:", installResult.stdout.trim());
146
+ verbose("Install stderr:", installResult.stderr.trim());
147
+ if (installResult.code !== 0) {
148
+ const detail = [installResult.stdout.trim(), installResult.stderr.trim()]
149
+ .filter(Boolean)
150
+ .join("\n");
151
+ return {
152
+ ok: false,
153
+ package: packageName,
154
+ crashed: false,
155
+ error: `Install failed (exit ${installResult.code}):\n${detail}`,
156
+ };
157
+ }
158
+ const apkSizeNum = parseFloat(apkSizeMB);
159
+ const installInfo = {
160
+ incremental: hasIdsig,
161
+ installSecs: parseFloat(installSecs),
162
+ apkSizeMB: apkSizeNum,
163
+ ...(installResult.totalBlocks > 0 ? {
164
+ blocksTransferred: installResult.blocksTransferred,
165
+ totalBlocks: installResult.totalBlocks,
166
+ bytesTransferred: installResult.blocksTransferred * 4096,
167
+ } : {}),
168
+ };
169
+ console.log(`APK installed (${installSecs}s)`);
170
+ // Start logcat capture (clears buffer first)
171
+ await logcat.start();
172
+ const logcatFile = logcat.status().file;
173
+ if (!logcatFile)
174
+ throw new Error("logcat started but no file created");
175
+ // Launch app
176
+ console.log("Launching app...");
177
+ try {
178
+ // Try to launch via monkey (works for any app with a launcher activity)
179
+ await execCommand("adb", adbArgs("shell", "monkey", "-p", packageName, "-c", "android.intent.category.LAUNCHER", "1"));
180
+ verbose(`Launched ${packageName}`);
181
+ }
182
+ catch (error) {
183
+ return {
184
+ ok: false,
185
+ package: packageName,
186
+ crashed: false,
187
+ logcatFile,
188
+ error: `Launch failed: ${error.message}`,
189
+ };
190
+ }
191
+ // Wait for potential crash
192
+ console.log(`Waiting ${crashWaitMs}ms for crash check...`);
193
+ await new Promise((r) => setTimeout(r, crashWaitMs));
194
+ // Check for crash in logcat
195
+ const { crashed, lines, reason, matchedLine, matchedPattern } = logcat.scanForCrash(200, packageName);
196
+ if (crashed) {
197
+ const detail = [
198
+ `Crash reason: ${reason ?? "unknown"}`,
199
+ `Matched pattern: /${matchedPattern}/`,
200
+ `Triggered by line: ${matchedLine}`,
201
+ ].join("\n");
202
+ return {
203
+ ok: false,
204
+ package: packageName,
205
+ crashed: true,
206
+ logcatLines: lines,
207
+ logcatFile,
208
+ error: detail,
209
+ };
210
+ }
211
+ // Verify process is still running
212
+ const psResult = await execCommandFull("adb", adbArgs("shell", "pidof", packageName));
213
+ const pid = psResult.stdout.trim();
214
+ const processAlive = psResult.code === 0 && pid.length > 0;
215
+ if (!processAlive) {
216
+ // Process died without obvious crash pattern
217
+ const tail = logcat.readTail(100);
218
+ return {
219
+ ok: false,
220
+ package: packageName,
221
+ crashed: true,
222
+ logcatLines: tail,
223
+ logcatFile,
224
+ error: `Process not running (pidof exit=${psResult.code}, stdout="${pid}", stderr="${psResult.stderr.trim()}")`,
225
+ };
226
+ }
227
+ console.log(`Deploy successful: ${packageName} is running`);
228
+ return { ok: true, package: packageName, crashed: false, logcatFile, install: installInfo };
229
+ }
230
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/daemon/deploy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Logcat manager for the daemon process.
3
+ * Manages adb logcat capture to timestamped files.
4
+ */
5
+ export interface LogcatStatus {
6
+ capturing: boolean;
7
+ pid: number | null;
8
+ file: string | null;
9
+ size: string | null;
10
+ }
11
+ export declare class LogcatManager {
12
+ private proc;
13
+ private currentFile;
14
+ /** Whether logcat is currently capturing */
15
+ get isCapturing(): boolean;
16
+ /** Start logcat capture. Stops any previous capture first. */
17
+ start(filter?: string): Promise<{
18
+ file: string;
19
+ pid: number;
20
+ }>;
21
+ /** Stop logcat capture */
22
+ stop(): void;
23
+ /** Get capture status */
24
+ status(): LogcatStatus;
25
+ /** Read tail of current logcat file (reads only the last chunk, not the entire file) */
26
+ readTail(lineCount?: number): string[];
27
+ /** Scan tail for crash patterns, optionally scoped to a package name */
28
+ scanForCrash(lineCount?: number, packageName?: string): {
29
+ crashed: boolean;
30
+ lines: string[];
31
+ reason?: string;
32
+ matchedLine?: string;
33
+ matchedPattern?: string;
34
+ };
35
+ /** Cleanup: stop capture */
36
+ cleanup(): void;
37
+ private getFileStats;
38
+ }
39
+ //# sourceMappingURL=logcat-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logcat-manager.d.ts","sourceRoot":"","sources":["../../src/daemon/logcat-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuBH,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,WAAW,CAAuB;IAE1C,4CAA4C;IAC5C,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,8DAA8D;IACxD,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IA4DpE,0BAA0B;IAC1B,IAAI,IAAI,IAAI;IAYZ,yBAAyB;IACzB,MAAM,IAAI,YAAY;IAoBtB,wFAAwF;IACxF,QAAQ,CAAC,SAAS,GAAE,MAAW,GAAG,MAAM,EAAE;IAwB1C,wEAAwE;IACxE,YAAY,CAAC,SAAS,GAAE,MAAY,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE;IAyClK,4BAA4B;IAC5B,OAAO,IAAI,IAAI;IAIf,OAAO,CAAC,YAAY;CAmBrB"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Logcat manager for the daemon process.
3
+ * Manages adb logcat capture to timestamped files.
4
+ */
5
+ import { spawn } from "node:child_process";
6
+ import { existsSync, mkdirSync, openSync, closeSync, readSync, statSync, unlinkSync, symlinkSync, } from "node:fs";
7
+ import { join, resolve } from "node:path";
8
+ import { execCommand } from "../utils/exec.js";
9
+ import { verbose } from "../utils/verbose.js";
10
+ import { adbArgs } from "../utils/adb.js";
11
+ const LOG_DIR = resolve(process.env.LOG_DIR || "logs/logcat");
12
+ const LOGFILE_LINK = join(LOG_DIR, "latest.txt");
13
+ export class LogcatManager {
14
+ proc = null;
15
+ currentFile = null;
16
+ /** Whether logcat is currently capturing */
17
+ get isCapturing() {
18
+ return this.proc !== null && this.proc.exitCode === null;
19
+ }
20
+ /** Start logcat capture. Stops any previous capture first. */
21
+ async start(filter) {
22
+ // Stop existing capture
23
+ if (this.isCapturing) {
24
+ this.stop();
25
+ }
26
+ // Ensure log directory
27
+ if (!existsSync(LOG_DIR)) {
28
+ mkdirSync(LOG_DIR, { recursive: true });
29
+ }
30
+ // Generate filename
31
+ const timestamp = new Date()
32
+ .toISOString()
33
+ .replace(/[-:]/g, "")
34
+ .replace(/\..+/, "")
35
+ .replace("T", "_")
36
+ .slice(0, 15);
37
+ const logFile = join(LOG_DIR, `logcat_${timestamp}.txt`);
38
+ this.currentFile = logFile;
39
+ // Clear ring buffer (with timeout — adb logcat -c can hang on flaky connections)
40
+ try {
41
+ await Promise.race([
42
+ execCommand("adb", adbArgs("logcat", "-c")),
43
+ new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 5000)),
44
+ ]);
45
+ }
46
+ catch (error) {
47
+ verbose("Failed to clear logcat buffer:", error.message);
48
+ }
49
+ // Start logcat process
50
+ const args = adbArgs("logcat", "-v", "threadtime");
51
+ if (filter) {
52
+ args.push(filter);
53
+ }
54
+ const fd = openSync(logFile, "w");
55
+ this.proc = spawn("adb", args, {
56
+ stdio: ["ignore", fd, fd],
57
+ detached: true,
58
+ });
59
+ this.proc.unref();
60
+ closeSync(fd); // child process owns the fd now
61
+ // Update symlink
62
+ try {
63
+ if (existsSync(LOGFILE_LINK)) {
64
+ unlinkSync(LOGFILE_LINK);
65
+ }
66
+ symlinkSync(`logcat_${timestamp}.txt`, LOGFILE_LINK);
67
+ }
68
+ catch {
69
+ // Non-fatal
70
+ }
71
+ const pid = this.proc.pid;
72
+ console.log(`Logcat capture started (PID: ${pid}) → ${logFile}`);
73
+ return { file: logFile, pid };
74
+ }
75
+ /** Stop logcat capture */
76
+ stop() {
77
+ if (this.proc && this.proc.exitCode === null) {
78
+ try {
79
+ this.proc.kill("SIGTERM");
80
+ verbose(`Logcat capture stopped (PID: ${this.proc.pid})`);
81
+ }
82
+ catch {
83
+ // Already dead
84
+ }
85
+ }
86
+ this.proc = null;
87
+ }
88
+ /** Get capture status */
89
+ status() {
90
+ const capturing = this.isCapturing;
91
+ const file = this.currentFile;
92
+ let size = null;
93
+ if (file && existsSync(file)) {
94
+ const stats = this.getFileStats(file);
95
+ if (stats) {
96
+ size = stats.size;
97
+ }
98
+ }
99
+ return {
100
+ capturing,
101
+ pid: capturing ? this.proc.pid : null,
102
+ file,
103
+ size,
104
+ };
105
+ }
106
+ /** Read tail of current logcat file (reads only the last chunk, not the entire file) */
107
+ readTail(lineCount = 50) {
108
+ const file = this.currentFile;
109
+ if (!file || !existsSync(file)) {
110
+ return [];
111
+ }
112
+ try {
113
+ const stat = statSync(file);
114
+ // Read ~200 bytes per line as a rough estimate for logcat lines
115
+ const bytesToRead = Math.min(stat.size, lineCount * 200);
116
+ const buffer = Buffer.alloc(bytesToRead);
117
+ const fd = openSync(file, "r");
118
+ try {
119
+ readSync(fd, buffer, 0, bytesToRead, Math.max(0, stat.size - bytesToRead));
120
+ }
121
+ finally {
122
+ closeSync(fd);
123
+ }
124
+ const lines = buffer.toString("utf-8").split("\n");
125
+ return lines.slice(-lineCount);
126
+ }
127
+ catch {
128
+ return [];
129
+ }
130
+ }
131
+ /** Scan tail for crash patterns, optionally scoped to a package name */
132
+ scanForCrash(lineCount = 200, packageName) {
133
+ const tail = this.readTail(lineCount);
134
+ // Patterns that are app-specific (only match if they mention our package)
135
+ const pkgEscaped = packageName ? packageName.replace(/\./g, "\\.") : null;
136
+ const crashPatterns = [
137
+ { pattern: /FATAL EXCEPTION/i, label: "FATAL EXCEPTION" },
138
+ { pattern: /panicked at/i, label: "Rust panic" },
139
+ { pattern: /signal \d+ \(SIG/i, label: "signal/crash" },
140
+ { pattern: /Native crash/i, label: "native crash" },
141
+ // These patterns are scoped to our package to avoid false positives
142
+ // from other processes dying (e.g. com.oculus.assistant)
143
+ ...(pkgEscaped ? [
144
+ { pattern: new RegExp(`ANR in ${pkgEscaped}`, "i"), label: "ANR (not responding)" },
145
+ { pattern: new RegExp(`Process ${pkgEscaped}.* has died`, "i"), label: "process died" },
146
+ { pattern: new RegExp(`Force finishing activity.*${pkgEscaped}`, "i"), label: "force finishing activity" },
147
+ ] : [
148
+ { pattern: /ANR in/i, label: "ANR (not responding)" },
149
+ { pattern: /Process .+ has died/i, label: "process died" },
150
+ { pattern: /Force finishing activity/i, label: "force finishing activity" },
151
+ ]),
152
+ ];
153
+ for (const line of tail) {
154
+ for (const { pattern, label } of crashPatterns) {
155
+ if (pattern.test(line)) {
156
+ const idx = tail.indexOf(line);
157
+ return {
158
+ crashed: true,
159
+ lines: tail.slice(idx),
160
+ reason: label,
161
+ matchedLine: line.trim(),
162
+ matchedPattern: pattern.source,
163
+ };
164
+ }
165
+ }
166
+ }
167
+ return { crashed: false, lines: [] };
168
+ }
169
+ /** Cleanup: stop capture */
170
+ cleanup() {
171
+ this.stop();
172
+ }
173
+ getFileStats(filePath) {
174
+ try {
175
+ const stats = statSync(filePath);
176
+ const sizeInBytes = stats.size;
177
+ let sizeStr;
178
+ if (sizeInBytes < 1024) {
179
+ sizeStr = `${sizeInBytes}B`;
180
+ }
181
+ else if (sizeInBytes < 1024 * 1024) {
182
+ sizeStr = `${(sizeInBytes / 1024).toFixed(1)}K`;
183
+ }
184
+ else {
185
+ sizeStr = `${(sizeInBytes / (1024 * 1024)).toFixed(1)}M`;
186
+ }
187
+ return { size: sizeStr };
188
+ }
189
+ catch {
190
+ return null;
191
+ }
192
+ }
193
+ }
194
+ //# sourceMappingURL=logcat-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logcat-manager.js","sourceRoot":"","sources":["../../src/daemon/logcat-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Unified Fastify server for the quest-dev daemon.
3
+ * Hosts all endpoint groups: core, stay-awake, logcat, deploy, cast.
4
+ */
5
+ import { type FastifyInstance } from "fastify";
6
+ import type { StayAwakeManager } from "./stay-awake-manager.js";
7
+ import type { LogcatManager } from "./logcat-manager.js";
8
+ import type { CastManager } from "./cast-manager.js";
9
+ export interface DaemonServerOptions {
10
+ port: number;
11
+ host: string;
12
+ stayAwake: StayAwakeManager;
13
+ logcat: LogcatManager;
14
+ castManager: CastManager;
15
+ onActivity: () => void;
16
+ onShutdown: () => void;
17
+ }
18
+ export declare function createDaemonServer(options: DaemonServerOptions): Promise<FastifyInstance>;
19
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAC;AASxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKrD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,gBAAgB,CAAC;IAC5B,MAAM,EAAE,aAAa,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,eAAe,CAAC,CAijB1B"}