Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
421 changes: 421 additions & 0 deletions components/chat-input-form/coding-mode-button.tsx

Large diffs are not rendered by default.

27 changes: 26 additions & 1 deletion components/chat-input-form/inside-buttons.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import type React from 'react';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { useTranslations } from 'next-intl';
import { Button } from '@/components/ui/button';
import {
Expand All @@ -19,7 +19,9 @@ import { X, BookOpen, Archive, Check, Terminal } from 'lucide-react';
import { DeepSearchIcon, CanvasIcon } from '@/components/icons/svg-icons';
import { TOOLS } from '@iblai/iblai-js/web-utils';
import { MemoryButton } from './memory-button';
import { CodingModeButton } from './coding-mode-button';
import { MemoryMenu } from './memory-menu';
import { isTauriApp } from '@/types/tauri';

interface InsideButtonsProps {
activeOptions: string[];
Expand Down Expand Up @@ -61,6 +63,27 @@ export const InsideButtons = ({
username,
}: InsideButtonsProps) => {
const t = useTranslations('chatInputFormInsideButtons');

// Code (opencode over ACP) is desktop-only. Detected AFTER mount, never during
// render: Tauri injects its globals into the remote origin some time after load, so a
// render-time read can latch false forever (and would mismatch prerendered HTML
// during hydration). Keeping the gate here also means <CodingModeButton> — which
// needs Redux + the mentor route — never mounts in a plain browser.
const [inTauri, setInTauri] = useState(false);
useEffect(() => {
if (isTauriApp()) return setInTauri(true);
let tries = 0;
const t = setInterval(() => {
if (isTauriApp()) {
setInTauri(true);
clearInterval(t);
} else if (++tries > 10) {
clearInterval(t);
}
}, 500);
return () => clearInterval(t);
}, []);

const allInsideButtons = [
{
name: 'Canvas',
Expand Down Expand Up @@ -136,6 +159,8 @@ export const InsideButtons = ({

return (
<div className="relative flex items-center gap-1.5">
{/* Coding Mode (desktop-only) — always inline; owns its own folder popover. */}
{inTauri && <CodingModeButton />}
{/* Responsive Inside Buttons */}
{visibleInsideButtons.map((button) => {
if (button.name === 'Memory') {
Expand Down
12 changes: 9 additions & 3 deletions hooks/use-mentors/use-mentor-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,21 @@ export function useMentorSettings({
mentorId: mentorIdFromProps,
tenantKey: tenantKeyFromProps,
}: Props = {}) {
const { tenantKey: tenantKeyFromParams, mentorId: mentorIdFromParams } =
useParams<TenantKeyMentorIdParams>();
// `useParams()` is null outside a matched route segment, so destructuring it
// directly throws ("Cannot destructure property 'tenantKey' of null") and takes down
// whatever rendered the caller. Read it defensively — callers already handle a
// missing mentorId/tenantKey (the query is skipped below).
const params = useParams<TenantKeyMentorIdParams>();
const tenantKeyFromParams = params?.tenantKey;
const mentorIdFromParams = params?.mentorId;
const username = useUsername();
const COMMUNITY_MENTOR_VISIBILITY = MentorVisibilityEnum.VIEWABLE_BY_ANYONE;
const mentorId = mentorIdFromProps || mentorIdFromParams;
const tenantKey = tenantKeyFromProps || tenantKeyFromParams;
const isLoggedIn = Boolean(username);
const searchParams = useSearchParams();
const isAccessingPublicRoute = !!searchParams.get('token');
// Null outside a matched route segment, same as `useParams()` above.
const isAccessingPublicRoute = !!searchParams?.get('token');

// Check if we're in Tauri offline mode
const isOffline = isTauriApp() && isTauriOfflineMode();
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"@sentry/nextjs": "10.62.0",
"@tanstack/react-form": "1.6.3",
"@tauri-apps/api": "2.11.0",
"@tauri-apps/plugin-dialog": "2.7.2",
"@tauri-apps/plugin-opener": "2.5.3",
"@tauri-apps/plugin-os": "2.3.2",
"@tauri-apps/plugin-shell": "2.3.4",
Expand Down
58 changes: 34 additions & 24 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,10 @@ overrides:
# (see patches/google-drive-picker@1.1.29.patch and its regression test).
patchedDependencies:
google-drive-picker@1.1.29: patches/google-drive-picker@1.1.29.patch

# Local Verdaccio publishes of @iblai/* carry throwaway -acp suffixes newer than the
# min-release-age floor (.npmrc: min-release-age=7). Exclude them so
# `pnpm i --registry http://localhost:4873/` can install the freshly published Coding
# Mode SDK. Local scaffolding — remove before PR.
minimumReleaseAgeExclude:
- '@iblai/*'
67 changes: 67 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading