Skip to content

Commit af10167

Browse files
wip v28
1 parent 3bf6708 commit af10167

25 files changed

Lines changed: 916 additions & 54 deletions

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ LOG_LEVEL=info
2626
NEXT_PUBLIC_COMING_SOON=false
2727
NEXT_PUBLIC_CONVERSATION_SECTION=false
2828
NEXT_PUBLIC_CONVERSATIONS_WIDGET=false
29+
NEXT_PUBLIC_DISABLE_CONVERSATIONS_ROUTE=false
2930
NEXT_PUBLIC_DISABLE_USING=false
3031
NEXT_PUBLIC_INVISIBLE_INTERFACES_GROUP=false
3132
NEXT_PUBLIC_LIGHTPAPER_BANNER=false

uapi/app/ClientLayoutInner.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,19 @@ const Conversation = dynamic(() => import('@/app/conversations/components/Conver
5353
// Prefetch heavy components for instant loading
5454
const prefetchHeavyComponents = () => {
5555
if (typeof window !== 'undefined') {
56+
const conversationsEnabled = !FEATURE_FLAGS.DISABLE_CONVERSATIONS_ROUTE && FEATURE_FLAGS.CONVERSATIONS_WIDGET;
57+
5658
// Prefetch Conversations after 2 seconds (lower priority than Orbital)
5759
setTimeout(() => {
58-
if (!(window as any).__conversationsPrefetched) {
60+
if (conversationsEnabled && !(window as any).__conversationsPrefetched) {
5961
(window as any).__conversationsPrefetched = true;
6062
import('@/app/conversations/components/ConversationsOverlay').catch(() => {});
6163
}
6264
}, 2000);
6365

6466
// Prefetch the retained Conversations sidebar after 3 seconds.
6567
setTimeout(() => {
66-
if (!window.__sidebarsPrefetched) {
68+
if (conversationsEnabled && !window.__sidebarsPrefetched) {
6769
window.__sidebarsPrefetched = true;
6870
import('@/components/base/bitcode/layout/sidebars/right-sidebar').catch(() => {});
6971
}
@@ -220,6 +222,7 @@ export default function ClientLayoutInner({ children }: { children: ReactNode })
220222
const { data: onboardingData } = useOnboarding();
221223
const isOnboardingComplete = onboardingData?.isOnboardingComplete ?? false;
222224
const hideFooter = shouldHideWorkspaceFooter(pathname);
225+
const conversationsEnabled = !FEATURE_FLAGS.DISABLE_CONVERSATIONS_ROUTE && FEATURE_FLAGS.CONVERSATIONS_WIDGET;
223226

224227
return (
225228
<AuthProvider>
@@ -231,7 +234,7 @@ export default function ClientLayoutInner({ children }: { children: ReactNode })
231234
<React.Suspense fallback={null}>
232235
{/* Desktop supporting overlays. Auxillaries stays portal-only for V28. */}
233236
<div className="hidden laptop:block">
234-
{authLoaded && user && !mockMode && pathname !== '/terminal' && pathname !== '/conversations' && isOnboardingComplete && FEATURE_FLAGS.CONVERSATIONS_WIDGET && (
237+
{authLoaded && user && !mockMode && pathname !== '/terminal' && pathname !== '/conversations' && isOnboardingComplete && conversationsEnabled && (
235238
<>
236239
<Conversation
237240
position="bottom-right"

uapi/app/edgetimes/EdgetimesPageContent.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import Link from 'next/link';
33

44
import Footer from '@/components/base/bitcode/layout/footer';
5+
import { FEATURE_FLAGS } from '@/config/features';
56

67
import { EDGETIMES_TOPOLOGY, getEdgetimesTopologySummary } from './edgetimes-topology';
78

@@ -149,12 +150,14 @@ export default function EdgetimesPageContent() {
149150
>
150151
Open Bitcode Terminal
151152
</Link>
152-
<Link
153-
href="/conversations"
154-
className="inline-flex items-center rounded-full border border-white/12 bg-white/5 px-4 py-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-white/84 transition hover:border-white/20 hover:bg-white/10"
155-
>
156-
Open conversations
157-
</Link>
153+
{!FEATURE_FLAGS.DISABLE_CONVERSATIONS_ROUTE ? (
154+
<Link
155+
href="/conversations"
156+
className="inline-flex items-center rounded-full border border-white/12 bg-white/5 px-4 py-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-white/84 transition hover:border-white/20 hover:bg-white/10"
157+
>
158+
Open conversations
159+
</Link>
160+
) : null}
158161
</section>
159162
</main>
160163

uapi/app/terminal/TerminalCoreNativeSections.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,11 @@ export default function TerminalCoreNativeSections({
196196
: 'Repository connection posture is not currently validated.',
197197
badge: connectionStatus?.metadata?.mock_mode ? 'mock' : 'connected',
198198
metrics: [
199-
{ label: 'Default branch', value: selectedRepository.defaultBranch || 'main' },
199+
{ label: 'Selected branch', value: repositoryContext?.selectedBranch || selectedRepository.defaultBranch || 'main' },
200200
{ label: 'Visibility', value: selectedRepository.private ? 'private' : 'public' },
201201
],
202202
rows: [
203+
{ label: 'Commit', value: repositoryContext?.selectedCommit || 'commit pending' },
203204
{ label: 'Language', value: selectedRepository.language || 'n/a' },
204205
{
205206
label: 'Owner',

uapi/app/terminal/TerminalDepositComposer.tsx

Lines changed: 102 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client';
22

33
import React, { useEffect, useMemo, useState } from 'react';
4-
import type { VCSProviderType } from '@bitcode/vcs-core';
4+
import type { VCSBranch, VCSCommit, VCSProviderType } from '@bitcode/vcs-core';
55

66
import BitcodeChipCloud from '@/components/base/bitcode/execution/BitcodeChipCloud';
77
import BitcodeInlineExplainer from '@/components/base/bitcode/execution/BitcodeInlineExplainer';
@@ -34,14 +34,36 @@ interface TerminalDepositComposerProps {
3434
onRecordActivity?: (draft: TerminalActivityRecordDraft) => Promise<unknown>;
3535
repositoryAnchor?: string | null;
3636
repositoryProvider?: VCSProviderType | null;
37+
repositoryBranch?: string | null;
38+
repositoryCommit?: string | null;
39+
repositoryBranches?: VCSBranch[];
40+
repositoryCommits?: VCSCommit[];
41+
isLoadingRepositoryBranches?: boolean;
42+
isLoadingRepositoryCommits?: boolean;
43+
onRepositorySourceBranchChange?: (branch: string) => void;
44+
onRepositorySourceCommitChange?: (commit: string) => void;
3745
transactionReadiness: BitcodeTransactionReadiness;
3846
showDemonstrationDraft?: boolean;
3947
}
4048

49+
function formatCommitOption(commit: VCSCommit) {
50+
const shortSha = commit.sha.slice(0, 7);
51+
const title = commit.message.split('\n')[0]?.trim() || 'Commit';
52+
return `${shortSha} - ${title}`;
53+
}
54+
4155
export default function TerminalDepositComposer({
4256
onRecordActivity,
4357
repositoryAnchor,
4458
repositoryProvider,
59+
repositoryBranch,
60+
repositoryCommit,
61+
repositoryBranches = [],
62+
repositoryCommits = [],
63+
isLoadingRepositoryBranches = false,
64+
isLoadingRepositoryCommits = false,
65+
onRepositorySourceBranchChange,
66+
onRepositorySourceCommitChange,
4567
transactionReadiness,
4668
showDemonstrationDraft = true,
4769
}: TerminalDepositComposerProps) {
@@ -60,7 +82,11 @@ export default function TerminalDepositComposer({
6082
const [content, setContent] = useState('');
6183
const [submitState, setSubmitState] = useState<SubmitState>({ kind: 'idle' });
6284
const repositoryAnchorValue = String(repositoryAnchor || '').trim();
85+
const repositoryBranchValue = String(repositoryBranch || '').trim();
86+
const repositoryCommitValue = String(repositoryCommit || '').trim();
6387
const usesLiveRepositoryAnchor = Boolean(repositoryAnchorValue);
88+
const hasSelectedSourceRevision =
89+
!usesLiveRepositoryAnchor || Boolean(repositoryBranchValue && repositoryCommitValue);
6490
const composer = useMemo<TerminalDepositComposerState | null>(
6591
() => {
6692
if (!showDemonstrationDraft && repositoryAnchorValue) {
@@ -84,6 +110,7 @@ export default function TerminalDepositComposer({
84110
const selectedSupplyCount = usesLiveRepositoryAnchor ? 1 : composer?.selectedCount || 0;
85111
const selectedInventoryEntryIds = usesLiveRepositoryAnchor ? [] : composer?.selectedInventoryEntryIds || [];
86112
const displayedSourceRepo = usesLiveRepositoryAnchor ? repositoryAnchorValue : sourceRepo;
113+
const displayedSourceCommit = usesLiveRepositoryAnchor ? repositoryCommitValue : sourceCommit;
87114

88115
useEffect(() => {
89116
setSignerAddress((current) => current || composer?.signerAddress || '');
@@ -105,6 +132,7 @@ export default function TerminalDepositComposer({
105132
(selectedSupplyCount > 0 || content.trim()) &&
106133
(title.trim() || selectedSupplyCount > 0) &&
107134
(author.trim() || effectiveAuthSessionId) &&
135+
hasSelectedSourceRevision &&
108136
settlementReady,
109137
);
110138

@@ -133,7 +161,9 @@ export default function TerminalDepositComposer({
133161
repositoryAnchor: repositoryAnchorValue || composer.sourceRepo || undefined,
134162
repositoryProvider: repositoryProvider || undefined,
135163
sourceRepo: displayedSourceRepo || undefined,
136-
sourceCommit,
164+
sourceBranch: repositoryBranchValue || undefined,
165+
sourceRef: repositoryBranchValue || undefined,
166+
sourceCommit: displayedSourceCommit || undefined,
137167
workflowRunId,
138168
signerAddress,
139169
visualPreview,
@@ -181,6 +211,8 @@ export default function TerminalDepositComposer({
181211
selectedInventoryEntryIds,
182212
selectedInventoryTitles: selectedEntryLabels,
183213
repositoryAnchor: repositoryAnchorValue || null,
214+
sourceBranch: repositoryBranchValue || null,
215+
sourceCommit: displayedSourceCommit || null,
184216
candidateAssetId: payload.asset?.assetId || null,
185217
},
186218
output: {
@@ -322,17 +354,71 @@ export default function TerminalDepositComposer({
322354

323355
<div className="rounded-[1.5rem] border border-white/8 bg-black/20 px-4 py-4">
324356
<span className="flex items-center gap-2 text-[0.66rem] uppercase tracking-[0.24em] text-neutral-400">
325-
<span>Source commit / ref</span>
326-
<BitcodeInlineExplainer explainer={TERMINAL_INLINE_EXPLAINERS.sourceCommit} />
357+
<span>{usesLiveRepositoryAnchor ? 'Source branch' : 'Source commit / ref'}</span>
358+
<BitcodeInlineExplainer
359+
explainer={
360+
usesLiveRepositoryAnchor
361+
? TERMINAL_INLINE_EXPLAINERS.sourceBranch
362+
: TERMINAL_INLINE_EXPLAINERS.sourceCommit
363+
}
364+
/>
327365
</span>
328-
<input
329-
value={sourceCommit}
330-
onChange={(event) => setSourceCommit(event.target.value)}
331-
placeholder="commit or branch override"
332-
className="mt-3 w-full rounded-xl border border-white/10 bg-[rgba(10,15,30,0.88)] px-3 py-3 text-sm text-white outline-none transition placeholder:text-neutral-500 focus:border-emerald-400/40"
333-
/>
366+
{usesLiveRepositoryAnchor ? (
367+
<>
368+
<select
369+
aria-label="Deposit source branch"
370+
value={repositoryBranchValue}
371+
disabled={isLoadingRepositoryBranches || repositoryBranches.length === 0}
372+
onChange={(event) => onRepositorySourceBranchChange?.(event.target.value)}
373+
className="mt-3 w-full rounded-xl border border-white/10 bg-[rgba(10,15,30,0.88)] px-3 py-3 text-sm text-white outline-none transition focus:border-emerald-400/40 disabled:cursor-not-allowed disabled:opacity-60"
374+
>
375+
{repositoryBranches.length ? null : <option value="">No branches loaded</option>}
376+
{repositoryBranches.map((branch) => (
377+
<option key={branch.name} value={branch.name}>
378+
{branch.name}
379+
</option>
380+
))}
381+
</select>
382+
<p className="mt-2 text-[0.68rem] uppercase tracking-[0.18em] text-neutral-500">
383+
{isLoadingRepositoryBranches ? 'Loading branches…' : 'Changing branch refreshes commit refs'}
384+
</p>
385+
</>
386+
) : (
387+
<input
388+
value={sourceCommit}
389+
onChange={(event) => setSourceCommit(event.target.value)}
390+
placeholder="commit or branch override"
391+
className="mt-3 w-full rounded-xl border border-white/10 bg-[rgba(10,15,30,0.88)] px-3 py-3 text-sm text-white outline-none transition placeholder:text-neutral-500 focus:border-emerald-400/40"
392+
/>
393+
)}
334394
</div>
335395

396+
{usesLiveRepositoryAnchor ? (
397+
<div className="rounded-[1.5rem] border border-white/8 bg-black/20 px-4 py-4">
398+
<span className="flex items-center gap-2 text-[0.66rem] uppercase tracking-[0.24em] text-neutral-400">
399+
<span>Source commit / ref</span>
400+
<BitcodeInlineExplainer explainer={TERMINAL_INLINE_EXPLAINERS.sourceCommit} />
401+
</span>
402+
<select
403+
aria-label="Deposit source commit"
404+
value={repositoryCommitValue}
405+
disabled={!repositoryBranchValue || isLoadingRepositoryCommits || repositoryCommits.length === 0}
406+
onChange={(event) => onRepositorySourceCommitChange?.(event.target.value)}
407+
className="mt-3 w-full rounded-xl border border-white/10 bg-[rgba(10,15,30,0.88)] px-3 py-3 text-sm text-white outline-none transition focus:border-emerald-400/40 disabled:cursor-not-allowed disabled:opacity-60"
408+
>
409+
{repositoryCommits.length ? null : <option value="">No commits loaded</option>}
410+
{repositoryCommits.map((commit) => (
411+
<option key={commit.sha} value={commit.sha}>
412+
{formatCommitOption(commit)}
413+
</option>
414+
))}
415+
</select>
416+
<p className="mt-2 text-[0.68rem] uppercase tracking-[0.18em] text-neutral-500">
417+
{isLoadingRepositoryCommits ? 'Loading commits…' : 'Exact source materialization uses this commit SHA'}
418+
</p>
419+
</div>
420+
) : null}
421+
336422
<label className="rounded-[1.5rem] border border-white/8 bg-black/20 px-4 py-4">
337423
<span className="text-[0.66rem] uppercase tracking-[0.24em] text-neutral-400">Workflow run override</span>
338424
<input
@@ -468,10 +554,15 @@ export default function TerminalDepositComposer({
468554
<p className="mt-3 text-sm leading-6 text-neutral-300">
469555
{selectedSupplyCount
470556
? usesLiveRepositoryAnchor
471-
? `Bitcode will bind ${repositoryAnchorValue} as the selected repository source for this deposit.`
557+
? `Bitcode will bind ${repositoryAnchorValue}${repositoryBranchValue ? ` on ${repositoryBranchValue}` : ''}${repositoryCommitValue ? ` at ${repositoryCommitValue.slice(0, 12)}` : ''} as the selected repository source for this deposit.`
472558
: `Bitcode will bind ${selectedSupplyCount} selected repo artifact${selectedSupplyCount === 1 ? '' : 's'} into this deposit.`
473559
: 'No repo artifacts are currently selected. Use raw fallback content or select inventory above.'}
474560
</p>
561+
{usesLiveRepositoryAnchor && !hasSelectedSourceRevision ? (
562+
<p className="mt-3 rounded-[1.1rem] border border-amber-400/20 bg-amber-400/10 px-4 py-3 text-sm leading-6 text-amber-100">
563+
Select a branch and commit before depositing so source materialization can fetch an exact snapshot.
564+
</p>
565+
) : null}
475566
{selectedEntryLabels.length ? (
476567
<BitcodeChipCloud
477568
chips={selectedEntryLabels}

uapi/app/terminal/TerminalExperienceFrame.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@ import { jumpToShellSection } from './terminal-shell-reading';
1414

1515
interface TerminalExperienceFrameProps {
1616
onOpenConversations: () => void;
17+
conversationsEnabled?: boolean;
1718
}
1819

19-
export default function TerminalExperienceFrame({ onOpenConversations }: TerminalExperienceFrameProps) {
20+
export default function TerminalExperienceFrame({
21+
onOpenConversations,
22+
conversationsEnabled = true,
23+
}: TerminalExperienceFrameProps) {
2024
return (
2125
<TerminalWorkspaceCard
2226
kicker="Mode map"
@@ -63,7 +67,7 @@ export default function TerminalExperienceFrame({ onOpenConversations }: Termina
6367
>
6468
Focus activity ledger
6569
</button>
66-
) : experience.id === 'conversations' ? (
70+
) : experience.id === 'conversations' && conversationsEnabled ? (
6771
<TerminalOpenConversationsButton
6872
onOpen={onOpenConversations}
6973
className="rounded-[1.3rem] border border-emerald-400/30 bg-emerald-400/10 px-4 py-3 text-sm font-medium text-emerald-100 transition hover:border-emerald-300/50 hover:bg-emerald-400/15"

0 commit comments

Comments
 (0)