mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-22 03:33:06 +08:00
feat: adopt new backend api for attachment (#13336)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduced a new query for applying document updates using AI, allowing merged markdown responses. * Added support for an optional file upload field when creating chat messages. * **Improvements** * Enhanced recent Copilot sessions query with pagination by adding an offset parameter. * Refined attachment handling in chat responses to better distinguish between single and multiple file uploads, improving reliability. * **Bug Fixes** * Minor update to error handling for clearer messaging. * **Chores** * Cleaned up and updated iOS project configuration files for improved build consistency. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 77;
|
objectVersion = 56;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
@@ -90,6 +90,8 @@
|
|||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
C45499AB2D140B5000E21978 /* NBStore */ = {
|
C45499AB2D140B5000E21978 /* NBStore */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
);
|
||||||
path = NBStore;
|
path = NBStore;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -337,13 +339,9 @@
|
|||||||
);
|
);
|
||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
);
|
);
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AFFiNE/Pods-AFFiNE-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AFFiNE/Pods-AFFiNE-frameworks.sh\"\n";
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
@_exported import ApolloAPI
|
||||||
|
|
||||||
|
public class ApplyDocUpdatesQuery: GraphQLQuery {
|
||||||
|
public static let operationName: String = "applyDocUpdates"
|
||||||
|
public static let operationDocument: ApolloAPI.OperationDocument = .init(
|
||||||
|
definition: .init(
|
||||||
|
#"query applyDocUpdates($workspaceId: String!, $docId: String!, $op: String!, $updates: String!) { applyDocUpdates( workspaceId: $workspaceId docId: $docId op: $op updates: $updates ) }"#
|
||||||
|
))
|
||||||
|
|
||||||
|
public var workspaceId: String
|
||||||
|
public var docId: String
|
||||||
|
public var op: String
|
||||||
|
public var updates: String
|
||||||
|
|
||||||
|
public init(
|
||||||
|
workspaceId: String,
|
||||||
|
docId: String,
|
||||||
|
op: String,
|
||||||
|
updates: String
|
||||||
|
) {
|
||||||
|
self.workspaceId = workspaceId
|
||||||
|
self.docId = docId
|
||||||
|
self.op = op
|
||||||
|
self.updates = updates
|
||||||
|
}
|
||||||
|
|
||||||
|
public var __variables: Variables? { [
|
||||||
|
"workspaceId": workspaceId,
|
||||||
|
"docId": docId,
|
||||||
|
"op": op,
|
||||||
|
"updates": updates
|
||||||
|
] }
|
||||||
|
|
||||||
|
public struct Data: AffineGraphQL.SelectionSet {
|
||||||
|
public let __data: DataDict
|
||||||
|
public init(_dataDict: DataDict) { __data = _dataDict }
|
||||||
|
|
||||||
|
public static var __parentType: any ApolloAPI.ParentType { AffineGraphQL.Objects.Query }
|
||||||
|
public static var __selections: [ApolloAPI.Selection] { [
|
||||||
|
.field("applyDocUpdates", String.self, arguments: [
|
||||||
|
"workspaceId": .variable("workspaceId"),
|
||||||
|
"docId": .variable("docId"),
|
||||||
|
"op": .variable("op"),
|
||||||
|
"updates": .variable("updates")
|
||||||
|
]),
|
||||||
|
] }
|
||||||
|
|
||||||
|
/// Apply updates to a doc using LLM and return the merged markdown.
|
||||||
|
public var applyDocUpdates: String { __data["applyDocUpdates"] }
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-4
@@ -7,24 +7,28 @@ public class GetCopilotRecentSessionsQuery: GraphQLQuery {
|
|||||||
public static let operationName: String = "getCopilotRecentSessions"
|
public static let operationName: String = "getCopilotRecentSessions"
|
||||||
public static let operationDocument: ApolloAPI.OperationDocument = .init(
|
public static let operationDocument: ApolloAPI.OperationDocument = .init(
|
||||||
definition: .init(
|
definition: .init(
|
||||||
#"query getCopilotRecentSessions($workspaceId: String!, $limit: Int = 10) { currentUser { __typename copilot(workspaceId: $workspaceId) { __typename chats( pagination: { first: $limit } options: { fork: false, sessionOrder: desc, withMessages: false } ) { __typename ...PaginatedCopilotChats } } } }"#,
|
#"query getCopilotRecentSessions($workspaceId: String!, $limit: Int = 10, $offset: Int = 0) { currentUser { __typename copilot(workspaceId: $workspaceId) { __typename chats( pagination: { first: $limit, offset: $offset } options: { action: false, fork: false, sessionOrder: desc, withMessages: false } ) { __typename ...PaginatedCopilotChats } } } }"#,
|
||||||
fragments: [CopilotChatHistory.self, CopilotChatMessage.self, PaginatedCopilotChats.self]
|
fragments: [CopilotChatHistory.self, CopilotChatMessage.self, PaginatedCopilotChats.self]
|
||||||
))
|
))
|
||||||
|
|
||||||
public var workspaceId: String
|
public var workspaceId: String
|
||||||
public var limit: GraphQLNullable<Int>
|
public var limit: GraphQLNullable<Int>
|
||||||
|
public var offset: GraphQLNullable<Int>
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
workspaceId: String,
|
workspaceId: String,
|
||||||
limit: GraphQLNullable<Int> = 10
|
limit: GraphQLNullable<Int> = 10,
|
||||||
|
offset: GraphQLNullable<Int> = 0
|
||||||
) {
|
) {
|
||||||
self.workspaceId = workspaceId
|
self.workspaceId = workspaceId
|
||||||
self.limit = limit
|
self.limit = limit
|
||||||
|
self.offset = offset
|
||||||
}
|
}
|
||||||
|
|
||||||
public var __variables: Variables? { [
|
public var __variables: Variables? { [
|
||||||
"workspaceId": workspaceId,
|
"workspaceId": workspaceId,
|
||||||
"limit": limit
|
"limit": limit,
|
||||||
|
"offset": offset
|
||||||
] }
|
] }
|
||||||
|
|
||||||
public struct Data: AffineGraphQL.SelectionSet {
|
public struct Data: AffineGraphQL.SelectionSet {
|
||||||
@@ -65,8 +69,12 @@ public class GetCopilotRecentSessionsQuery: GraphQLQuery {
|
|||||||
public static var __selections: [ApolloAPI.Selection] { [
|
public static var __selections: [ApolloAPI.Selection] { [
|
||||||
.field("__typename", String.self),
|
.field("__typename", String.self),
|
||||||
.field("chats", Chats.self, arguments: [
|
.field("chats", Chats.self, arguments: [
|
||||||
"pagination": ["first": .variable("limit")],
|
"pagination": [
|
||||||
|
"first": .variable("limit"),
|
||||||
|
"offset": .variable("offset")
|
||||||
|
],
|
||||||
"options": [
|
"options": [
|
||||||
|
"action": false,
|
||||||
"fork": false,
|
"fork": false,
|
||||||
"sessionOrder": "desc",
|
"sessionOrder": "desc",
|
||||||
"withMessages": false
|
"withMessages": false
|
||||||
|
|||||||
+7
@@ -12,6 +12,7 @@ public struct CreateChatMessageInput: InputObject {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
attachments: GraphQLNullable<[String]> = nil,
|
attachments: GraphQLNullable<[String]> = nil,
|
||||||
|
blob: GraphQLNullable<Upload> = nil,
|
||||||
blobs: GraphQLNullable<[Upload]> = nil,
|
blobs: GraphQLNullable<[Upload]> = nil,
|
||||||
content: GraphQLNullable<String> = nil,
|
content: GraphQLNullable<String> = nil,
|
||||||
params: GraphQLNullable<JSON> = nil,
|
params: GraphQLNullable<JSON> = nil,
|
||||||
@@ -19,6 +20,7 @@ public struct CreateChatMessageInput: InputObject {
|
|||||||
) {
|
) {
|
||||||
__data = InputDict([
|
__data = InputDict([
|
||||||
"attachments": attachments,
|
"attachments": attachments,
|
||||||
|
"blob": blob,
|
||||||
"blobs": blobs,
|
"blobs": blobs,
|
||||||
"content": content,
|
"content": content,
|
||||||
"params": params,
|
"params": params,
|
||||||
@@ -31,6 +33,11 @@ public struct CreateChatMessageInput: InputObject {
|
|||||||
set { __data["attachments"] = newValue }
|
set { __data["attachments"] = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var blob: GraphQLNullable<Upload> {
|
||||||
|
get { __data["blob"] }
|
||||||
|
set { __data["blob"] = newValue }
|
||||||
|
}
|
||||||
|
|
||||||
public var blobs: GraphQLNullable<[Upload]> {
|
public var blobs: GraphQLNullable<[Upload]> {
|
||||||
get { __data["blobs"] }
|
get { __data["blobs"] }
|
||||||
set { __data["blobs"] = newValue }
|
set { __data["blobs"] = newValue }
|
||||||
|
|||||||
+8
-9
@@ -167,8 +167,12 @@ private extension ChatManager {
|
|||||||
"files": [String](), // attachment in context, keep nil for now
|
"files": [String](), // attachment in context, keep nil for now
|
||||||
"searchMode": editorData.isSearchEnabled ? "MUST" : "AUTO",
|
"searchMode": editorData.isSearchEnabled ? "MUST" : "AUTO",
|
||||||
]
|
]
|
||||||
let attachmentFieldName = "options.blobs"
|
let hasMultipleAttachmentBlobs = [
|
||||||
var uploadableAttachments: [GraphQLFile] = [
|
editorData.fileAttachments.count,
|
||||||
|
editorData.documentAttachments.count,
|
||||||
|
].reduce(0, +) > 1
|
||||||
|
let attachmentFieldName = hasMultipleAttachmentBlobs ? "options.blobs" : "options.blob"
|
||||||
|
let uploadableAttachments: [GraphQLFile] = [
|
||||||
editorData.fileAttachments.map { file -> GraphQLFile in
|
editorData.fileAttachments.map { file -> GraphQLFile in
|
||||||
.init(fieldName: attachmentFieldName, originalName: file.name, data: file.data ?? .init())
|
.init(fieldName: attachmentFieldName, originalName: file.name, data: file.data ?? .init())
|
||||||
},
|
},
|
||||||
@@ -177,15 +181,10 @@ private extension ChatManager {
|
|||||||
},
|
},
|
||||||
].flatMap(\.self)
|
].flatMap(\.self)
|
||||||
assert(uploadableAttachments.allSatisfy { !($0.data?.isEmpty ?? true) })
|
assert(uploadableAttachments.allSatisfy { !($0.data?.isEmpty ?? true) })
|
||||||
// in Apollo, filed name is handled as attached object to field when there is only one attachment
|
|
||||||
// to use array on our server, we need to append a dummy attachment
|
|
||||||
// which is ignored if data is empty and name is empty
|
|
||||||
if uploadableAttachments.count == 1 {
|
|
||||||
uploadableAttachments.append(.init(fieldName: attachmentFieldName, originalName: "", data: .init()))
|
|
||||||
}
|
|
||||||
guard let input = try? CreateChatMessageInput(
|
guard let input = try? CreateChatMessageInput(
|
||||||
attachments: [],
|
attachments: [],
|
||||||
blobs: .some([]), // must have the placeholder
|
blob: hasMultipleAttachmentBlobs ? .none : "",
|
||||||
|
blobs: hasMultipleAttachmentBlobs ? .some([]) : .none,
|
||||||
content: .some(contextSnippet.isEmpty ? editorData.text : "\(contextSnippet)\n\(editorData.text)"),
|
content: .some(contextSnippet.isEmpty ? editorData.text : "\(contextSnippet)\n\(editorData.text)"),
|
||||||
params: .some(AffineGraphQL.JSON(_jsonValue: messageParameters)),
|
params: .some(AffineGraphQL.JSON(_jsonValue: messageParameters)),
|
||||||
sessionId: sessionId
|
sessionId: sessionId
|
||||||
|
|||||||
+1
-1
@@ -62,7 +62,7 @@ public class IntelligentContext {
|
|||||||
"Login required: \(reason)"
|
"Login required: \(reason)"
|
||||||
case let .sessionCreationFailed(reason):
|
case let .sessionCreationFailed(reason):
|
||||||
"Session creation failed: \(reason)"
|
"Session creation failed: \(reason)"
|
||||||
case let .featureClosed:
|
case .featureClosed:
|
||||||
"Intelligent feature closed"
|
"Intelligent feature closed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,13 +45,13 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../../../../../node_modules/capacitor-plugin-app-tracking-transparency"
|
:path: "../../../../../node_modules/capacitor-plugin-app-tracking-transparency"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Capacitor: 106e7a4205f4618d582b886a975657c61179138d
|
Capacitor: 03bc7cbdde6a629a8b910a9d7d78c3cc7ed09ea7
|
||||||
CapacitorApp: d63334c052278caf5d81585d80b21905c6f93f39
|
CapacitorApp: febecbb9582cb353aed037e18ec765141f880fe9
|
||||||
CapacitorBrowser: 081852cf532acf77b9d2953f3a88fe5b9711fb06
|
CapacitorBrowser: 6299776d496e968505464884d565992faa20444a
|
||||||
CapacitorCordova: 5967b9ba03915ef1d585469d6e31f31dc49be96f
|
CapacitorCordova: 5967b9ba03915ef1d585469d6e31f31dc49be96f
|
||||||
CapacitorHaptics: 70e47470fa1a6bd6338cd102552e3846b7f9a1b3
|
CapacitorHaptics: 1f1e17041f435d8ead9ff2a34edd592c6aa6a8d6
|
||||||
CapacitorKeyboard: 969647d0ca2e5c737d7300088e2517aa832434e2
|
CapacitorKeyboard: 09fd91dcde4f8a37313e7f11bde553ad1ed52036
|
||||||
CapacitorPluginAppTrackingTransparency: 2a2792623a5a72795f2e8f9ab3f1147573732fd8
|
CapacitorPluginAppTrackingTransparency: 92ae9c1cfb5cf477753db9269689332a686f675a
|
||||||
CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483
|
CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483
|
||||||
|
|
||||||
PODFILE CHECKSUM: 2c1e4be82121f2d9724ecf7e31dd14e165aeb082
|
PODFILE CHECKSUM: 2c1e4be82121f2d9724ecf7e31dd14e165aeb082
|
||||||
|
|||||||
Reference in New Issue
Block a user