From 50f649f73048a2a5d4394e475326782d34cab2b8 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Tue, 8 Apr 2025 16:49:55 +0300 Subject: [PATCH 1/9] Add files searching --- .../FilesPlugin/files-apiplugin.json | 36 ++ .../FilesPlugin/files-openapi.yml | 480 ++++++++++++++++++ .../DemoCommand.cs | 11 + 3 files changed, 527 insertions(+) create mode 100644 dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-apiplugin.json create mode 100644 dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-openapi.yml diff --git a/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-apiplugin.json b/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-apiplugin.json new file mode 100644 index 000000000000..3ed47615f328 --- /dev/null +++ b/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-apiplugin.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.1/schema.json", + "schema_version": "v2.1", + "name_for_human": "OData Service for namespace microsoft.graph", + "description_for_human": "This OData service is located at https://graph.microsoft.com/v1.0", + "description_for_model": "This OData service is located at https://graph.microsoft.com/v1.0", + "contact_email": "publisher-email@example.com", + "namespace": "Files", + "capabilities": { + "conversation_starters": [ + { + "text": "Invoke action query" + } + ] + }, + "functions": [ + { + "name": "search_query", + "description": "Runs the query specified in the request body. Search results are provided in the response." + } + ], + "runtimes": [ + { + "type": "OpenApi", + "auth": { + "type": "None" + }, + "spec": { + "url": "files-openapi.yml" + }, + "run_for_functions": [ + "search_query" + ] + } + ] +} \ No newline at end of file diff --git a/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-openapi.yml b/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-openapi.yml new file mode 100644 index 000000000000..9bdb0610b009 --- /dev/null +++ b/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-openapi.yml @@ -0,0 +1,480 @@ +openapi: 3.0.4 +info: + title: OData Service for namespace microsoft.graph - Subset + description: This OData service is located at https://graph.microsoft.com/v1.0 + version: v1.0 +servers: + - url: https://graph.microsoft.com/v1.0 +paths: + /search/query: + post: + tags: + - search.searchEntity.Actions + summary: Invoke action query + description: Runs the query specified in the request body. Search results are provided in the response. + operationId: search_query + requestBody: + description: Action parameters + content: + application/json: + schema: + type: object + properties: + requests: + type: array + items: + title: searchRequest + required: + - '@odata.type' + type: object + properties: + aggregationFilters: + type: array + items: + type: string + nullable: true + description: 'Contains one or more filters to obtain search results aggregated and filtered to a specific value of a field. Optional.Build this filter based on a prior search that aggregates by the same field. From the response of the prior search, identify the searchBucket that filters results to the specific value of the field, use the string in its aggregationFilterToken property, and build an aggregation filter string in the format ''{field}:/''{aggregationFilterToken}/''''. If multiple values for the same field need to be provided, use the strings in its aggregationFilterToken property and build an aggregation filter string in the format ''{field}:or(/''{aggregationFilterToken1}/'',/''{aggregationFilterToken2}/'')''. For example, searching and aggregating drive items by file type returns a searchBucket for the file type docx in the response. You can conveniently use the aggregationFilterToken returned for this searchBucket in a subsequent search query and filter matches down to drive items of the docx file type. Example 1 and example 2 show the actual requests and responses.' + aggregations: + type: array + items: + title: aggregationOption + required: + - '@odata.type' + type: object + properties: + bucketDefinition: + title: bucketAggregationDefinition + required: + - '@odata.type' + type: object + properties: + isDescending: + type: boolean + nullable: true + description: 'True to specify the sort order as descending. The default is false, with the sort order as ascending. Optional.' + minimumCount: + maximum: 2147483647 + minimum: -2147483648 + type: number + nullable: true + description: The minimum number of items that should be present in the aggregation to be returned in a bucket. Optional. + format: int32 + prefixFilter: + type: string + nullable: true + description: A filter to define a matching criteria. The key should start with the specified prefix to be returned in the response. Optional. + ranges: + type: array + items: + title: bucketAggregationRange + required: + - '@odata.type' + type: object + properties: + from: + type: string + description: Defines the lower bound from which to compute the aggregation. This can be a numeric value or a string representation of a date using the YYYY-MM-DDTHH:mm:ss.sssZ format. Required. + to: + type: string + description: Defines the upper bound up to which to compute the aggregation. This can be a numeric value or a string representation of a date using the YYYY-MM-DDTHH:mm:ss.sssZ format. Required. + '@odata.type': + type: string + description: Specifies the manual ranges to compute the aggregations. This is only valid for nonstring refiners of date or numeric type. Optional. + sortBy: + title: bucketAggregationSortProperty + enum: + - count + - keyAsString + - keyAsNumber + - unknownFutureValue + type: string + '@odata.type': + type: string + field: + type: string + description: Computes aggregation on the field while the field exists in the current entity type. Required. + size: + maximum: 2147483647 + minimum: -2147483648 + type: number + nullable: true + description: 'The number of searchBucket resources to be returned. This isn''t required when the range is provided manually in the search request. The minimum accepted size is 1, and the maximum is 65535. Optional.' + format: int32 + '@odata.type': + type: string + description: Specifies aggregations (also known as refiners) to be returned alongside search results. Optional. + collapseProperties: + type: array + items: + title: collapseProperty + required: + - '@odata.type' + type: object + properties: + fields: + type: array + items: + type: string + description: Defines the collapse group to trim results. The properties in this collection must be sortable/refinable properties. Required. + limit: + maximum: 32767 + minimum: -32768 + type: number + description: Defines a maximum limit count for this field. This numeric value must be a positive integer. Required. + format: int16 + '@odata.type': + type: string + description: Contains the ordered collection of fields and limit to collapse results. Optional. + contentSources: + type: array + items: + type: string + nullable: true + description: Contains the connection to be targeted. + enableTopResults: + type: boolean + nullable: true + description: 'This triggers hybrid sort for messages : the first 3 messages are the most relevant. This property is only applicable to entityType=message. Optional.' + entityTypes: + type: array + items: + title: entityType + enum: + - event + - message + - driveItem + - externalItem + - site + - list + - listItem + - drive + - unknownFutureValue + - chatMessage + - person + - acronym + - bookmark + type: string + description: 'One or more types of resources expected in the response. Possible values are: event, message, driveItem, externalItem, site, list, listItem, drive, chatMessage, person, acronym, bookmark. Use the Prefer: include-unknown-enum-members request header to get the following value(s) in this evolvable enum: chatMessage, person, acronym, bookmark. See known limitations for those combinations of two or more entity types that are supported in the same search request. Required.' + fields: + type: array + items: + type: string + nullable: true + description: 'Contains the fields to be returned for each resource object specified in entityTypes, allowing customization of the fields returned by default; otherwise, including additional fields such as custom managed properties from SharePoint and OneDrive, or custom fields in externalItem from the content that Microsoft Graph connectors bring in. The fields property can use the semantic labels applied to properties. For example, if a property is labeled as title, you can retrieve it using the following syntax: label_title. Optional.' + from: + maximum: 2147483647 + minimum: -2147483648 + type: number + description: Specifies the offset for the search results. Offset 0 returns the very first result. Optional. + format: int32 + query: + title: searchQuery + required: + - '@odata.type' + type: object + properties: + queryString: + type: string + description: The search query containing the search terms. Required. + queryTemplate: + type: string + nullable: true + description: Provides a way to decorate the query string. Supports both KQL and query variables. Optional. + '@odata.type': + type: string + queryAlterationOptions: + title: searchAlterationOptions + required: + - '@odata.type' + type: object + properties: + enableModification: + type: boolean + nullable: true + description: 'Indicates whether spelling modifications are enabled. If enabled, the user gets the search results for the corrected query if there were no results for the original query with typos. The response will also include the spelling modification information in the queryAlterationResponse property. Optional.' + enableSuggestion: + type: boolean + nullable: true + description: 'Indicates whether spelling suggestions are enabled. If enabled, the user gets the search results for the original search query and suggestions for spelling correction in the queryAlterationResponse property of the response for the typos in the query. Optional.' + '@odata.type': + type: string + region: + type: string + nullable: true + description: 'The geographic location for the search. Required for searches that use application permissions. For details, see Get the region value.' + resultTemplateOptions: + title: resultTemplateOption + required: + - '@odata.type' + type: object + properties: + enableResultTemplate: + type: boolean + nullable: true + description: 'Indicates whether search display layouts are enabled. If enabled, the user will get the result template to render the search results content in the resultTemplates property of the response. The result template is based on Adaptive Cards. Optional.' + '@odata.type': + type: string + sharePointOneDriveOptions: + title: sharePointOneDriveOptions + required: + - '@odata.type' + type: object + properties: + includeContent: + title: searchContent + enum: + - sharedContent + - privateContent + - unknownFutureValue + type: string + x-ms-enum-flags: + isFlags: true + '@odata.type': + type: string + size: + maximum: 2147483647 + minimum: -2147483648 + type: number + description: The size of the page to be retrieved. The maximum value is 500. Optional. + format: int32 + sortProperties: + type: array + items: + title: sortProperty + required: + - '@odata.type' + type: object + properties: + isDescending: + type: boolean + nullable: true + description: 'True if the sort order is descending. Default is false, with the sort order as ascending. Optional.' + name: + type: string + description: The name of the property to sort on. Required. + '@odata.type': + type: string + description: Contains the ordered collection of fields and direction to sort results. There can be at most 5 sort properties in the collection. Optional. + '@odata.type': + type: string + required: true + responses: + 2XX: + description: Success + content: + application/json: + schema: + title: Base collection pagination and count responses + type: object + properties: + '@odata.count': + type: integer + nullable: true + format: int64 + '@odata.nextLink': + type: string + nullable: true + value: + type: array + items: + title: searchResponse + required: + - '@odata.type' + type: object + properties: + hitsContainers: + type: array + items: + title: searchHitsContainer + required: + - '@odata.type' + type: object + properties: + aggregations: + type: array + items: + title: searchAggregation + required: + - '@odata.type' + type: object + properties: + buckets: + type: array + items: + title: searchBucket + required: + - '@odata.type' + type: object + properties: + aggregationFilterToken: + type: string + nullable: true + description: 'A token containing the encoded filter to aggregate search matches by the specific key value. To use the filter, pass the token as part of the aggregationFilter property in a searchRequest object, in the format ''{field}:/''{aggregationFilterToken}/''''. See an example.' + count: + maximum: 2147483647 + minimum: -2147483648 + type: number + nullable: true + description: The approximate number of search matches that share the same value specified in the key property. Note that this number is not the exact number of matches. + format: int32 + key: + type: string + nullable: true + description: The discrete value of the field that an aggregation was computed on. + '@odata.type': + type: string + field: + type: string + nullable: true + '@odata.type': + type: string + hits: + type: array + items: + title: searchHit + required: + - '@odata.type' + type: object + properties: + contentSource: + type: string + nullable: true + description: The name of the content source that the externalItem is part of. + hitId: + type: string + nullable: true + description: 'The internal identifier for the item. The format of the identifier varies based on the entity type. For details, see hitId format.' + isCollapsed: + type: boolean + nullable: true + description: Indicates whether the current result is collapsed when the collapseProperties property in the searchRequest is used. + rank: + maximum: 2147483647 + minimum: -2147483648 + type: number + nullable: true + description: The rank or the order of the result. + format: int32 + resultTemplateId: + type: string + nullable: true + description: ID of the result template used to render the search result. This ID must map to a display layout in the resultTemplates dictionary that is also included in the searchResponse. + summary: + type: string + nullable: true + description: 'A summary of the result, if a summary is available.' + resource: + title: entity + required: + - '@odata.type' + type: object + properties: + id: + type: string + description: The unique identifier for an entity. Read-only. + '@odata.type': + type: string + discriminator: + propertyName: '@odata.type' + '@odata.type': + type: string + description: A collection of the search results. + moreResultsAvailable: + type: boolean + nullable: true + description: 'Provides information if more results are available. Based on this information, you can adjust the from and size properties of the searchRequest accordingly.' + total: + maximum: 2147483647 + minimum: -2147483648 + type: number + nullable: true + description: 'The total number of results. Note this isn''t the number of results on the page, but the total number of results satisfying the query.' + format: int32 + '@odata.type': + type: string + description: A collection of search results. + queryAlterationResponse: + title: alterationResponse + required: + - '@odata.type' + type: object + properties: + originalQueryString: + type: string + nullable: true + description: Defines the original user query string. + queryAlteration: + title: searchAlteration + required: + - '@odata.type' + type: object + properties: + alteredHighlightedQueryString: + type: string + nullable: true + description: 'Defines the altered highlighted query string with spelling correction. The annotation around the corrected segment is: /ue000, /ue001.' + alteredQueryString: + type: string + nullable: true + description: Defines the altered query string with spelling correction. + alteredQueryTokens: + type: array + items: + title: alteredQueryToken + required: + - '@odata.type' + type: object + properties: + length: + maximum: 2147483647 + minimum: -2147483648 + type: number + nullable: true + description: Defines the length of a changed segment. + format: int32 + offset: + maximum: 2147483647 + minimum: -2147483648 + type: number + nullable: true + description: Defines the offset of a changed segment. + format: int32 + suggestion: + type: string + nullable: true + description: Represents the corrected segment string. + '@odata.type': + type: string + description: Represents changed segments related to an original user query. + '@odata.type': + type: string + queryAlterationType: + title: searchAlterationType + enum: + - suggestion + - modification + - unknownFutureValue + type: string + '@odata.type': + type: string + resultTemplates: + title: resultTemplateDictionary + required: + - '@odata.type' + type: object + properties: + '@odata.type': + type: string + searchTerms: + type: array + items: + type: string + nullable: true + description: Contains the search terms sent in the initial search query. + '@odata.type': + type: string + x-ms-pageable: + nextLinkName: '@odata.nextLink' + operationName: listMore + itemName: value +components: { } \ No newline at end of file diff --git a/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs b/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs index 336b1832e455..33c792b2fc49 100644 --- a/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs +++ b/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs @@ -440,6 +440,16 @@ await kernel.ImportPluginFromCopilotAgentPluginAsync( "uniqueId", "uniqueIdType", "webLink", + "aggregationFilters", + "aggregations", + "collapseProperties", + "contentSources", + "enableTopResults", + "fields", + "region", + "resultTemplateOptions", + "sortProperties", + ], StringComparer.OrdinalIgnoreCase ); @@ -500,6 +510,7 @@ private static void TrimPropertiesFromJsonNode(JsonNode jsonNode) { #pragma warning restore SKEXP0040 if (("me_sendMail".Equals(context.Operation.Id, StringComparison.OrdinalIgnoreCase) || + ("search_query".Equals(context.Operation.Id, StringComparison.OrdinalIgnoreCase)) || ("me_calendar_CreateEvents".Equals(context.Operation.Id, StringComparison.OrdinalIgnoreCase)) && "payload".Equals(context.Parameter.Name, StringComparison.OrdinalIgnoreCase))) { From 62d5c2a7fb7399c539e7645ce841c66388a35fb6 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 14 Apr 2025 14:25:26 +0300 Subject: [PATCH 2/9] chore: sort fields to ignore alphabetically --- .../DemoCommand.cs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs b/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs index 33c792b2fc49..2b39d2232333 100644 --- a/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs +++ b/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs @@ -389,36 +389,42 @@ await kernel.ImportPluginFromCopilotAgentPluginAsync( private static readonly HashSet s_fieldsToIgnore = new( [ "@odata.type", - "attachments", + "aggregationFilters", + "aggregations", "allowNewTimeProposals", + "attachments", "bccRecipients", "bodyPreview", "calendar", "categories", "ccRecipients", "changeKey", + "collapseProperties", + "contentSources", "conversationId", - "coordinates", "conversationIndex", + "coordinates", "createdDateTime", "discriminator", - "lastModifiedDateTime", - "locations", + "enableTopResults", "extensions", + "fields", "flag", "from", "hasAttachments", "iCalUId", "id", "inferenceClassification", - "internetMessageHeaders", "instances", + "internetMessageHeaders", "isCancelled", "isDeliveryReceiptRequested", "isDraft", "isOrganizer", "isRead", "isReadReceiptRequested", + "lastModifiedDateTime", + "locations", "multiValueExtendedProperties", "onlineMeeting", "onlineMeetingProvider", @@ -429,26 +435,20 @@ await kernel.ImportPluginFromCopilotAgentPluginAsync( "range", "receivedDateTime", "recurrence", + "region", "replyTo", + "resultTemplateOptions", "sender", "sentDateTime", "seriesMasterId", "singleValueExtendedProperties", - "transactionId", + "sortProperties", "time", + "transactionId", "uniqueBody", "uniqueId", "uniqueIdType", "webLink", - "aggregationFilters", - "aggregations", - "collapseProperties", - "contentSources", - "enableTopResults", - "fields", - "region", - "resultTemplateOptions", - "sortProperties", ], StringComparer.OrdinalIgnoreCase From aa198e8be82810232022c4b0b97c2ddd9b5b3a08 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 14 Apr 2025 18:12:51 +0300 Subject: [PATCH 3/9] Add a utility function to give the LLMs the date today --- .../CopilotAgentPluginsDemoSample/DemoCommand.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs b/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs index 2b39d2232333..ab3de5bd58fa 100644 --- a/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs +++ b/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs @@ -55,6 +55,13 @@ public override async Task ExecuteAsync(CommandContext context, Settings se _ => throw new InvalidOperationException($"Invalid kernel selection. {selectedKernelName} is not a valid kernel.") }; kernel.AutoFunctionInvocationFilters.Add(new ExpectedSchemaFunctionFilter()); + kernel.Plugins.AddFromFunctions("time_plugin", [ + KernelFunctionFactory.CreateFromMethod( + method: () => DateTime.Today, + functionName: "get_the_date_and_time_today", + description: "Get the date today and the time now." + ) + ]); while (true) { From 762bb94be5a6d94f39728c1f731e01882d5de539 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 14 Apr 2025 18:13:21 +0300 Subject: [PATCH 4/9] Add new functions to trim properties --- .../CopilotAgentPluginsDemoSample/DemoCommand.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs b/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs index ab3de5bd58fa..dcc867a2d981 100644 --- a/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs +++ b/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs @@ -516,10 +516,9 @@ private static void TrimPropertiesFromJsonNode(JsonNode jsonNode) private static readonly RestApiParameterFilter s_restApiParameterFilter = (RestApiParameterFilterContext context) => { #pragma warning restore SKEXP0040 - if (("me_sendMail".Equals(context.Operation.Id, StringComparison.OrdinalIgnoreCase) || - ("search_query".Equals(context.Operation.Id, StringComparison.OrdinalIgnoreCase)) || - ("me_calendar_CreateEvents".Equals(context.Operation.Id, StringComparison.OrdinalIgnoreCase)) && - "payload".Equals(context.Parameter.Name, StringComparison.OrdinalIgnoreCase))) + string[] _functionNames = ["drives_GetItemsContent", "me_calendar_CreateEvents", "me_sendMail", "search_query", "sites_lists_items_GetDriveItemContent"]; + bool hasFunctionName = _functionNames.Any(s => s.Equals(context.Operation.Id, StringComparison.OrdinalIgnoreCase)); + if (hasFunctionName && "payload".Equals(context.Parameter.Name, StringComparison.OrdinalIgnoreCase)) { context.Parameter.Schema = TrimPropertiesFromRequestBody(context.Parameter.Schema); return context.Parameter; From 78f065615f20d5d86ba20b78ca3ee53370af4b43 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 14 Apr 2025 18:14:37 +0300 Subject: [PATCH 5/9] Update the sites and drive content fetch endpoints --- .../FilesPlugin/files-apiplugin.json | 18 ++++- .../FilesPlugin/files-openapi.yml | 76 +++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-apiplugin.json b/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-apiplugin.json index 3ed47615f328..6a2e39a845eb 100644 --- a/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-apiplugin.json +++ b/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-apiplugin.json @@ -8,15 +8,29 @@ "namespace": "Files", "capabilities": { "conversation_starters": [ + { + "text": "Get content for the navigation property items from" + }, { "text": "Invoke action query" + }, + { + "text": "Get content for the navigation property driveItem " } ] }, "functions": [ + { + "name": "drives_GetItemsContent", + "description": "The content stream, if the item represents a file." + }, { "name": "search_query", "description": "Runs the query specified in the request body. Search results are provided in the response." + }, + { + "name": "sites_lists_items_GetDriveItemContent", + "description": "The content stream, if the item represents a file." } ], "runtimes": [ @@ -29,7 +43,9 @@ "url": "files-openapi.yml" }, "run_for_functions": [ - "search_query" + "drives_GetItemsContent", + "search_query", + "sites_lists_items_GetDriveItemContent" ] } ] diff --git a/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-openapi.yml b/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-openapi.yml index 9bdb0610b009..335723eb89df 100644 --- a/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-openapi.yml +++ b/dotnet/samples/Concepts/Resources/Plugins/CopilotAgentPlugins/FilesPlugin/files-openapi.yml @@ -6,6 +6,41 @@ info: servers: - url: https://graph.microsoft.com/v1.0 paths: + '/drives/{drive-id}/items/{driveItem-id}/content': + get: + tags: + - drives.driveItem + summary: Get content for the navigation property items from drives + description: 'The content stream, if the item represents a file.' + operationId: drives_GetItemsContent + parameters: + - name: $format + in: query + description: Format of the content + explode: false + schema: + type: string + responses: + 2XX: + description: Retrieved media content + content: + application/octet-stream: + schema: + type: string + format: binary + parameters: + - name: drive-id + in: path + description: The unique identifier of drive + required: true + schema: + type: string + - name: driveItem-id + in: path + description: The unique identifier of driveItem + required: true + schema: + type: string /search/query: post: tags: @@ -477,4 +512,45 @@ paths: nextLinkName: '@odata.nextLink' operationName: listMore itemName: value + '/sites/{site-id}/lists/{list-id}/items/{listItem-id}/driveItem/content': + get: + tags: + - sites.list + summary: Get content for the navigation property driveItem from sites + description: 'The content stream, if the item represents a file.' + operationId: sites_lists_items_GetDriveItemContent + parameters: + - name: $format + in: query + description: Format of the content + explode: false + schema: + type: string + responses: + 2XX: + description: Retrieved media content + content: + application/octet-stream: + schema: + type: string + format: binary + parameters: + - name: site-id + in: path + description: The unique identifier of site + required: true + schema: + type: string + - name: list-id + in: path + description: The unique identifier of list + required: true + schema: + type: string + - name: listItem-id + in: path + description: The unique identifier of listItem + required: true + schema: + type: string components: { } \ No newline at end of file From 6cc9fb450656d77aaacaea2c01fa9b46f8e8235a Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 14 Apr 2025 18:15:59 +0300 Subject: [PATCH 6/9] Add debug option to debug command --- .vscode/launch.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index d643e4be4b96..e274d51c7211 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,8 @@ "preLaunchTask": "build (CopilotAgentPluginsDemoSample)", "program": "${workspaceFolder}/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/bin/Debug/net8.0/CopilotAgentPluginsDemoSample.exe", "args": [ - "demo" + "demo", + "--debug" ], "cwd": "${workspaceFolder}/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample", "stopAtEntry": false, From 59caf3353d102bc02ba399031d38856561f5b443 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 14 Apr 2025 18:19:26 +0300 Subject: [PATCH 7/9] Add ue to spell checker exemptions --- .vscode/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 8be83c425f2f..eb32cf6e5334 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -73,7 +73,8 @@ "superstep", "Supersteps", "typeref", - "uninstantiated" + "uninstantiated", + "ue" ], "[java]": { "editor.formatOnSave": false, From 7e786d26407680c51ae3ce124d4504bb6db9ef6e Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 14 Apr 2025 18:27:09 +0300 Subject: [PATCH 8/9] Ignore typos on copilot plugin and manifest files --- .github/_typos.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/_typos.toml b/.github/_typos.toml index aaba7f3b7291..512bcb7080a7 100644 --- a/.github/_typos.toml +++ b/.github/_typos.toml @@ -26,7 +26,9 @@ extend-exclude = [ "SK-dotnet.sln.DotSettings", "**/azure_ai_search_hotel_samples/README.md", "**/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ProcessOrchestrator/Program.cs", - "**/Demos/ProcessFrameworkWithAspire/**/*.http" + "**/Demos/ProcessFrameworkWithAspire/**/*.http", + "**/Concepts/Resources/Plugins/CopilotAgentPlugins/**/*.yml", + "**/Concepts/Resources/Plugins/CopilotAgentPlugins/**/*.json" ] [default.extend-words] From dce1fee43a4cfdba0cc298bb60e4f0f0105a0179 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Wed, 16 Apr 2025 19:59:51 +0300 Subject: [PATCH 9/9] Handle _format parameter for drives_GetItemsContent --- .../CopilotAgentPluginsDemoSample/DemoCommand.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs b/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs index dcc867a2d981..afd5dd9a3ad9 100644 --- a/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs +++ b/dotnet/samples/Demos/CopilotAgentPlugins/CopilotAgentPluginsDemoSample/DemoCommand.cs @@ -516,6 +516,13 @@ private static void TrimPropertiesFromJsonNode(JsonNode jsonNode) private static readonly RestApiParameterFilter s_restApiParameterFilter = (RestApiParameterFilterContext context) => { #pragma warning restore SKEXP0040 + // Handle _format parameter for drives_GetItemsContent + if (context.Operation.Id.Equals("drives_GetItemsContent", StringComparison.OrdinalIgnoreCase) + && context.Parameter.Name.Equals("$format", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + string[] _functionNames = ["drives_GetItemsContent", "me_calendar_CreateEvents", "me_sendMail", "search_query", "sites_lists_items_GetDriveItemContent"]; bool hasFunctionName = _functionNames.Any(s => s.Equals(context.Operation.Id, StringComparison.OrdinalIgnoreCase)); if (hasFunctionName && "payload".Equals(context.Parameter.Name, StringComparison.OrdinalIgnoreCase))