@leanandmean/coding-agent 0.74.1-scramjet.13 → 0.74.1-scramjet.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.
@@ -58,7 +58,7 @@ import { TreeSelectorComponent } from "./components/tree-selector.js";
58
58
  import { UserMessageComponent } from "./components/user-message.js";
59
59
  import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
60
60
  import { NspellProvider } from "./spellcheck.js";
61
- import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, initTheme, onThemeChange, setRegisteredThemes, setTheme, setThemeInstance, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
61
+ import { classifyBackgroundColor, detectThemeFromEnvironment, getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, initTheme, onThemeChange, setRegisteredThemes, setTheme, setThemeInstance, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
62
62
  function isExpandable(obj) {
63
63
  return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
64
64
  }
@@ -402,12 +402,38 @@ export class InteractiveMode {
402
402
  : "";
403
403
  console.log(theme.fg("dim", `Model scope: ${modelList}${cycleHint}`));
404
404
  }
405
- // Add header container as first child
405
+ // Add header container as first child (content built after theme detection below)
406
406
  this.ui.addChild(this.headerContainer);
407
- // Add header with keybindings from config (unless silenced)
407
+ this.ui.addChild(this.chatContainer);
408
+ this.ui.addChild(this.pendingMessagesContainer);
409
+ this.ui.addChild(this.statusContainer);
410
+ this.renderWidgets(); // Initialize with default spacer
411
+ this.ui.addChild(this.widgetContainerAbove);
412
+ this.ui.addChild(this.editorContainer);
413
+ this.ui.addChild(this.widgetContainerBelow);
414
+ this.ui.addChild(this.footer);
415
+ this.ui.setFocus(this.editor);
416
+ this.setupKeyHandlers();
417
+ this.setupEditorSubmitHandler();
418
+ // Start the UI before initializing extensions so session_start handlers can use interactive dialogs
419
+ this.ui.start();
420
+ this.isInitialized = true;
421
+ // Detect terminal background via OSC 11 if no stronger signal resolved synchronously.
422
+ // The constructor already initialized theme from explicit setting, COLORFGBG, or Apple Terminal
423
+ // heuristic (via getDefaultTheme). This step only fires when no explicit theme is set and
424
+ // detectThemeFromEnvironment() returned undefined (no env signal available).
425
+ if (!this.settingsManager.getTheme() && !detectThemeFromEnvironment()) {
426
+ const rgb = await this.ui.queryTerminalBackgroundColor({ timeoutMs: 100 });
427
+ if (rgb) {
428
+ const detected = classifyBackgroundColor(rgb);
429
+ if (detected !== "dark") {
430
+ setTheme(detected);
431
+ }
432
+ }
433
+ }
434
+ // Build themed header content (after theme detection so colors are correct)
408
435
  if (this.options.verbose || !this.settingsManager.getQuietStartup()) {
409
436
  const logo = theme.bold(theme.fg("accent", APP_NAME)) + theme.fg("dim", ` v${this.version}`);
410
- // Build startup instructions using keybinding hint helpers
411
437
  const hint = (keybinding, description) => keyHint(keybinding, description);
412
438
  const expandedInstructions = [
413
439
  hint("app.interrupt", "to interrupt"),
@@ -442,30 +468,14 @@ export class InteractiveMode {
442
468
  // SCRAMJET-DIVERGENCE: rebrand Pi → APP_NAME.
443
469
  `${APP_NAME} can explain its own features and look up its docs. Ask it how to use or extend ${APP_NAME}.`);
444
470
  this.builtInHeader = new ExpandableText(() => `${logo}\n${compactInstructions}\n${compactOnboarding}\n\n${onboarding}`, () => `${logo}\n${expandedInstructions}\n\n${onboarding}`, this.getStartupExpansionState(), 1, 0);
445
- // Setup UI layout
446
471
  this.headerContainer.addChild(new Spacer(1));
447
472
  this.headerContainer.addChild(this.builtInHeader);
448
473
  this.headerContainer.addChild(new Spacer(1));
449
474
  }
450
475
  else {
451
- // Minimal header when silenced
452
476
  this.builtInHeader = new Text("", 0, 0);
453
477
  this.headerContainer.addChild(this.builtInHeader);
454
478
  }
455
- this.ui.addChild(this.chatContainer);
456
- this.ui.addChild(this.pendingMessagesContainer);
457
- this.ui.addChild(this.statusContainer);
458
- this.renderWidgets(); // Initialize with default spacer
459
- this.ui.addChild(this.widgetContainerAbove);
460
- this.ui.addChild(this.editorContainer);
461
- this.ui.addChild(this.widgetContainerBelow);
462
- this.ui.addChild(this.footer);
463
- this.ui.setFocus(this.editor);
464
- this.setupKeyHandlers();
465
- this.setupEditorSubmitHandler();
466
- // Start the UI before initializing extensions so session_start handlers can use interactive dialogs
467
- this.ui.start();
468
- this.isInitialized = true;
469
479
  // Initialize extensions first so resources are shown before messages
470
480
  await this.rebindCurrentSession();
471
481
  // Render initial messages AFTER showing loaded resources