Skip to content

feat: enable AIPG_DEBUGGING_PORT in packaged builds + rewire --start-page flag#241

Merged
mschuettlerTNG merged 3 commits into
TNG:devfrom
rwest-interactive:feat/rxt-default-imagegen-and-cdp-envvar
Jun 1, 2026
Merged

feat: enable AIPG_DEBUGGING_PORT in packaged builds + rewire --start-page flag#241
mschuettlerTNG merged 3 commits into
TNG:devfrom
rwest-interactive:feat/rxt-default-imagegen-and-cdp-envvar

Conversation

@kyleriemensnider
Copy link
Copy Markdown

@kyleriemensnider kyleriemensnider commented May 29, 2026

Summary

Two small patches for using AI Playground as a programmable demo target.
Coordinated with Markus via email on 2026-05-29.

feat(debug): enable AIPG_DEBUGGING_PORT in packaged builds

Drops the !app.isPackaged guard around the existing env-var-gated
Chrome DevTools Protocol port. The env var itself stays opt-in
(off by default), so packaged builds gain the existing dev capability
without changing the default security posture.

Use case: an external controller process (an automation runner)
needs a stable, packaged build to attach CDP and observe / steer the
renderer in production-shaped environments.

feat(launcher): rewire --start-page flag to land on requested mode

The getInitialPage IPC handler was returning the legacy AipgPage
vocabulary (create | enhance | answer | learn-more), which no longer
matches the renderer's ModeType (chat | imageGen | imageEdit | video).
The renderer never consumed the IPC result, so --start-page was
effectively dead in v3.x.

  • main process: validate the parsed --start-page= value against
    ModeType, return 'chat' as the safe fallback
  • env.d.ts: switch getInitialPage's return type to
    Promise<ModeType>, drop the now-unused AipgPage alias
  • renderer entry: top-level await getInitialPage() alongside the
    existing getDemoModeSettings() call, then route the result through
    promptStore.setCurrentMode() so the mode change also picks up the
    last-used preset for that category

Test plan

  • npm run typecheck clean against tng/dev
  • npm run build produces a clean NSIS installer
    (AI Playground-3.1.1-beta.exe, ~211MB)
  • Launching the packaged exe with AIPG_DEBUGGING_PORT=9223
    exposes the DevTools port; confirmed via CDP /json/version
  • --start-page=imageGen lands the renderer on Image Gen;
    --start-page=chat lands on Chat — both verified visually
    against the installed 3.1.1-beta build

Both commits are DCO sign-off compliant.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved validation and error handling for initial page startup configuration.
  • Improvements

    • Optimized concurrent loading of application settings and demo mode configuration during startup for faster initialization.

Review Change Stack

Drop the `!app.isPackaged` guard so the existing env-var-gated Chrome
DevTools Protocol port works in packaged builds too. The env var
itself remains opt-in (off by default), so this extends an existing
dev capability into a distribution channel without changing the
default security posture.

Use case: an external controller process (e.g. an automation runner)
needs a stable, packaged build to attach CDP and observe / steer the
renderer in production-shaped environments.

