feat(prokube): add Kubeflow-ready Docker image with prefix-aware UI#2
Draft
feat(prokube): add Kubeflow-ready Docker image with prefix-aware UI#2
Conversation
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
Docker Image PublishedVersion: Image Tags
Full image URLs for copy/paste |
…n support - esbuild + SolidJS build system with PostCSS/Tailwind - Runtime prefix detection via window.__OPENCODE__.basePath - Dev server with API proxy for backend at 127.0.0.1:4096 - Improved SSE streaming through proxy with TransformStream - Session page with message sending and polling fallback - Markdown rendering for assistant messages - Full component library (layout, sidebar, session list)
- New ProviderProvider context for state management - Settings page for connecting providers via API key - Model picker dropdown in session header - Agent picker dropdown in session header - Provider status indicator in sidebar - Fix SSE proxy idleTimeout issue
- Add CSS design tokens for colors, backgrounds, borders - Redesign sidebar with cleaner, more elegant styling - Redesign settings page with tabs for providers/models/agents - Update session page to use CSS variables throughout - Update home page with consistent theming - Add /agent to dev proxy paths - Add null checks in SSE event handling
Shows the current project in the sidebar header with a dropdown listing all projects. Includes a hint that switching projects requires running opencode in the target folder since the backend is project-specific.
- Add directory-layout component that extracts directory from URL
- Add project-picker page for selecting from available projects
- Update SDK context to pass x-opencode-directory header
- Group sessions by project in sidebar with unique display names
- Add per-project session creation with always-visible + button
- Update routing to use /{base64Dir}/session/{id} pattern
- Add MCPProvider context for tracking server status - Add MCPDialog for connect/disconnect of servers - Add MCPAddDialog for adding new local/remote servers - Add MCP indicator in session header showing connection status - Add /mcp slash command for quick access
- Add environment variables support for local MCP servers - Add custom HTTP headers for remote MCP servers - Add OAuth configuration (client ID, secret, scope, toggle) - Add timeout setting for all server types - Add MCP Servers tab to Settings page with full server management - Export MCP config types from context for component use
- Multi-stage Dockerfile with Bun build and Alpine runtime - Bun-based UI server with API proxy (serve-ui.ts) - s6-overlay for process management - GitHub Actions workflow for GCP Artifact Registry - Supports NB_PREFIX for Kubeflow notebook URL prefixes
- Add OpenCode wordmark logo to home and session welcome screens - Replace project picker with PK logo in sidebar - Make model list clickable to select default model - Add settings button to home page - Add favicon and SVG assets - Add command context for future keyboard shortcuts
Keep only opencode-prefixable.yml for our Kubeflow image builds. Upstream workflows are not relevant for this fork.
Align with prokube-images workflow - always push to GCP Artifact Registry. Also adds PR comment with image tags.
In Kubeflow context, automatically redirect to the default home directory instead of showing 'No projects found' error.
- Strip base path prefix before checking API routes - Remove serverUrl injection (use window.location.origin instead) - Use prefixed path for EventSource SSE connection - Fix requests going directly to internal 127.0.0.1:4096
- Add error state and early return in sendMessage() when no model is selected - Prevents OpenCode from auto-selecting a broken provider (e.g., bedrock from MinIO AWS env vars) - Display API errors in message bubbles so users see why requests failed - Add hint text when providers are connected but no model is selected
Default to 'build' agent if none selected. OpenCode throws 'undefined is not an object (evaluating agent.name)' when no agent is provided.
- PK icon in header now links to homescreen (/) - Homescreen shows folder/project picker instead of auto-redirecting - Open Folder: search for existing folders using find API - Create Folder: navigate to new folder path in /home/jovyan/ - Recent Projects: list of previously used projects - Quick access link to home directory
- PK icon now navigates to basePath instead of hardcoded / - Current directory always appears in sidebar, even without sessions - Empty projects show 'No sessions yet' under the project name
- Remove Recent Projects from homescreen (was showing all historical projects) - Sidebar now shows only current project's sessions, not all projects - Add project name to sidebar header next to PK icon - PK icon links to homescreen to switch projects - Fix dev server API proxy to correctly strip base path prefix
- Store models per agent in modelsByAgent record instead of single selectedModel - Persist models to localStorage for each agent separately - Auto-load saved models on mount - Return correct model for currently selected agent via selectedModel getter - Matches behavior of original TUI where each agent remembers its model
- Add detailed logging for MCP server addition - Check server status after adding and throw specific errors - Show OAuth and connection errors to user - Clear previous errors when attempting to add server
When adding an MCP server via MCP.add(), the server was only added to memory state but not persisted to the config file. This caused the MCP.status() function to return undefined for the newly added server since it only reads from the config file. This fix adds Config.update() call to persist the MCP server configuration to the config file after successfully creating the client, ensuring the server appears in status checks and persists across restarts. Fixes issue where prokube UI would not show newly added MCP servers.
- Add environment variables table - Add fork & upstream sync strategy section - Remove redundant app-prefixable/AGENTS.md - Remove outdated app-prefixable/AGENT_PROMPT.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…kube This moves the mkdir and directory listing features from packages/ (upstream code) to prokube/, avoiding future rebase conflicts. Changes: - Add /api/prokube/mkdir and /api/prokube/list-dirs endpoints to serve-ui.ts (production) and dev.ts (development) - Add prokube-api.ts utility for frontend API calls - Update project-dialog.tsx and terminal.tsx to use new endpoints - Revert upstream changes in packages/opencode and packages/sdk Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Revert the MCP.add() config persistence change to keep upstream code unmodified. This feature may need to be reimplemented in prokube/ layer if still needed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8b004a2 to
a127440
Compare
- Add SessionSidebar component showing tasks and git branch - Fix processing state not resetting when switching sessions - Add /vcs to proxy paths in dev.ts and serve-ui.ts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When adding an MCP server via the UI, the server configuration was only added to memory but not persisted to the config file. Since mcp.status() reads from the config file to determine which servers to include in the response, newly added servers wouldn't show up. This fix persists the MCP config to the global config file before calling mcp.add, ensuring the server appears in the status list. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add clear documentation about the separation between upstream OpenCode code (packages/) and prokube-specific code (prokube/). Key additions: - New README.md explaining the architecture and feature split - AGENTS.md updated with critical boundary rules and examples - Document prokube-specific endpoints (/api/prokube/*) - Document frontend workarounds (MCP persistence, mkdir) - Real example: MCP persistence bug fix approach Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move duplicated prokube API endpoints (/api/prokube/mkdir, /api/prokube/list-dirs) from dev.ts and serve-ui.ts into shared/prokube-endpoints.ts. This eliminates code duplication between the dev and production servers. Both servers now import from the shared module. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ability to remove MCP servers from the global config via the UI. Changes: - Add remove() function to MCP context that: - Disconnects the server - Removes entry from global config - Add delete button (trash icon) next to each MCP server in the dialog - Confirm before deleting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The serve-ui.ts imports from ../shared/prokube-endpoints but the shared directory wasn't being copied to the Docker image. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ability to delete MCP servers from the Settings page MCP tab, matching the functionality already available in the MCP dialog. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After deleting an MCP server, the backend restarts due to config change. The UI wasn't refreshing after reconnect, so deleted servers still appeared. Now MCP status refreshes on server.connected event. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The backend does a deep merge on config.update(), so omitting a key doesn't delete it. We now explicitly set the server to null to signal deletion. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The OpenCode SDK's global.config.update() does a deep merge and doesn't support deleting keys. We now use a custom prokube endpoint that directly modifies the config file to remove MCP servers. - Add DELETE /api/prokube/mcp/:name endpoint in prokube-endpoints.ts - Update MCP context to use this endpoint for removal Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…URLs The regex to strip JSONC comments was breaking URLs like http://... Now we try JSON.parse first, and only strip comments if that fails. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After deleting from config file, we need to trigger a backend restart so it reloads the updated config. We do this by calling global.config.update() which causes server.instance.disposed and a restart. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The backend needs a moment to fully initialize after restart. Add 500ms delay before refreshing MCP status on server.connected. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add smart auto-scroll that detects when user manually scrolls up and pauses auto-scrolling. Auto-scroll resumes when user scrolls back to the bottom or sends a new message. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The server.connected event wasn't reliably triggering refresh. Now we explicitly wait 1.5s and refresh after triggering backend restart. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Terminal button to HomeLayout sidebar (available without active session) - Add resizable Terminal panel at bottom of home screen - Simplify SSH key settings to read-only display with copy functionality - Show ssh-keygen command for users to generate keys themselves - Remove Terminal ActionCard from project-picker (now in sidebar instead) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Users with multiple SSH keys can now see all of them in the Git settings, making it easier to copy the right key for different Git providers. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Now lists all .pub files in ~/.ssh/ directory instead of only checking for id_ed25519, id_ecdsa, id_rsa, id_dsa. Standard keys are shown first, followed by custom-named keys alphabetically. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use reconcile() when updating the SolidJS store to properly handle deleted keys. Without this, removed servers would persist in the store until a full page refresh. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the backend echoes back the user's message, the event handler was creating a new "assistant" message because the messageID didn't match the optimistic user message ID. Now we track the pending user message text and match it against incoming parts - if it matches, we update the optimistic message's ID instead of creating a duplicate assistant message. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
findLastIndex is ES2023 and may not be available in all environments. Use a simple reverse loop instead. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show clear error message when selected model's provider is not connected - Remove polling loop that was causing constant console logs - Rely on SSE events for real-time updates (like the original UI does) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Docker Image
NB_PREFIXfor Kubeflow notebook URL prefixesUI Improvements
Testing