nyxcore-systems
4 min read

A Late-Night Sprint: Unifying UI, Smarter AI, and Taming Deployment Gremlins

A deep dive into a recent development session, covering a significant UI component migration, the introduction of intelligent AI model recommendations, and overcoming common deployment challenges.

refactoringUI/UXAILLMdeploymentdockerdevelopment-log

It was late, the kind of late where the only sounds are the hum of your server and the click of your keyboard. The mission for the evening: a final push to migrate our ProviderModelPicker UI component across the remaining pages, ensure a critical AI workflow was humming, and ship it all to production. What started as a focused task evolved into a journey through UI consolidation, intelligent AI model selection, and a few valuable lessons learned about deployment and large language model interactions.

The Grand Unification: ProviderModelPicker Takes Center Stage

One of the most satisfying parts of any refactor is watching disparate, redundant code coalesce into a single, elegant solution. Our ProviderModelPicker component was designed to be the single source of truth for selecting AI providers and models throughout our application. This session was about bringing that vision to full fruition.

We tackled three key pages, each previously sporting its own flavor of model selection logic:

  • src/app/(dashboard)/dashboard/auto-fix/page.tsx: A robust auto-fix interface, now shedding 52 lines of custom button grid logic.
  • src/app/(dashboard)/dashboard/workflows/new/page.tsx: The entry point for creating new workflows, now 61 lines leaner.
  • src/app/(dashboard)/dashboard/projects/[id]/page.tsx: Our comprehensive project detail page, which previously hosted complex blog and enrichment pickers, saw a massive reduction of 220 lines!

The result? A cleaner codebase, a more consistent user experience, and a much happier future self when it comes to maintenance. With commit a25f6b5 ("feat: migrate remaining pages to ProviderModelPicker component"), the migration was complete, and the old, sprawling src/components/discussion/provider-picker.tsx (183 lines!) was finally retired and deleted.

Under the Hood: The Brains Behind Smart AI Model Selection

Beyond the UI, a significant improvement landed in our AI workflow engine: intelligent provider and model recommendation. Our goal is to ensure that for any given step in a workflow, the optimal LLM is automatically suggested.

We introduced src/server/services/provider-recommendation.ts, a new service designed to auto-recommend the best provider/model based on the type of step:

  • LLM-intensive tasks: Default to google/gemini-2.5-pro for its advanced reasoning capabilities.
  • Review/critique steps: Opt for anthropic/claude-sonnet-4-6, known for its strong conversational and analytical prowess.
  • Fast, lightweight operations: Utilize google/gemini-2.5-flash for speed and cost-effectiveness.

This service was then wired into our action-points.ts router, ensuring both createWorkflow and createGroupWorkflow benefit from these smart defaults. This isn't just about convenience; it's about optimizing performance, cost, and output quality across our diverse AI-powered features.

Enriching the AI Experience: Wisdom Sources and Truncation Tales

Our note-enrichment.ts service, responsible for providing context to our AI models, also received a significant upgrade. We expanded its "wisdom sources" to include:

  • consolidations
  • code_patterns
  • workflow_insights
  • memory_entries

This means our AI now has a much richer tapestry of information to draw from when generating insights and action points.

However, this enhancement brought a classic LLM challenge to the forefront: JSON truncation. When feeding long notes to the enrichment LLM call with a maxTokens limit of 4096, the JSON output would often be cut off mid-parse. This resulted in raw, incomplete JSON displayed in the UI and, critically, zero action points being extracted.

Lesson Learned: Always account for the full potential output size when interacting with LLMs, especially when expecting structured data like JSON.

Our solution involved:

  1. Increasing maxTokens: Bumping it up to 16384 dramatically reduced truncation incidents.
  2. Robust Recovery Parser: Implementing a regex-based recovery parser that can gracefully handle partially truncated JSON, ensuring we still extract as much valid data as possible.

This fix was crucial for the reliability of our AI-driven insights. We also took the opportunity to improve our action point extraction prompt, instructing the LLM to scan every subsection and re-scan for verification, leading to more comprehensive and accurate results.

Deployment Adventures: Taming the Docker Beast

No late-night session is complete without a minor deployment hiccup. Earlier in the day, an attempt to deploy with docker compose up -d app while an old container was still running resulted in the dreaded Conflict. The container name is already in use error.

While a quick docker compose down app && docker compose up -d app resolved it then, it's a good reminder of Docker's lifecycle management. Thankfully, for this session's deployment, the Recreate step worked smoothly, indicating it might have been a transient issue or a specific state from the earlier session. It's a small detail, but understanding these little quirks is vital for smooth operations.

Current Status and The Road Ahead

As the night winds down, the system is purring. All UI migrations are committed and deployed successfully. Our Ipcha Mistabra workflow (b29285b4-401b-4f50-a1d6-e739ca89b1ef), a 12-step beast of a process, is currently at step 7, actively utilizing the new auto-recommendation features (Gemini 2.5 Pro for LLM steps, Claude Sonnet 4-6 for reviews).

Immediate next steps include:

  • Monitoring the Ipcha Mistabra workflow to ensure it progresses smoothly through to the synthesis step.
  • Cleaning up old tRPC procedures like discussions.availableProviders that are now obsolete.
  • Exploring new models like Kimi (kimi-k2-0711-preview) for review preferences.
  • Laying the groundwork for "Bring Your Own Key" (BYOK) functionality by wiring userId into provider resolution.
  • Adding RLS policies for our project_syncs table to enhance security.

It's been a productive session, pushing the boundaries of our AI capabilities while refining our codebase. The journey continues, one commit, one deploy, and one late-night insight at a time.