Signed-off-by: kyleriemensnider <kyle.riemensnider@gmail.com>
The getInitialPage IPC handler still returned the legacy AipgPage
vocabulary (`create | enhance | answer | learn-more`), which no
longer matches the renderer's ModeType (`chat | imageGen | imageEdit
| video`). The renderer never consumed the IPC result, so the
--start-page CLI flag was effectively dead in v3.x.

Changes:
- main process: validate the parsed --start-page= value against
  ModeType and return 'chat' as the safe fallback.
- env.d.ts: switch getInitialPage's return type to Promise<ModeType>
  and drop the now-unused AipgPage alias.
- renderer entry: top-level await getInitialPage() alongside the
  existing getDemoModeSettings() call, then route the result through
  promptStore.setCurrentMode() so the mode change also picks up the
  last-used preset for that category.

Verification: launching with --start-page=imageGen lands the renderer
on Image Gen; --start-page=chat lands on Chat; missing or invalid
values fall back to Chat without crashing.

Signed-off-by: kyleriemensnider <kyle.riemensnider@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Warning

Review limit reached

@kyleriemensnider, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 45 minutes and 17 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 40796c79-0e97-429c-8958-fddaaf36e2f4

📥 Commits

Reviewing files that changed from the base of the PR and between 257bfec and 906116c.

📒 Files selected for processing (3)
  • WebUI/electron/main.ts
  • WebUI/src/env.d.ts
  • WebUI/src/main.ts
📝 Walkthrough

Walkthrough

The PR refactors initial page mode selection from deprecated AipgPage type to restricted ModeType values (chat, imageGen, imageEdit, video). Electron's IPC handler validates --start-page arguments, renderer startup concurrently initializes demo settings and fetches the validated mode, and remote debugging is simplified to enable based on environment variable alone.

Changes

Initial Page Mode Selection and Debugging Configuration

Layer / File(s) Summary
Type contract alignment
WebUI/src/env.d.ts
Deprecated AipgPage backward-compatibility type is removed. Window.getInitialPage return type changes from Promise<AipgPage> to Promise<ModeType>, aligning renderer typing with restricted mode values.
Electron initial page validation
WebUI/electron/main.ts
IPC handler getInitialPage parses --start-page=<mode> from process.argv, validates against allowed ModeType values (chat, imageGen, imageEdit, video), and defaults to 'chat' when absent or invalid.
Renderer startup mode initialization
WebUI/src/main.ts
Startup concurrently fetches demo settings and initial page via Promise.all, sets window.__AIPG_DEMO_MODE__ from settings, and conditionally updates prompt store current mode when initial page is not 'chat'.
Remote debugging configuration
WebUI/electron/main.ts
Remote debugging port is enabled whenever process.env.AIPG_DEBUGGING_PORT is present, without requiring !app.isPackaged condition.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • TNG/AI-Playground#198: Overlaps on enabling --remote-debugging-port based on AIPG_DEBUGGING_PORT environment variable in electron startup.

Suggested reviewers

  • mschuettlerTNG

Poem

🐰 The modes now flow through types so clear,
Chat, image-gen, and edit appear,
Validation guards each starting page,
While debug ports emerge, no longer caged!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes both main changes: enabling AIPG_DEBUGGING_PORT in packaged builds and rewiring the --start-page flag to work with current UI modes.
Description check ✅ Passed The description covers the key sections: summary, rationale for each patch, implementation details, and comprehensive testing. However, the formal checklist items are not explicitly marked as completed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
WebUI/src/main.ts (1)

6-6: ⚡ Quick win

Use the @ alias for this new store import.

This new relative import is outside the WebUI import convention and will be more brittle under moves/renames.

Suggested change
-import { usePromptStore } from './assets/js/store/promptArea'
+import { usePromptStore } from '`@/assets/js/store/promptArea`'

As per coding guidelines, WebUI/**/*.{ts,tsx,js,vue}: Use path alias @ → ./src and electron → ./electron in imports.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@WebUI/src/main.ts` at line 6, The import in main.ts is using a brittle
relative path for the new store; replace the relative import of usePromptStore
with the project path alias form (usePromptStore from
'`@/assets/js/store/promptArea`') so it follows the WebUI import convention and
remains stable under file moves/renames; update the import statement that
currently references './assets/js/store/promptArea' to use the '@' alias and
keep the same exported symbol usePromptStore.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@WebUI/electron/main.ts`:
- Around line 1010-1014: The getInitialPage IPC handler currently returns only a
ModeType and conflates three cases (no flag, invalid flag, explicit
--start-page=chat); change ipcMain.handle('getInitialPage') to return a
structured object (e.g., { success: boolean, mode?: ModeType, requested?:
boolean, error?: string }) that preserves whether the flag was provided and
whether it was valid; validate the parsed startPageArg, set requested = true
when the flag exists, set mode to the validated ModeType or leave undefined and
return success: false with an error message for invalid values, and update the
renderer and type definitions (ModeType contract in env.d.ts/main.ts) to consume
this new response and follow the { success, error? } IPC pattern.

In `@WebUI/src/main.ts`:
- Around line 8-11: Wrap the parallel IPC startup calls to
window.electronAPI.getDemoModeSettings() and window.electronAPI.getInitialPage()
(the const [settings, initialPage] = await Promise.all([...]) line) in a
try/catch so rejections won't abort module evaluation; on error console.error()
the caught error and assign safe fallback values for settings and initialPage
(e.g., defaults that allow the renderer to mount) before continuing so startup
remains recoverable.

---

Nitpick comments:
In `@WebUI/src/main.ts`:
- Line 6: The import in main.ts is using a brittle relative path for the new
store; replace the relative import of usePromptStore with the project path alias
form (usePromptStore from '`@/assets/js/store/promptArea`') so it follows the
WebUI import convention and remains stable under file moves/renames; update the
import statement that currently references './assets/js/store/promptArea' to use
the '@' alias and keep the same exported symbol usePromptStore.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1473c55e-d3b4-47c8-8dbd-e3c94f5ed52f

📥 Commits

Reviewing files that changed from the base of the PR and between 290be96 and 257bfec.

📒 Files selected for processing (3)
  • WebUI/electron/main.ts
  • WebUI/src/env.d.ts
  • WebUI/src/main.ts

Comment thread WebUI/electron/main.ts Outdated
Comment on lines +1010 to +1014
ipcMain.handle('getInitialPage', (): ModeType => {
const validModes: ModeType[] = ['chat', 'imageGen', 'imageEdit', 'video']
const startPageArg = process.argv.find((arg) => arg.startsWith('--start-page='))
return startPageArg ? startPageArg.split('=')[1] : 'create'
const parsed = startPageArg?.split('=')[1]
return validModes.includes(parsed as ModeType) ? (parsed as ModeType) : 'chat'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Preserve whether --start-page was actually requested.

This handler folds “no flag”, “invalid flag”, and explicit --start-page=chat into the same 'chat' value. The renderer now skips applying 'chat', so a persisted non-chat mode can survive even when the user explicitly asked for chat. Return a structured result that distinguishes those cases instead of a bare ModeType.

Suggested direction
-  ipcMain.handle('getInitialPage', (): ModeType => {
-    const validModes: ModeType[] = ['chat', 'imageGen', 'imageEdit', 'video']
-    const startPageArg = process.argv.find((arg) => arg.startsWith('--start-page='))
-    const parsed = startPageArg?.split('=')[1]
-    return validModes.includes(parsed as ModeType) ? (parsed as ModeType) : 'chat'
-  })
+  ipcMain.handle('getInitialPage', () => {
+    const validModes = new Set<ModeType>(['chat', 'imageGen', 'imageEdit', 'video'])
+    const startPageArg = process.argv.find((arg) => arg.startsWith('--start-page='))
+    const parsed = startPageArg?.split('=')[1]
+
+    if (!startPageArg) {
+      return { success: true, page: null }
+    }
+
+    if (parsed && validModes.has(parsed as ModeType)) {
+      return { success: true, page: parsed as ModeType }
+    }
+
+    return { success: false, page: 'chat', error: 'Invalid --start-page value' }
+  })

WebUI/src/env.d.ts and WebUI/src/main.ts would need the matching contract update.

As per coding guidelines, WebUI/electron/main.ts: IPC handlers must return { success: boolean, error?: string } pattern for error propagation.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ipcMain.handle('getInitialPage', (): ModeType => {
const validModes: ModeType[] = ['chat', 'imageGen', 'imageEdit', 'video']
const startPageArg = process.argv.find((arg) => arg.startsWith('--start-page='))
return startPageArg ? startPageArg.split('=')[1] : 'create'
const parsed = startPageArg?.split('=')[1]
return validModes.includes(parsed as ModeType) ? (parsed as ModeType) : 'chat'
ipcMain.handle('getInitialPage', () => {
const validModes = new Set<ModeType>(['chat', 'imageGen', 'imageEdit', 'video'])
const startPageArg = process.argv.find((arg) => arg.startsWith('--start-page='))
const parsed = startPageArg?.split('=')[1]
if (!startPageArg) {
return { success: true, page: null }
}
if (parsed && validModes.has(parsed as ModeType)) {
return { success: true, page: parsed as ModeType }
}
return { success: false, page: 'chat', error: 'Invalid --start-page value' }
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@WebUI/electron/main.ts` around lines 1010 - 1014, The getInitialPage IPC
handler currently returns only a ModeType and conflates three cases (no flag,
invalid flag, explicit --start-page=chat); change
ipcMain.handle('getInitialPage') to return a structured object (e.g., { success:
boolean, mode?: ModeType, requested?: boolean, error?: string }) that preserves
whether the flag was provided and whether it was valid; validate the parsed
startPageArg, set requested = true when the flag exists, set mode to the
validated ModeType or leave undefined and return success: false with an error
message for invalid values, and update the renderer and type definitions
(ModeType contract in env.d.ts/main.ts) to consume this new response and follow
the { success, error? } IPC pattern.

