@rubytech/create-maxy-lite 0.1.13 → 0.1.14

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-lite",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Install maxy-lite on an Android phone: orchestrates proot-distro Ubuntu, glibc Node, claude, the web-chat relay, the vault and its bind-mount — run via npx in bare Termux.",
5
5
  "type": "module",
6
6
  "engines": {
@@ -36,6 +36,7 @@ const STATE_DIR = process.env.LITE_STATE_DIR || path.join(AGENT_HOME, '.maxy-lit
36
36
  const SESSION_FILE = path.join(STATE_DIR, 'session-id')
37
37
  const TAIL_MS = 250 // JSONL poll interval
38
38
  const QUIET_MS = 1500 // silence that ends a turn for op=done
39
+ const NO_REPLY_MS = 8000 // a turn with NO transcript growth this long = swallowed; surface why
39
40
 
40
41
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
41
42
 
@@ -89,9 +90,26 @@ const child = pty.spawn(CLAUDE_BIN, args, {
89
90
  cwd: AGENT_HOME,
90
91
  env: process.env,
91
92
  })
92
- // The pty is input-only for our purposes; draining stdout prevents backpressure
93
- // from stalling claude. Render comes from the JSONL, never these bytes.
94
- child.onData(() => {})
93
+ // Render comes from the JSONL, not these bytes but capture a bounded, sanitised
94
+ // sample of claude's own pty output so a swallow is diagnosable. It reveals a
95
+ // first-run trust/onboarding prompt eating the input, an error screen, or silence
96
+ // (input never submitted). Draining also prevents backpressure stalling claude.
97
+ let ptyBytes = 0
98
+ let turnPtyBase = 0
99
+ let ptySample = ''
100
+ const sanitizePty = (s) =>
101
+ s
102
+ .replace(/\x1b\[[0-9;?]*[A-Za-z]/g, '')
103
+ .replace(/\x1b[()][AB0]/g, '')
104
+ .replace(/[\r\n]+/g, ' ')
105
+ .replace(/[^\x20-\x7e]/g, '')
106
+ child.onData((d) => {
107
+ ptyBytes += d.length
108
+ ptySample = (ptySample + sanitizePty(d)).slice(-300) // most recent 300 printable chars
109
+ })
110
+ // Log the fresh claude screen once it has settled — a trust/onboarding prompt here
111
+ // explains a swallowed first message before any turn is even sent.
112
+ setTimeout(() => log('output', { turn: 0, ptyBytes, head: ptySample.slice(0, 300) }), 3000)
95
113
  child.onExit(({ exitCode }) => log('child-exit', { exitCode }))
96
114
  log('spawn', { turn: 0, pty: true, pid: child.pid })
97
115
 
@@ -162,9 +180,26 @@ setInterval(tail, TAIL_MS)
162
180
  // Gated on turnSawGrowth so a slow first JSONL write (cold start, discovery
163
181
  // latency) cannot mark the turn done before any reply has rendered.
164
182
  setInterval(() => {
165
- if (turnActive && turnSawGrowth && Date.now() - lastActivity > QUIET_MS) {
183
+ if (!turnActive) return
184
+ if (turnSawGrowth && Date.now() - lastActivity > QUIET_MS) {
166
185
  turnActive = false
167
186
  log('done', { turn, ranMs: Date.now() - turnStart })
187
+ } else if (!turnSawGrowth && Date.now() - turnStart > NO_REPLY_MS) {
188
+ // No transcript growth after the input → the message was swallowed. Surface the
189
+ // two facts that locate it: what claude actually emitted to its pty, and whether
190
+ // its transcript was even found (and if not, what dirs exist vs the one wanted).
191
+ turnActive = false
192
+ log('output', { turn, ptyBytes: ptyBytes - turnPtyBase, head: ptySample.slice(0, 300) })
193
+ if (!transcriptPath) {
194
+ let dirs = []
195
+ try {
196
+ dirs = fs.readdirSync(PROJECTS_DIR)
197
+ } catch {
198
+ /* PROJECTS_DIR absent */
199
+ }
200
+ log('jsonl-missing', { want: `${sessionId}.jsonl`, projectsDir: PROJECTS_DIR, dirs: `[${dirs.join(',')}]` })
201
+ }
202
+ log('done', { turn, ok: false, reason: 'no-transcript-growth', ranMs: Date.now() - turnStart })
168
203
  }
169
204
  }, 500)
170
205
 
@@ -180,6 +215,8 @@ function submitToAgent(text) {
180
215
  turnSawGrowth = false
181
216
  turnStart = Date.now()
182
217
  lastActivity = Date.now()
218
+ turnPtyBase = ptyBytes // baseline so op=output reports bytes claude emitted THIS turn
219
+ ptySample = ''
183
220
  log('inbound', { turn, chars: text.length })
184
221
  child.write(ptyLine(text))
185
222
  log('spawn', { turn, pty: true, pid: child.pid })