committed by
GitHub
14 changed files with 405 additions and 94 deletions
@ -0,0 +1,84 @@ |
|||
<script setup lang="ts"> |
|||
import type { PropertyInfo } from '@abp/ui'; |
|||
|
|||
import type { AIToolPropertyDescriptorDto } from '../../types/tools'; |
|||
|
|||
import { PropertyTable } from '@abp/ui'; |
|||
import { |
|||
Checkbox, |
|||
FormItemRest, |
|||
Input, |
|||
InputNumber, |
|||
Select, |
|||
} from 'ant-design-vue'; |
|||
|
|||
const props = defineProps<{ |
|||
model: Record<string, any>; |
|||
property: AIToolPropertyDescriptorDto; |
|||
}>(); |
|||
const emit = defineEmits<{ |
|||
(event: 'change', data: Record<string, any>): void; |
|||
(event: 'update:value', data: Record<string, any>): void; |
|||
}>(); |
|||
const onValueChange = (value?: any) => { |
|||
const prop = props.model; |
|||
prop[props.property.name] = value; |
|||
emit('change', prop); |
|||
emit('update:value', prop); |
|||
}; |
|||
const onPropChange = (propertyInfo: PropertyInfo) => { |
|||
const prop = props.model; |
|||
prop[props.property.name] ??= {}; |
|||
prop[props.property.name][propertyInfo.key] = propertyInfo.value; |
|||
emit('change', prop); |
|||
emit('update:value', prop); |
|||
}; |
|||
const onPropDelete = (propertyInfo: PropertyInfo) => { |
|||
const prop = props.model; |
|||
prop[props.property.name] ??= {}; |
|||
delete prop[props.property.name][propertyInfo.key]; |
|||
emit('change', prop); |
|||
emit('update:value', prop); |
|||
}; |
|||
</script> |
|||
|
|||
<template> |
|||
<InputNumber |
|||
v-if="property.valueType === 'Number'" |
|||
class="w-full" |
|||
:min="0" |
|||
:value="model[property.name]" |
|||
@change="onValueChange($event)" |
|||
/> |
|||
<Input |
|||
v-if="property.valueType === 'String'" |
|||
class="w-full" |
|||
:min="0" |
|||
:value="model[property.name]" |
|||
@change="onValueChange($event.target.value)" |
|||
/> |
|||
<Checkbox |
|||
v-else-if="property.valueType === 'Boolean'" |
|||
:checked="model[property.name] === true" |
|||
@change="onValueChange($event.target.checked)" |
|||
> |
|||
{{ property.displayName }} |
|||
</Checkbox> |
|||
<Select |
|||
v-else-if="property.valueType === 'Select'" |
|||
class="w-full" |
|||
:options="property.options" |
|||
:field-names="{ label: 'name', value: 'value' }" |
|||
:value="model[property.name]" |
|||
@change="onValueChange($event)" |
|||
/> |
|||
<FormItemRest v-else-if="property.valueType === 'Dictionary'"> |
|||
<PropertyTable |
|||
:data="model[property.name]" |
|||
@change="onPropChange" |
|||
@delete="onPropDelete" |
|||
/> |
|||
</FormItemRest> |
|||
</template> |
|||
|
|||
<style scoped></style> |
|||
@ -0,0 +1,31 @@ |
|||
using System.Threading.Tasks; |
|||
using System.Web; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.AI.Tools.Mcp; |
|||
|
|||
[Dependency(TryRegister = true)] |
|||
public class DefaultMcpAuthorizationCodeProvider : IMcpAuthorizationCodeProvider, ISingletonDependency |
|||
{ |
|||
public async virtual Task<string?> HandleAsync(McpAuthorizationCodeHandleContext context) |
|||
{ |
|||
using var redirectResponse = await context.HttpClient.GetAsync(context.AuthorizationUrl, context.CancellationToken); |
|||
var location = redirectResponse.Headers.Location; |
|||
|
|||
if (location is not null && !string.IsNullOrEmpty(location.Query)) |
|||
{ |
|||
// Parse query string to extract "code" parameter
|
|||
var query = location.Query.TrimStart('?'); |
|||
foreach (var pair in query.Split('&')) |
|||
{ |
|||
var parts = pair.Split('=', 2); |
|||
if (parts.Length == 2 && parts[0] == "code") |
|||
{ |
|||
return HttpUtility.UrlDecode(parts[1]); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.AI.Tools.Mcp; |
|||
public interface IMcpAuthorizationCodeProvider |
|||
{ |
|||
Task<string?> HandleAsync(McpAuthorizationCodeHandleContext context); |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using System; |
|||
using System.Net.Http; |
|||
using System.Threading; |
|||
|
|||
namespace LINGYUN.Abp.AI.Tools.Mcp; |
|||
public class McpAuthorizationCodeHandleContext |
|||
{ |
|||
public IServiceProvider ServiceProvider { get; } |
|||
public HttpClient HttpClient { get; } |
|||
public Uri AuthorizationUrl { get; } |
|||
public Uri RedirectUri { get; } |
|||
public CancellationToken CancellationToken { get; } |
|||
public McpAuthorizationCodeHandleContext( |
|||
IServiceProvider serviceProvider, |
|||
HttpClient httpClient, |
|||
Uri authorizationUrl, |
|||
Uri redirectUri, |
|||
CancellationToken cancellationToken) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
HttpClient = httpClient; |
|||
AuthorizationUrl = authorizationUrl; |
|||
RedirectUri = redirectUri; |
|||
CancellationToken = cancellationToken; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue