Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
6eeae28
Integrate billing popup, usage sidebar, and credit preview toggle
CJWTRUST Jan 20, 2026
744e5c9
fix(resolution-search): preserve chat context and make search non-blo…
google-labs-jules[bot] Jan 22, 2026
73924c9
Merge pull request #447 from QueueLab/fix-resolution-search-context-7…
ngoiyaeric Jan 22, 2026
160e082
Recover lost commit 488b47c and restore branch head
google-labs-jules[bot] Jan 28, 2026
ae085cf
Merge pull request #456 from QueueLab/jules-16847885310673003402-db9c…
ngoiyaeric Jan 28, 2026
73c385c
Restore branch history to 488b47c and integrate latest fixes
google-labs-jules[bot] Jan 28, 2026
1508c04
Restore branch history to 488b47c and resolve build errors
google-labs-jules[bot] Jan 28, 2026
c8c028b
Restore branch history, fix build errors, and re-enable pricing popup
google-labs-jules[bot] Jan 28, 2026
e2c0615
Finalize recovery with performance optimizations and UI fixes
google-labs-jules[bot] Jan 28, 2026
d48f378
feat: add digital global timezone clock to calendar UI
google-labs-jules[bot] Jan 28, 2026
2c53604
fix: stabilize map and search button by removing redundant cleanup logic
google-labs-jules[bot] Jan 28, 2026
1eb28e1
feat: improve resolution search with time context and stabilize map
google-labs-jules[bot] Jan 28, 2026
128e7bd
Merge pull request #460 from QueueLab/feature/timezone-clock-68263987…
ngoiyaeric Jan 28, 2026
43179e7
Synchronize with main, restore history, and optimize performance
google-labs-jules[bot] Jan 29, 2026
7d45e02
Finalize recovery with prioritized main branch code and usage UI
google-labs-jules[bot] Jan 29, 2026
5623831
Refine usage UI and Lottie animation visibility
google-labs-jules[bot] Jan 29, 2026
44e86b6
Complete recovery, synchronization with main, and usage UI integration
google-labs-jules[bot] Jan 29, 2026
0a48018
feat: recover branch state, optimize resolution search, and fix UI st…
google-labs-jules[bot] Jan 29, 2026
6acfbe5
fix: resolve build error and ESLint warnings
google-labs-jules[bot] Jan 29, 2026
25a50ed
Delete CC BY-NC 4.0.docx
ngoiyaeric Jan 30, 2026
a674fce
Refactor inquiry agent and task manager for conjecture-driven explora…
google-labs-jules[bot] Jan 31, 2026
ccd7086
I have integrated map drawings into the resolution search context. I …
google-labs-jules[bot] Jan 31, 2026
62df7fc
Merge pull request #465 from QueueLab/fix/inquiry-agent-context-30161…
ngoiyaeric Jan 31, 2026
bdd9b5d
Merge branch 'main' into feature/resolution-search-drawings-context-1…
ngoiyaeric Jan 31, 2026
2fcf31e
feat: include map drawings in resolution search context
google-labs-jules[bot] Jan 31, 2026
9b98e20
feat: fix streaming and add drawings to resolution search context
google-labs-jules[bot] Jan 31, 2026
2fef8f0
Merge pull request #466 from QueueLab/feature/resolution-search-drawi…
ngoiyaeric Jan 31, 2026
8ae549a
Update LICENSE
ngoiyaeric Feb 1, 2026
3495da1
Update LICENSE
ngoiyaeric Feb 1, 2026
ba36e58
Merge pull request #469 from QueueLab/ngoiyaeric-patch-4
ngoiyaeric Feb 1, 2026
6431b41
fix: reduce padding in mobile chat input area
google-labs-jules[bot] Feb 1, 2026
8a04d49
Merge pull request #470 from QueueLab/fix/mobile-chat-input-padding-1…
ngoiyaeric Feb 1, 2026
10ab3fe
feat: update Stripe checkout links to new URL
google-labs-jules[bot] Feb 1, 2026
250283e
Merge pull request #471 from QueueLab/update-stripe-links-17354207767…
ngoiyaeric Feb 1, 2026
6554775
fix: ensure long sentences wrap to the next line across UI components
google-labs-jules[bot] Feb 1, 2026
e95a25b
Merge pull request #473 from QueueLab/fix/text-overflow-wrapping-4739…
ngoiyaeric Feb 1, 2026
f80c87f
Resolve merge conflicts and synchronize with main
CJWTRUST Feb 2, 2026
c4278e9
feat: final stability and performance improvements
google-labs-jules[bot] Feb 2, 2026
813d264
Resolve merge conflicts and synchronize with main, preserving branch …
google-labs-jules[bot] Feb 2, 2026
c868dcd
Merge branch 'feature/billing-integration-recovery-648258468266820429…
ngoiyaeric Feb 2, 2026
fb33c86
Merge pull request #475 from QueueLab/jules-8488824498232079115-26d4e4cd
ngoiyaeric Feb 2, 2026
75f7fdf
Merge branch 'fix/regressions-security-architecture-13947295106479740…
ngoiyaeric Feb 2, 2026
509e7bf
fix: resolve build errors in history component and chat history client
CJWTRUST Feb 2, 2026
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
138 changes: 83 additions & 55 deletions app/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async function submit(formData?: FormData, skip?: boolean) {
const action = formData?.get('action') as string;
if (action === 'resolution_search') {
const file = formData?.get('file') as File;
const timezone = (formData?.get('timezone') as string) || 'UTC';
if (!file) {
throw new Error('No file provided for resolution search.');
}
Expand All @@ -60,7 +61,8 @@ async function submit(formData?: FormData, skip?: boolean) {
message.role !== 'tool' &&
message.type !== 'followup' &&
message.type !== 'related' &&
message.type !== 'end'
message.type !== 'end' &&
message.type !== 'resolution_search_result'
);

// The user's prompt for this action is static.
Expand All @@ -82,74 +84,97 @@ async function submit(formData?: FormData, skip?: boolean) {
});
messages.push({ role: 'user', content });

// Call the simplified agent, which now returns data directly.
const analysisResult = await resolutionSearch(messages) as any;
// Create a streamable value for the summary.
const summaryStream = createStreamableValue<string>('');

// Create a streamable value for the summary and mark it as done.
const summaryStream = createStreamableValue<string>();
summaryStream.done(analysisResult.summary || 'Analysis complete.');
async function processResolutionSearch() {
try {
// Call the simplified agent, which now returns a stream result.
const streamResult = await resolutionSearch(messages, timezone);

// Update the UI stream with the BotMessage component.
uiStream.update(
<BotMessage content={summaryStream.value} />
);
for await (const partialObject of streamResult.partialObjectStream) {
if (partialObject.summary) {
summaryStream.update(partialObject.summary);
}
}

messages.push({ role: 'assistant', content: analysisResult.summary || 'Analysis complete.' });
const analysisResult = await streamResult.object;

const sanitizedMessages: CoreMessage[] = messages.map(m => {
if (Array.isArray(m.content)) {
return {
...m,
content: m.content.filter(part => part.type !== 'image')
} as CoreMessage
}
return m
})
// Mark the summary stream as done with the result.
summaryStream.done(analysisResult.summary || 'Analysis complete.');

const relatedQueries = await querySuggestor(uiStream, sanitizedMessages);
uiStream.append(
<Section title="Follow-up">
messages.push({ role: 'assistant', content: analysisResult.summary || 'Analysis complete.' });

const sanitizedMessages: CoreMessage[] = messages.map(m => {
if (Array.isArray(m.content)) {
return {
...m,
content: m.content.filter(part => part.type !== 'image')
} as CoreMessage
}
return m
})

const relatedQueries = await querySuggestor(uiStream, sanitizedMessages);
uiStream.append(
<Section title="Follow-up">
<FollowupPanel />
</Section>
);
</Section>
);

await new Promise(resolve => setTimeout(resolve, 500));
await new Promise(resolve => setTimeout(resolve, 500));

const groupeId = nanoid();
const groupeId = nanoid();

aiState.done({
...aiState.get(),
messages: [
aiState.done({
...aiState.get(),
messages: [
...aiState.get().messages,
{
id: groupeId,
role: 'assistant',
content: analysisResult.summary || 'Analysis complete.',
type: 'response'
id: groupeId,
role: 'assistant',
content: analysisResult.summary || 'Analysis complete.',
type: 'response'
},
{
id: groupeId,
role: 'assistant',
content: JSON.stringify(analysisResult),
type: 'resolution_search_result'
id: groupeId,
role: 'assistant',
content: JSON.stringify(analysisResult),
type: 'resolution_search_result'
},
{
id: groupeId,
role: 'assistant',
content: JSON.stringify(relatedQueries),
type: 'related'
id: groupeId,
role: 'assistant',
content: JSON.stringify(relatedQueries),
type: 'related'
},
{
id: groupeId,
role: 'assistant',
content: 'followup',
type: 'followup'
id: groupeId,
role: 'assistant',
content: 'followup',
type: 'followup'
}
]
});
]
});
} catch (error) {
console.error('Error in resolution search:', error);
summaryStream.error(error);
} finally {
isGenerating.done(false);
uiStream.done();
}
Comment on lines +159 to +165

Choose a reason for hiding this comment

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

summaryStream.error(error) is called with an unknown/non-Error possible value. Depending on the stream implementation, this can result in a useless [object Object] message or even a runtime error if it expects an Error.

Also, console.error is fine, but user-visible output should be a safe string/message.

Suggestion

Normalize the error before passing it to the stream and provide a user-safe message:

} catch (err) {
  const e = err instanceof Error ? err : new Error(String(err));
  console.error('Error in resolution search:', e);
  summaryStream.error(e);
}

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this change.

}

