@jhizzard/termdeck 0.13.0 → 0.15.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.
@@ -15,7 +15,7 @@ const os = require('os');
15
15
  const path = require('path');
16
16
  const { resolveTheme } = require('./theme-resolver');
17
17
  const flashbackDiag = require('./flashback-diag');
18
- const claudeAdapter = require('./agent-adapters/claude');
18
+ const geminiAdapter = require('./agent-adapters/gemini');
19
19
  const { detectAdapter, getAdapterForSessionType } = require('./agent-adapters');
20
20
 
21
21
  // Strip ANSI escape codes for pattern matching
@@ -29,24 +29,31 @@ function stripAnsi(str) {
29
29
 
30
30
  // Pattern matchers for detecting terminal type and status.
31
31
  //
32
- // Sprint 44 T3: claudeCode patterns are owned by the Claude adapter at
33
- // ./agent-adapters/claude.js. This object continues to expose them under
34
- // the legacy `PATTERNS.claudeCode.*` shape so external callers
35
- // (tests/rcfile-noise.test.js, tests/analyzer-error-fixtures.test.js, the
36
- // rcfile-noise analyze.js fixture script) keep working without import
37
- // changes. Sprint 45 T4 removes this shim — new code should consume the
38
- // adapter directly via require('./agent-adapters/claude').
32
+ // Sprint 45 T4 removed the Sprint 44 T3 Claude shim (`PATTERNS.claudeCode.*`
33
+ // and `PATTERNS.errorLineStart`). Claude-specific regexes now live exclusively
34
+ // at ./agent-adapters/claude.js read via `claudeAdapter.patterns.*`. The
35
+ // `_detectErrors` and `_updateStatus` paths route through `getAdapterForSessionType`
36
+ // for any registered adapter.
37
+ //
38
+ // Sprint 45 T2 retains `PATTERNS.geminiCli` as a shim into the Gemini adapter
39
+ // for the one-release deprecation horizon — same pattern Sprint 44 T3 used.
40
+ // What stays in this file:
41
+ // • geminiCli — Sprint 45 T2 shim into ./agent-adapters/gemini.js
42
+ // • pythonServer — server SUBTYPE detection (no adapter; status-badge only)
43
+ // • shell — default fallback (no adapter)
44
+ // • error — cross-agent prose-shape primary error fallback (used
45
+ // by `_detectErrors` when the active adapter has no
46
+ // `patterns.error`, and exported for tests)
47
+ // • shellError — cross-agent Unix shell-error shapes (always tried as
48
+ // the secondary fallback in `_detectErrors`)
39
49
  const PATTERNS = {
40
- claudeCode: {
41
- prompt: claudeAdapter.patterns.prompt,
42
- thinking: claudeAdapter.patterns.thinking,
43
- editing: claudeAdapter.patterns.editing,
44
- tool: claudeAdapter.patterns.tool,
45
- idle: claudeAdapter.patterns.idle
46
- },
50
+ // Sprint 45 T2: geminiCli patterns are owned by the Gemini adapter at
51
+ // ./agent-adapters/gemini.js. Shim preserves the legacy
52
+ // `PATTERNS.geminiCli.{prompt,thinking}` shape — same regex objects, so
53
+ // any external reference equality holds.
47
54
  geminiCli: {
48
- prompt: /^gemini>\s/m,
49
- thinking: /\b(Generating|Working)\b/,
55
+ prompt: geminiAdapter.patterns.prompt,
56
+ thinking: geminiAdapter.patterns.thinking,
50
57
  },
51
58
  pythonServer: {
52
59
  uvicorn: /Uvicorn running on/,
@@ -90,17 +97,12 @@ const PATTERNS = {
90
97
  // child-process error reporting fire without depending on the line ALSO
91
98
  // containing the `No such file or directory` prose phrase.
92
99
  error: /(?:^|\n)\s*(?:Error:\s+\S|error:\s+\S|ERROR:\s+\S|Traceback \(most recent call last\):|npm ERR!|error\[E\d+\]:|Uncaught Exception|Fatal:|ENOENT:\s+\S|EACCES:\s+\S|ECONNREFUSED:\s+\S)/m,
93
- // Stricter line-anchored variant for Claude Code, whose tool output (grep
94
- // results, test logs, file contents) routinely mentions "Error" mid-line
95
- // without representing an actual failure of the agent itself.
96
- // Sprint 40 T2: added mixed-case `Fatal` (mirrors `fatal` / `FATAL`) and
97
- // the `npm ERR!` shape (special-cased outside the alternation because
98
- // `!` is not a word character so `\b` after `npm ERR!` doesn't match).
99
- // Sprint 44 T3: this regex is now owned by the Claude adapter
100
- // (./agent-adapters/claude.js patterns.error). The shim below preserves
101
- // the legacy PATTERNS.errorLineStart export — same regex object, so any
102
- // existing reference equality (e.g. `=== PATTERNS.errorLineStart`) holds.
103
- errorLineStart: claudeAdapter.patterns.error,
100
+ // Sprint 45 T4: the Claude-specific line-anchored variant
101
+ // (formerly `PATTERNS.errorLineStart`) is owned by the Claude adapter at
102
+ // ./agent-adapters/claude.js read via `claudeAdapter.patterns.error`.
103
+ // _detectErrors below routes through `getAdapterForSessionType` for
104
+ // claude-code sessions and falls through to PATTERNS.error / shellError
105
+ // for non-adapter sessions.
104
106
  // Sprint 33: PATTERNS.error misses the most common Unix shell errors —
105
107
  // `cat: /foo: No such file or directory`, `bash: foo: command not found`,
106
108
  // `rm: cannot remove ...: Permission denied`. These have a colon-prefix
@@ -255,20 +257,17 @@ class Session {
255
257
  }
256
258
 
257
259
  _detectType(data) {
258
- // Sprint 44 T3: registry-aware detection. detectAdapter() iterates
259
- // AGENT_ADAPTERS in declaration order and returns the first hit by
260
- // prompt regex OR command-string match. Sprint 44 lands Claude only
261
- // (so this returns the Claude adapter or undefined); Sprint 45 adds
262
- // Codex / Gemini / Grok adapters and the gemini fall-through below
263
- // moves into gemini.js.
260
+ // Sprint 44 T3 + Sprint 45: registry-aware detection. detectAdapter()
261
+ // iterates AGENT_ADAPTERS in declaration order and returns the first
262
+ // hit by prompt regex OR command-string match. Claude / Codex /
263
+ // Gemini / Grok all live in the registry now; only python-server
264
+ // (a non-CLI-agent type) stays here as in-file fall-through.
264
265
  const adapter = detectAdapter(data, this.meta.command);
265
266
  if (adapter) {
266
267
  this.meta.type = adapter.sessionType;
267
268
  return;
268
269
  }
269
- if (PATTERNS.geminiCli.prompt.test(data) || /gemini/i.test(this.meta.command)) {
270
- this.meta.type = 'gemini';
271
- } else if (
270
+ if (
272
271
  PATTERNS.pythonServer.uvicorn.test(data) ||
273
272
  PATTERNS.pythonServer.flask.test(data) ||
274
273
  PATTERNS.pythonServer.django.test(data) ||
@@ -282,12 +281,11 @@ class Session {
282
281
  const p = PATTERNS;
283
282
  const oldStatus = this.meta.status;
284
283
 
285
- // Sprint 44 T3: claude-code status detection now lives in the Claude
284
+ // Sprint 44 T3 + Sprint 45: per-agent status detection lives in each
286
285
  // adapter's `statusFor(data)` method. Returns { status, statusDetail }
287
286
  // on a match, null on no-change — preserves the original switch's
288
- // "leave status untouched if no claude pattern fires" semantics.
289
- // Other types (gemini, python-server, default shell) stay in-file
290
- // until Sprint 45 migrates them.
287
+ // "leave status untouched if no pattern fires" semantics. Only
288
+ // non-CLI-agent types (python-server + default shell) stay in-file.
291
289
  const adapter = getAdapterForSessionType(this.meta.type);
292
290
  if (adapter && typeof adapter.statusFor === 'function') {
293
291
  const result = adapter.statusFor(data);
@@ -297,16 +295,6 @@ class Session {
297
295
  }
298
296
  } else {
299
297
  switch (this.meta.type) {
300
- case 'gemini':
301
- if (p.geminiCli.thinking.test(data)) {
302
- this.meta.status = 'thinking';
303
- this.meta.statusDetail = 'Gemini is generating...';
304
- } else if (p.geminiCli.prompt.test(data)) {
305
- this.meta.status = 'idle';
306
- this.meta.statusDetail = 'Waiting for input';
307
- }
308
- break;
309
-
310
298
  case 'python-server':
311
299
  if (p.pythonServer.request.test(data)) {
312
300
  this.meta.status = 'active';
@@ -409,12 +397,12 @@ class Session {
409
397
  // (grep matches, test results, log dumps). Use a line-anchored pattern
410
398
  // for that session type so we don't flag content as failure.
411
399
  //
412
- // Sprint 44 T3: per-agent primary error pattern is now read off the
413
- // adapter (`patterns.error` + `patternNames.error`). Falls back to the
414
- // generic prose-shape PATTERNS.error when no adapter has claimed the
415
- // session type. The Claude adapter's `patterns.error` IS the same regex
416
- // object as PATTERNS.errorLineStart (the shim wires them together), so
417
- // existing `=== PATTERNS.errorLineStart` reference checks still hold.
400
+ // Sprint 44 T3 / Sprint 45 T4: per-agent primary error pattern is read
401
+ // off the adapter (`patterns.error` + `patternNames.error`). Falls back
402
+ // to the generic prose-shape PATTERNS.error when no adapter has claimed
403
+ // the session type. (Sprint 44 retained a `PATTERNS.errorLineStart` shim
404
+ // that pointed at the Claude adapter's regex; Sprint 45 T4 removed the
405
+ // shim read `claudeAdapter.patterns.error` directly when needed.)
418
406
  const adapter = getAdapterForSessionType(this.meta.type);
419
407
  const primaryPattern = adapter && adapter.patterns && adapter.patterns.error
420
408
  ? adapter.patterns.error