Merge branch 'upstream' into concedo_experimental

# Conflicts:
#	.github/workflows/build-apple.yml
#	.github/workflows/build-cpu.yml
#	.github/workflows/build-cuda-ubuntu.yml
#	.github/workflows/build-sycl.yml
#	.github/workflows/build-vulkan.yml
#	.github/workflows/build-wasm.yml
#	.github/workflows/build-webgpu.yml
#	.github/workflows/hip-quality-check.yml
#	.github/workflows/server.yml
#	CMakeLists.txt
#	docs/backend/SYCL.md
#	ggml/CMakeLists.txt
#	ggml/src/CMakeLists.txt
#	ggml/src/ggml-opencl/CMakeLists.txt
#	ggml/src/ggml-opencl/ggml-opencl.cpp
#	ggml/src/ggml-opencl/kernels/concat.cl
#	ggml/src/ggml-opencl/kernels/cpy.cl
#	ggml/src/ggml-sycl/common.cpp
#	ggml/src/ggml-sycl/common.hpp
#	ggml/src/ggml-sycl/fattn-buffers.cpp
#	ggml/src/ggml-sycl/fwht.cpp
#	ggml/src/ggml-sycl/ggml-sycl.cpp
#	scripts/sync-ggml.last
#	tests/test-backend-ops.cpp
#	tests/test-llama-archs.cpp
This commit is contained in:
Concedo
2026-09-05 12:09:30 +08:00
35 changed files with 1665 additions and 50 deletions
@@ -194,7 +194,7 @@
/>
{:else if section.type === AgenticSectionType.TOOL_CALL || section.type === AgenticSectionType.TOOL_CALL_PENDING || section.type === AgenticSectionType.TOOL_CALL_STREAMING}
<ChatMessageToolCallBlock
attachments={message?.extra}
attachments={section.toolResultExtras}
isExecuting={section.toolCallId !== undefined &&
section.toolCallId === currentlyExecutingToolCallId}
{isStreaming}
@@ -139,12 +139,8 @@
async function handleExportConfirm(selectedConversations: DatabaseConversation[]) {
try {
const allData: ExportedConversation[] = await Promise.all(
selectedConversations.map(async (conv) => {
const messages = await conversationsStore.getConversationMessages(conv.id);
return { conv: $state.snapshot(conv), messages: $state.snapshot(messages) };
})
const allData = await conversationsStore.getConversationsForExport(
selectedConversations.map((conv) => conv.id)
);
if (allData.length === 1) {
@@ -2,8 +2,11 @@ import type { AgenticConfig } from '$lib/types/agentic';
export const ATTACHMENT_SAVED_REGEX = /\[Attachment saved: ([^\]]+)\]/;
// JSON detection: trimmed content opens with an object or array literal.
export const TOOL_RESULT_JSON_OPEN_REGEX = /^[[{]/;
// JSON detection: an attachment placeholder also starts with `[`, but is
// plain text (`[Attachment saved: ...]`), not an array literal. Require the
// first array value (or the closing bracket for an empty array) to look like
// a valid JSON token before attempting JSON.parse.
export const TOOL_RESULT_JSON_OPEN_REGEX = /^(?:\{|\[\s*(?:[[\]"{\-0-9]|true|false|null))/;
// Search-summary wire format used by file-glob and grep tools:
// <matches>
@@ -168,15 +168,7 @@ class ConversationsStore implements ConversationsPreferencesHost {
if (convIds.length === 0) return;
try {
const fetched = await DatabaseService.getConversationsWithMessages(convIds);
const activeId = this.activeConversation?.id;
const overridden = fetched.get(activeId ?? '');
if (overridden && activeId) {
overridden.conv = { ...this.activeConversation! };
}
const exported = [...fetched.values()];
const exported = await this.getConversationsForExport(convIds);
if (exported.length === 0) {
toast.error('No conversations to export');
@@ -365,16 +357,11 @@ class ConversationsStore implements ConversationsPreferencesHost {
* @param convId - The conversation ID to download
*/
async downloadConversation(convId: string): Promise<void> {
const conversation =
this.activeConversation?.id === convId
? this.activeConversation
: await DatabaseService.getConversation(convId);
const [exportedConversation] = await this.getConversationsForExport([convId]);
if (!conversation) return;
if (!exportedConversation) return;
const messages = await DatabaseService.getConversationMessages(convId);
ConversationTransferService.downloadConversationFile({ conv: conversation, messages });
ConversationTransferService.downloadConversationFile(exportedConversation);
}
/**
@@ -453,6 +440,19 @@ class ConversationsStore implements ConversationsPreferencesHost {
return await DatabaseService.getConversationMessages(convId);
}
/**
* Gets conversations and their messages from the database for export.
* @param convIds - Conversation IDs
* @returns List of conversations with messages, ordered by the input IDs
*/
async getConversationsForExport(convIds: string[]): Promise<ExportedConversation[]> {
const fetched = await DatabaseService.getConversationsWithMessages(convIds);
return convIds
.map((id) => fetched.get(id))
.filter((entry): entry is ExportedConversation => entry !== undefined);
}
/**
* Imports conversations from provided data (without file picker)
* @param data - Array of conversation data with messages