// Start the background process without awaiting it.
processResolutionSearch();

// Immediately update the UI stream with the BotMessage component.
uiStream.update(
<Section title="response">
<BotMessage content={summaryStream.value} />
</Section>
);

isGenerating.done(false);
uiStream.done();
return {
id: nanoid(),
isGenerating: isGenerating.value,
Expand All @@ -163,7 +188,8 @@ async function submit(formData?: FormData, skip?: boolean) {
message.role !== 'tool' &&
message.type !== 'followup' &&
message.type !== 'related' &&
message.type !== 'end'
message.type !== 'end' &&
message.type !== 'resolution_search_result'
)

const groupeId = nanoid()
Expand Down Expand Up @@ -295,7 +321,7 @@ async function submit(formData?: FormData, skip?: boolean) {
const hasImage = messageParts.some(part => part.type === 'image')
// Properly type the content based on whether it contains images
const content: CoreMessage['content'] = hasImage
? messageParts as CoreMessage['content']
? (messageParts as CoreMessage['content'])
: messageParts.map(part => part.text).join('\n')

const type = skip
Expand Down Expand Up @@ -340,7 +366,7 @@ async function submit(formData?: FormData, skip?: boolean) {
const mapProvider = formData?.get('mapProvider') as 'mapbox' | 'google'

async function processEvents() {
let action: any = { object: { next: 'proceed' } }
let action: { object: { next: string } } = { object: { next: 'proceed' } }
if (!skip) {
const taskManagerResult = await taskManager(messages)
if (taskManagerResult) {
Expand Down Expand Up @@ -371,7 +397,7 @@ async function submit(formData?: FormData, skip?: boolean) {
let answer = ''
let toolOutputs: ToolResultPart[] = []
let errorOccurred = false
const streamText = createStreamableValue<string>()
const streamText = createStreamableValue<string>('')
uiStream.update(<Spinner />)

while (
Expand Down Expand Up @@ -646,7 +672,9 @@ export const getUIStateFromAIState = (aiState: Chat) => {
)
}
case 'related':
const relatedQueries = createStreamableValue<RelatedQueries>()
const relatedQueries = createStreamableValue<RelatedQueries>({
items: []
})
relatedQueries.done(JSON.parse(content as string))
return {
id,
Expand Down
3 changes: 3 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import { SpeedInsights } from "@vercel/speed-insights/next"
import { Toaster } from '@/components/ui/sonner'
import { MapToggleProvider } from '@/components/map-toggle-context'
import { ProfileToggleProvider } from '@/components/profile-toggle-context'
import { UsageToggleProvider } from '@/components/usage-toggle-context'
import { CalendarToggleProvider } from '@/components/calendar-toggle-context'
import { HistoryToggleProvider } from '@/components/history-toggle-context'
import { HistorySidebar } from '@/components/history-sidebar'
import { MapLoadingProvider } from '@/components/map-loading-context';
import ConditionalLottie from '@/components/conditional-lottie';
import { MapProvider } from '@/components/map/map-context'
Expand Down
Loading