Comment thread WebUI/src/main.ts
Comment on lines +8 to +11
const [settings, initialPage] = await Promise.all([
window.electronAPI.getDemoModeSettings(),
window.electronAPI.getInitialPage(),
])
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Catch startup IPC failures and fall back to safe defaults.

If either IPC call rejects here, top-level module evaluation aborts and the renderer never mounts. This needs a try/catch with logging and fallback values so startup stays recoverable.

Suggested change
-const [settings, initialPage] = await Promise.all([
-  window.electronAPI.getDemoModeSettings(),
-  window.electronAPI.getInitialPage(),
-])
+let settings: DemoModeSettings = {
+  isDemoModeEnabled: false,
+  demoModeResetInSeconds: null,
+}
+let initialPage: ModeType | null = null
+
+try {
+  ;[settings, initialPage] = await Promise.all([
+    window.electronAPI.getDemoModeSettings(),
+    window.electronAPI.getInitialPage(),
+  ])
+} catch (error) {
+  console.error('Failed to load startup state', error)
+}

As per coding guidelines, Wrap async operations in try/catch blocks and Log errors with console.error().

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [settings, initialPage] = await Promise.all([
window.electronAPI.getDemoModeSettings(),
window.electronAPI.getInitialPage(),
])
let settings: DemoModeSettings = {
isDemoModeEnabled: false,
demoModeResetInSeconds: null,
}
let initialPage: ModeType | null = null
try {
;[settings, initialPage] = await Promise.all([
window.electronAPI.getDemoModeSettings(),
window.electronAPI.getInitialPage(),
])
} catch (error) {
console.error('Failed to load startup state', error)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@WebUI/src/main.ts` around lines 8 - 11, Wrap the parallel IPC startup calls
to window.electronAPI.getDemoModeSettings() and
window.electronAPI.getInitialPage() (the const [settings, initialPage] = await
Promise.all([...]) line) in a try/catch so rejections won't abort module
evaluation; on error console.error() the caught error and assign safe fallback
values for settings and initialPage (e.g., defaults that allow the renderer to
mount) before continuing so startup remains recoverable.

…ge=chat

Addresses CodeRabbit's review of 257bfec. The previous handler returned
'chat' for three distinct cases (no flag / invalid flag / explicit
--start-page=chat). The renderer guard (`if (initialPage !== 'chat')`)
then skipped applying the mode in all three.

That was the intent for the "no flag" case — don't override the persisted
mode for a normal user launch — but it also silently broke the explicit
--start-page=chat case: after a previous imageGen session, launching
with --start-page=chat would land on the persisted imageGen because chat
was never applied.

This change returns null when --start-page is absent, and the renderer
applies whenever the value is non-null. Validated-mode and fallback
paths are unchanged.

- main process: return ModeType | null
- env.d.ts: getInitialPage(): Promise<ModeType | null>
- renderer entry: guard on null instead of comparing to 'chat'

Signed-off-by: kyleriemensnider <kyle.riemensnider@gmail.com>
@mschuettlerTNG mschuettlerTNG merged commit f373e85 into TNG:dev Jun 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants