feat(editor): migrate typst mermaid to native (#14499)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Native/WASM Mermaid and Typst SVG preview rendering on desktop and mobile, plus cross-platform Preview plugin integrations. * **Improvements** * Centralized, sanitized rendering bridge with automatic Typst font-directory handling and configurable native renderer selection. * More consistent and robust error serialization and worker-backed preview flows for improved stability and performance. * **Tests** * Extensive unit and integration tests for preview rendering, font discovery, sanitization, and error serialization. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -8,4 +8,18 @@
|
||||
import ApolloAPI
|
||||
|
||||
/// The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
|
||||
public typealias JSON = String
|
||||
public struct JSON: CustomScalarType, Hashable, ExpressibleByDictionaryLiteral {
|
||||
public let value: JSONValue
|
||||
|
||||
public init(_jsonValue value: JSONValue) throws {
|
||||
self.value = value
|
||||
}
|
||||
|
||||
public init(dictionaryLiteral elements: (String, JSONValue)...) {
|
||||
value = ApolloAPI.JSONObject(uniqueKeysWithValues: elements) as JSONValue
|
||||
}
|
||||
|
||||
public var _jsonValue: JSONValue {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,4 +8,22 @@
|
||||
import ApolloAPI
|
||||
|
||||
/// The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
|
||||
public typealias JSONObject = String
|
||||
public struct JSONObject: CustomScalarType, Hashable, ExpressibleByDictionaryLiteral {
|
||||
public let object: ApolloAPI.JSONObject
|
||||
|
||||
public init(_jsonValue value: JSONValue) throws {
|
||||
object = try ApolloAPI.JSONObject(_jsonValue: value)
|
||||
}
|
||||
|
||||
public init(_ object: ApolloAPI.JSONObject) {
|
||||
self.object = object
|
||||
}
|
||||
|
||||
public init(dictionaryLiteral elements: (String, JSONValue)...) {
|
||||
object = ApolloAPI.JSONObject(uniqueKeysWithValues: elements)
|
||||
}
|
||||
|
||||
public var _jsonValue: JSONValue {
|
||||
object
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ private extension InputBoxData {
|
||||
}
|
||||
|
||||
public extension ChatManager {
|
||||
@MainActor
|
||||
func startUserRequest(editorData: InputBoxData, sessionId: String) {
|
||||
append(sessionId: sessionId, UserMessageCellViewModel(
|
||||
id: .init(),
|
||||
@@ -163,7 +164,7 @@ private extension ChatManager {
|
||||
assert(!Thread.isMainThread)
|
||||
print("[+] starting copilot response for session: \(sessionId)")
|
||||
|
||||
let messageParameters: [String: AnyHashable] = [
|
||||
let messageParameters: AffineGraphQL.JSON = [
|
||||
// packages/frontend/core/src/blocksuite/ai/provider/setup-provider.tsx
|
||||
"docs": editorData.documentAttachments.map(\.documentID), // affine doc
|
||||
"files": [String](), // attachment in context, keep nil for now
|
||||
@@ -193,18 +194,14 @@ private extension ChatManager {
|
||||
},
|
||||
].flatMap(\.self)
|
||||
assert(uploadableAttachments.allSatisfy { !($0.data?.isEmpty ?? true) })
|
||||
guard let input = try? CreateChatMessageInput(
|
||||
let input = CreateChatMessageInput(
|
||||
attachments: [],
|
||||
blob: attachmentCount == 1 ? "" : .none,
|
||||
blobs: attachmentCount > 1 && attachmentCount != 0 ? .some([]) : .none,
|
||||
content: .some(contextSnippet.isEmpty ? editorData.text : "\(contextSnippet)\n\(editorData.text)"),
|
||||
params: .some(AffineGraphQL.JSON(_jsonValue: messageParameters)),
|
||||
params: .some(messageParameters),
|
||||
sessionId: sessionId
|
||||
) else {
|
||||
report(sessionId, ChatError.unknownError)
|
||||
assertionFailure() // very unlikely to happen
|
||||
return
|
||||
}
|
||||
)
|
||||
let mutation = CreateCopilotMessageMutation(options: input)
|
||||
QLService.shared.client.upload(operation: mutation, files: uploadableAttachments) { result in
|
||||
print("[*] createCopilotMessage result: \(result)")
|
||||
@@ -277,7 +274,7 @@ private extension ChatManager {
|
||||
let eventSource = EventSource()
|
||||
let dataTask = eventSource.dataTask(for: request)
|
||||
var document = ""
|
||||
self.writeMarkdownContent(document + loadingIndicator, sessionId: sessionId, vmId: vmId)
|
||||
await self.writeMarkdownContent(document + loadingIndicator, sessionId: sessionId, vmId: vmId)
|
||||
for await event in dataTask.events() {
|
||||
switch event {
|
||||
case .open:
|
||||
@@ -287,7 +284,7 @@ private extension ChatManager {
|
||||
case let .event(event):
|
||||
guard let data = event.data else { continue }
|
||||
document += data
|
||||
self.writeMarkdownContent(
|
||||
await self.writeMarkdownContent(
|
||||
document + loadingIndicator,
|
||||
sessionId: sessionId,
|
||||
vmId: vmId
|
||||
@@ -297,13 +294,13 @@ private extension ChatManager {
|
||||
print("[*] connection closed")
|
||||
}
|
||||
}
|
||||
self.writeMarkdownContent(document, sessionId: sessionId, vmId: vmId)
|
||||
await self.writeMarkdownContent(document, sessionId: sessionId, vmId: vmId)
|
||||
self.closeAll()
|
||||
}))
|
||||
self.closable.append(closable)
|
||||
}
|
||||
|
||||
private func writeMarkdownContent(
|
||||
@MainActor private func writeMarkdownContent(
|
||||
_ document: String,
|
||||
sessionId: SessionID,
|
||||
vmId: UUID
|
||||
|
||||
@@ -9,7 +9,7 @@ import Foundation
|
||||
import MarkdownView
|
||||
|
||||
extension IntelligentContext {
|
||||
func prepareMarkdownViewThemes() {
|
||||
@MainActor func prepareMarkdownViewThemes() {
|
||||
MarkdownTheme.default.colors.body = .affineTextPrimary
|
||||
MarkdownTheme.default.colors.highlight = .affineTextLink
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ struct AssistantMessageCellViewModel: ChatCellViewModel {
|
||||
|
||||
var preprocessedContent: MarkdownTextView.PreprocessedContent
|
||||
|
||||
init(
|
||||
@MainActor init(
|
||||
id: UUID,
|
||||
content: String,
|
||||
timestamp: Date,
|
||||
|
||||
Reference in New Issue
Block a user