diff --git a/Drawer/.editorconfig b/Drawer/.editorconfig new file mode 100644 index 00000000..5b5c7082 --- /dev/null +++ b/Drawer/.editorconfig @@ -0,0 +1,238 @@ +[*.cs] + +# 禁用命名规则,因为与 StyleCop 冲突 +dotnet_diagnostic.SA1300.severity = none +# dotnet_diagnostic.SA1301.severity = none +# dotnet_diagnostic.SA1302.severity = none +# dotnet_diagnostic.SA1303.severity = none +# dotnet_diagnostic.SA1304.severity = none +# dotnet_diagnostic.SA1305.severity = none +# dotnet_diagnostic.SA1306.severity = none +# dotnet_diagnostic.SA1307.severity = none +# dotnet_diagnostic.SA1308.severity = none +# dotnet_diagnostic.SA1309.severity = none +# dotnet_diagnostic.SA1310.severity = none +# dotnet_diagnostic.SA1311.severity = none +# dotnet_diagnostic.SA1312.severity = none +# dotnet_diagnostic.SA1313.severity = none +# dotnet_diagnostic.SA1314.severity = none + +# SA1649: File name should match first type name +dotnet_diagnostic.SA1649.severity = none + +# SA1200: Using directives should be placed correctly +dotnet_diagnostic.SA1200.severity = none + +# SA1629: Documentation text should end with a period +dotnet_diagnostic.SA1629.severity = none + +# SA1512: Single-line comments should not be followed by blank line +dotnet_diagnostic.SA1512.severity = none + +# Element documentation header should be preceded by blank line +dotnet_diagnostic.SA1514.severity = none + +# SA1516: Elements should be separated by blank line +dotnet_diagnostic.SA1516.severity = none + +# SA1515: Single-line comment should be preceded by blank line +dotnet_diagnostic.SA1515.severity = none + +# SA1513: Closing brace should be followed by blank line +dotnet_diagnostic.SA1513.severity = none + +# SA1113: Comma should be on the same line as previous parameter +dotnet_diagnostic.SA1113.severity = none + +# SA1001: Commas should be spaced correctly +dotnet_diagnostic.SA1001.severity = none +csharp_using_directive_placement = outside_namespace:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_var_for_built_in_types = false:suggestion +csharp_style_var_when_type_is_apparent = false:suggestion +csharp_style_var_elsewhere = false:suggestion +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = block_scoped:silent + +# SA1201: Elements should appear in the correct order +# dotnet_diagnostic.SA1201.severity = none + +[*.{cs,vb}] +end_of_line = crlf +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_code_quality_unused_parameters = all:suggestion +dotnet_style_readonly_field = true:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +tab_width = 4 +indent_size = 4 +dotnet_style_operator_placement_when_wrapping = beginning_of_line +[*.cs] +#### 命名样式 #### + +# 命名规则 + +dotnet_naming_rule.接口_should_be_以_i_开始.severity = warning +dotnet_naming_rule.接口_should_be_以_i_开始.symbols = 接口 +dotnet_naming_rule.接口_should_be_以_i_开始.style = 以_i_开始 + +dotnet_naming_rule.私有方法_should_be_camel拼写法.severity = warning +dotnet_naming_rule.私有方法_should_be_camel拼写法.symbols = 私有方法 +dotnet_naming_rule.私有方法_should_be_camel拼写法.style = camel拼写法 + +dotnet_naming_rule.方法_should_be_帕斯卡拼写法.severity = warning +dotnet_naming_rule.方法_should_be_帕斯卡拼写法.symbols = 方法 +dotnet_naming_rule.方法_should_be_帕斯卡拼写法.style = 帕斯卡拼写法 + +# 符号规范 + +dotnet_naming_symbols.接口.applicable_kinds = interface +dotnet_naming_symbols.接口.applicable_accessibilities = public, internal, private, protected, protected_internal +dotnet_naming_symbols.接口.required_modifiers = + +dotnet_naming_symbols.私有方法.applicable_kinds = method +dotnet_naming_symbols.私有方法.applicable_accessibilities = private +dotnet_naming_symbols.私有方法.required_modifiers = + +dotnet_naming_symbols.方法.applicable_kinds = method +dotnet_naming_symbols.方法.applicable_accessibilities = public +dotnet_naming_symbols.方法.required_modifiers = + +# 命名样式 + +dotnet_naming_style.以_i_开始.required_prefix = I +dotnet_naming_style.以_i_开始.required_suffix = +dotnet_naming_style.以_i_开始.word_separator = +dotnet_naming_style.以_i_开始.capitalization = pascal_case + +dotnet_naming_style.camel拼写法.required_prefix = +dotnet_naming_style.camel拼写法.required_suffix = +dotnet_naming_style.camel拼写法.word_separator = +dotnet_naming_style.camel拼写法.capitalization = camel_case + +dotnet_naming_style.帕斯卡拼写法.required_prefix = +dotnet_naming_style.帕斯卡拼写法.required_suffix = +dotnet_naming_style.帕斯卡拼写法.word_separator = +dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_prefer_system_threading_lock = true:suggestion +csharp_style_prefer_primary_constructors = true:suggestion +csharp_prefer_static_anonymous_function = true:suggestion +csharp_prefer_static_local_function = true:suggestion +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_prefer_readonly_struct_member = true:suggestion +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_prefer_implicitly_typed_lambda_expression = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_unbound_generic_type_in_nameof = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_space_around_binary_operators = before_and_after +csharp_indent_labels = one_less_than_current + +# IDE1006: 命名样式 +dotnet_diagnostic.IDE1006.severity = none + +[*.vb] +#### 命名样式 #### + +# 命名规则 + +dotnet_naming_rule.interface_should_be_以_i_开始.severity = suggestion +dotnet_naming_rule.interface_should_be_以_i_开始.symbols = interface +dotnet_naming_rule.interface_should_be_以_i_开始.style = 以_i_开始 + +dotnet_naming_rule.类型_should_be_帕斯卡拼写法.severity = suggestion +dotnet_naming_rule.类型_should_be_帕斯卡拼写法.symbols = 类型 +dotnet_naming_rule.类型_should_be_帕斯卡拼写法.style = 帕斯卡拼写法 + +dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.severity = suggestion +dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.symbols = 非字段成员 +dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.style = 帕斯卡拼写法 + +# 符号规范 + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.类型.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.类型.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.类型.required_modifiers = + +dotnet_naming_symbols.非字段成员.applicable_kinds = property, event, method +dotnet_naming_symbols.非字段成员.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.非字段成员.required_modifiers = + +# 命名样式 + +dotnet_naming_style.以_i_开始.required_prefix = I +dotnet_naming_style.以_i_开始.required_suffix = +dotnet_naming_style.以_i_开始.word_separator = +dotnet_naming_style.以_i_开始.capitalization = pascal_case + +dotnet_naming_style.帕斯卡拼写法.required_prefix = +dotnet_naming_style.帕斯卡拼写法.required_suffix = +dotnet_naming_style.帕斯卡拼写法.word_separator = +dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case + +dotnet_naming_style.帕斯卡拼写法.required_prefix = +dotnet_naming_style.帕斯卡拼写法.required_suffix = +dotnet_naming_style.帕斯卡拼写法.word_separator = +dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case diff --git a/Drawer/.gitignore b/Drawer/.gitignore index f2c42941..d56c7c76 100644 --- a/Drawer/.gitignore +++ b/Drawer/.gitignore @@ -1,3 +1,4 @@ +bin packages # 忽略中间文件 @@ -25,4 +26,5 @@ MLMicroStructure.dll MLMicroStructure.pdb MicroStructurePP.dll MicroStructurePP.pdb -*.FileListAbsolute.txt \ No newline at end of file +*.FileListAbsolute.txt +obj/* \ No newline at end of file diff --git a/Drawer/AI/AI.csproj b/Drawer/AI/AI.csproj new file mode 100644 index 00000000..1dabb7a3 --- /dev/null +++ b/Drawer/AI/AI.csproj @@ -0,0 +1,36 @@ + + + + Library + net8.0-windows + enable + enable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Drawer/AI/AI.sln b/Drawer/AI/AI.sln new file mode 100644 index 00000000..6e942cc8 --- /dev/null +++ b/Drawer/AI/AI.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AI", "AI.csproj", "{F091FF6C-454D-F725-5E93-41983547B110}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F091FF6C-454D-F725-5E93-41983547B110}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F091FF6C-454D-F725-5E93-41983547B110}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F091FF6C-454D-F725-5E93-41983547B110}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F091FF6C-454D-F725-5E93-41983547B110}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FBDA3407-3A62-4B40-88D5-9D08353B1E4E} + EndGlobalSection +EndGlobal diff --git a/Drawer/AI/AISettings.cs b/Drawer/AI/AISettings.cs new file mode 100644 index 00000000..d87dad5c --- /dev/null +++ b/Drawer/AI/AISettings.cs @@ -0,0 +1,70 @@ +using System; +using System.IO; +using System.Text.Json; + +namespace AI +{ + /// + /// AI 服务配置 + /// + public class AISettings + { + /// + /// 模型 ID + /// + public string ModelId { get; set; } = string.Empty; + + /// + /// API Key + /// + public string ApiKey { get; set; } = string.Empty; + + /// + /// API Endpoint(OpenAI 兼容接口地址) + /// + public string Endpoint { get; set; } = string.Empty; + + /// + /// 从 DLL 所在目录旁的 ai-settings.json 加载配置。 + /// 若文件不存在,抛出 FileNotFoundException。 + /// + public static AISettings Load() + { + string baseDir = AppContext.BaseDirectory; + string configPath = Path.Combine(baseDir, "ai-settings.json"); + + if (!File.Exists(configPath)) + { + throw new FileNotFoundException( + $"AI 配置文件未找到,请在以下位置创建 ai-settings.json:{configPath}\n" + + "文件格式示例:\n" + + "{\n" + + " \"ModelId\": \"deepseek-v3\",\n" + + " \"ApiKey\": \"sk-xxx\",\n" + + " \"Endpoint\": \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\n" + + "}", + configPath); + } + + string json = File.ReadAllText(configPath); + var settings = JsonSerializer.Deserialize(json, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); + + if (settings == null) + { + throw new InvalidOperationException("ai-settings.json 解析失败,请检查 JSON 格式。"); + } + + if (string.IsNullOrWhiteSpace(settings.ModelId)) + throw new InvalidOperationException("ai-settings.json 中 ModelId 不能为空。"); + if (string.IsNullOrWhiteSpace(settings.ApiKey)) + throw new InvalidOperationException("ai-settings.json 中 ApiKey 不能为空。"); + if (string.IsNullOrWhiteSpace(settings.Endpoint)) + throw new InvalidOperationException("ai-settings.json 中 Endpoint 不能为空。"); + + return settings; + } + } +} diff --git a/Drawer/AI/AgentIntegration/ActionHandlerAttribute.cs b/Drawer/AI/AgentIntegration/ActionHandlerAttribute.cs new file mode 100644 index 00000000..a8b8bed2 --- /dev/null +++ b/Drawer/AI/AgentIntegration/ActionHandlerAttribute.cs @@ -0,0 +1,16 @@ +using System; + +namespace AI.AgentIntegration +{ + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + public class ActionHandlerAttribute : Attribute + { + public AppActionType ActionType { get; } + + public ActionHandlerAttribute(AppActionType actionType) + { + ActionType = actionType; + } + } +} + diff --git a/Drawer/AI/AgentIntegration/AgentMode.cs b/Drawer/AI/AgentIntegration/AgentMode.cs new file mode 100644 index 00000000..f05fa905 --- /dev/null +++ b/Drawer/AI/AgentIntegration/AgentMode.cs @@ -0,0 +1,26 @@ +using System; + +namespace AI.AgentIntegration +{ + /// + /// 定义代理的操作模式 + /// + public enum AgentMode + { + /// + /// 观察模式:仅观察用户操作,不主动干预 + /// + Observe, + + /// + /// 协助模式:在用户请求时提供帮助 + /// + Assist, + + /// + /// 控制模式:主动控制系统行为 + /// + Control, + } +} + diff --git a/Drawer/AI/AgentIntegration/AppAction.cs b/Drawer/AI/AgentIntegration/AppAction.cs new file mode 100644 index 00000000..d8b6f092 --- /dev/null +++ b/Drawer/AI/AgentIntegration/AppAction.cs @@ -0,0 +1,102 @@ +using System.Collections.Generic; + +namespace AI.AgentIntegration +{ + /// + /// 表示一个应用程序操作 + /// + public class AppAction + { + /// + /// 获取或设置操作类型 + /// + public AppActionType Action { get; set; } + + /// + /// 获取或设置操作参数字典 + /// + public Dictionary Parameters { get; set; } = new Dictionary(); + + /// + /// 创建 AppAction,使用它可以让调用代码变得简短 + /// + /// 类型 + /// 参数 + /// AppAction 对象 + public static AppAction CreateAction(AppActionType type, Dictionary? parameters = null) + { + return new AppAction() + { + Action = type, + Parameters = parameters ?? new Dictionary(), + }; + } + + /// + /// 创建一个支持单个参数的 Action + /// + /// 类型 + /// 参数名 + /// 参数值 + /// AppAction 对象 + public static AppAction CreateAction(AppActionType type, string name, object value) + { + return new AppAction() + { + Action = type, + Parameters = new Dictionary() { [name] = value }, + }; + } + + /// + /// 创建加载散点文件的 action + /// + /// 文件路径 + /// AppAction 对象 + public static AppAction CreateLoadXyz(string path) + { + return CreateAction(AppActionType.GriddingModuleLoadXyz, nameof(path), path); + } + + /// + /// 创建从文件导入井点数据的 action + /// + /// 井点数据文件路径 + /// AppAction 对象 + public static AppAction CreateImportWellPoints(string path) + { + return CreateAction(AppActionType.WellModuleImportWellPoints, nameof(path), path); + } + + /// + /// 创建从文件导入井曲线数据的 action + /// + /// 井曲线数据文件路径 + /// AppAction 对象 + public static AppAction CreateImportWellCurves(string path) + { + return CreateAction(AppActionType.WellModuleImportCurves, nameof(path), path); + } + + /// + /// 创建打开文件的 action + /// + /// 文件路径 + /// AppAction 对象 + public static AppAction CreateOpenFile(string path) + { + return CreateAction(AppActionType.OpenFile, nameof(path), path); + } + + /// + /// 创建参数设置 + /// + /// 参数 + /// AppAction 对象 + public static AppAction CreateSetParameters(string parameters) + { + return CreateAction(AppActionType.GriddingModuleSetParameters, nameof(parameters), parameters); + } + } +} + diff --git a/Drawer/AI/AgentIntegration/AppActionResult.cs b/Drawer/AI/AgentIntegration/AppActionResult.cs new file mode 100644 index 00000000..117c400a --- /dev/null +++ b/Drawer/AI/AgentIntegration/AppActionResult.cs @@ -0,0 +1,43 @@ +namespace AI.AgentIntegration +{ + /// + /// 表示应用程序操作的结果 + /// + public class AppActionResult + { + /// + /// 获取或设置操作是否成功 + /// + public bool Success { get; set; } + + /// + /// 获取或设置操作结果消息 + /// + public string? Message { get; set; } + + /// + /// 获取或设置操作返回的数据 + /// + public object? Data { get; set; } + + public static AppActionResult Sucess(string message, object? data = null) + { + return new AppActionResult() + { + Success = true, + Message = message, + Data = data, + }; + } + + public static AppActionResult Fail(string message) + { + return new AppActionResult() + { + Success = false, + Message = message, + }; + } + } +} + diff --git a/Drawer/AI/AgentIntegration/AppActionType.cs b/Drawer/AI/AgentIntegration/AppActionType.cs new file mode 100644 index 00000000..b6c05e16 --- /dev/null +++ b/Drawer/AI/AgentIntegration/AppActionType.cs @@ -0,0 +1,164 @@ +namespace AI.AgentIntegration +{ + /// + /// 定义应用程序可执行的操作类型 + /// + public enum AppActionType + { + /// + /// 获取打开的标签页列表 + /// + GetOpenTabs, + + /// + /// 打开文件 + /// + OpenFile, + + /// + /// 关闭当前文件 + /// + CloseFile, + + /// + /// 关闭所有文件 + /// + CloseAllFiles, + + /// + /// 保存当前文件 + /// + SaveFile, + + /// + /// 保存所有文件 + /// + SaveAll, + + /// + /// 重命名文件 + /// + RenameFile, + + /// + /// 重新加载文件 + /// + ReloadFile, + + /// + /// 切换标签页 + /// + SwitchTab, + + /// + /// 导航到指定视图 + /// + Navigate, + + /// + /// 后退导航 + /// + NavigateBack, + + /// + /// 前进导航 + /// + NavigateForward, + + /// + /// 设置系统忙状态 + /// + SetBusy, + + /// + /// 刷新界面 + /// + Refresh, + + /// + /// 退出应用程序 + /// + Exit, + + /// + /// 撤销操作 + /// + Undo, + + /// + /// 重做操作 + /// + Redo, + + /// + /// 添加比例尺 + /// + AddScaleBar, + + /// + /// 添加边框 + /// + AddBorder, + + /// + /// 添加图例 + /// + AddLegend, + + /// + /// 描述当前状态 + /// + DescribeState, + + /// + /// 加载 xyz 文件 + /// + GriddingModuleLoadXyz, + + /// + /// 获取列信息 + /// + GriddingModuleGetColumns, + + /// + /// 列头匹配 + /// + GriddingModuleMatchColumns, + + /// + /// 获取网络化参数 + /// + GriddingModuleGetParameters, + + /// + /// 设置网络化参数 + /// + GriddingModuleSetParameters, + + /// + /// 导入数据 + /// + GriddingModuleImport, + + /// + /// 数据预览 + /// + GriddingModulePreviewData, + + /// + /// 成图 + /// + GriddingModuleRun, + + /// + /// 从文件导入井点数据 + /// + WellModuleImportWellPoints, + + /// + /// 从文件导入井曲线数据 + /// + WellModuleImportCurves, + } +} + diff --git a/Drawer/AI/AgentIntegration/AppControllerHolder.cs b/Drawer/AI/AgentIntegration/AppControllerHolder.cs new file mode 100644 index 00000000..19d2799c --- /dev/null +++ b/Drawer/AI/AgentIntegration/AppControllerHolder.cs @@ -0,0 +1,14 @@ +namespace AI.AgentIntegration +{ + /// + /// 供宿主(如 Drawer)在构建 DI 前注入真实 IAppController 的占位。 + /// 在 Avalonia 应用启动前设置 ,则 会注册该实例。 + /// + public static class AppControllerHolder + { + /// + /// 宿主设置的应用程序控制器,若未设置则使用 。 + /// + public static IAppController? Instance { get; set; } + } +} diff --git a/Drawer/AI/AgentIntegration/AppPrompt.cs b/Drawer/AI/AgentIntegration/AppPrompt.cs new file mode 100644 index 00000000..2b4563fa --- /dev/null +++ b/Drawer/AI/AgentIntegration/AppPrompt.cs @@ -0,0 +1,33 @@ +namespace AI.AgentIntegration +{ + public static class AppPrompt + { + /// + /// 成图助手的交互式引导提示词(用于新会话的 System Message) + /// + public static string InteractiveGuidePrompt => +@"你是一名智能的成图助手,负责引导用户完成以下两步成图流程。 + +【成图流程 - 严格按顺序执行】 + +第一步:散点文件加载 +调用 ShowForm(""gridding-load-xyz"") 弹出散点文件加载卡片。 +卡片会自动引导用户完成文件选择、数据预览和列头匹配,无需你介入。 +用户确认列头匹配后,系统会向你发送一条包含文件信息与匹配结果的摘要消息,收到后再进行第二步。 + +第二步:网格化参数设置与成图 +调用 ShowForm(""gridding-parameters"") 弹出网格化参数设置卡片。 +卡片会自动加载当前参数,用户可在卡片中查看和修改参数,确认后点击「生成」按钮,卡片内部自动完成成图。 +调用后只需告知用户参数卡片已弹出,请在卡片中确认参数并点击生成,无需你再做任何操作。 + +【禁止的行为】 +- 禁止在第一步完成之前进行第二步 +- 禁止向用户暴露函数名称 +- 禁止用纯文字询问文件路径等信息,需要用户输入时必须通过卡片交互 + +【对话要求】 +- 每次调用函数前,先用一句自然语言告知用户即将执行的操作 +- 语言自然、简洁、友好,使用日常语言而非技术术语 +- 每步完成后明确告知用户结果并引导下一步"; + } +} diff --git a/Drawer/AI/AgentIntegration/AppState.cs b/Drawer/AI/AgentIntegration/AppState.cs new file mode 100644 index 00000000..50cea87e --- /dev/null +++ b/Drawer/AI/AgentIntegration/AppState.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace AI.AgentIntegration +{ + /// + /// 表示应用程序的整体状态 + /// + public class AppState + { + /// + /// 获取或设置用户界面状态 + /// + public UIState UI { get; set; } = new UIState(); + + /// + /// 获取或设置文件状态 + /// + public FileState File { get; set; } = new FileState(); + + /// + /// 获取或设置导航状态 + /// + public NavigationState Navigation { get; set; } = new NavigationState(); + + /// + /// 获取或设置系统状态 + /// + public SystemState System { get; set; } = new SystemState(); + + /// + /// 获取或设置代理状态 + /// + public AgentState Agent { get; set; } = new AgentState(); + + /// + /// 将当前状态序列化为 JSON 字符串 + /// + /// 是否使用缩进格式 + /// 表示当前状态的 JSON 字符串 + public string ToJson(bool indented = true) + { + return JsonConvert.SerializeObject(this, indented ? Formatting.Indented : Formatting.None); + } + } + + /// + /// 表示用户界面状态 + /// + public class UIState + { + /// + /// 获取或设置活动标签页的标识符 + /// + public string ActiveTab { get; set; } = string.Empty; + + /// + /// 获取或设置打开的标签页列表 + /// + public List OpenTabs { get; set; } = new List(); + + /// + /// 获取或设置当前获得焦点的控件 + /// + public string FocusedControl { get; set; } = string.Empty; + } + + /// + /// 表示文件状态 + /// + public class FileState + { + /// + /// 获取或设置活动文件的路径 + /// + public string ActiveFilePath { get; set; } = string.Empty; + + /// + /// 获取或设置是否有未保存的更改 + /// + public bool HasUnsavedChanges { get; set; } + + /// + /// 获取或设置文件类型 + /// + public string FileType { get; set; } = string.Empty; + } + + /// + /// 表示导航状态 + /// + public class NavigationState + { + /// + /// 获取或设置当前视图名称 + /// + public string CurrentView { get; set; } = "Home"; + + /// + /// 获取或设置导航堆栈 + /// + public List NavigationStack { get; set; } = new List(); + } + + /// + /// 表示系统状态 + /// + public class SystemState + { + /// + /// 获取或设置系统是否处于忙碌状态 + /// + public bool IsBusy { get; set; } + + /// + /// 获取或设置是否有模态对话框打开 + /// + public bool ModalOpen { get; set; } + + /// + /// 获取或设置最后一次操作的时间(UTC) + /// + public DateTime LastActionTimeUtc { get; set; } = DateTime.UtcNow; + } + + /// + /// 表示代理状态 + /// + public class AgentState + { + /// + /// 获取或设置代理的操作模式 + /// + public AgentMode Mode { get; set; } = AgentMode.Observe; + + /// + /// 获取或设置最后执行的命令 + /// + public string LastCommand { get; set; } = string.Empty; + + /// + /// 获取或设置最后命令的执行结果 + /// + public string LastResult { get; set; } = string.Empty; + } +} + diff --git a/Drawer/AI/AgentIntegration/IAppController.cs b/Drawer/AI/AgentIntegration/IAppController.cs new file mode 100644 index 00000000..b564773d --- /dev/null +++ b/Drawer/AI/AgentIntegration/IAppController.cs @@ -0,0 +1,29 @@ +using System; +using System.Threading.Tasks; + +namespace AI.AgentIntegration +{ + /// + /// 定义应用程序控制器的接口 + /// + public interface IAppController + { + /// + /// 当应用程序状态发生变化时触发的事件 + /// + event EventHandler StateChanged; + + /// + /// 获取应用程序的当前状态 + /// + /// 当前应用程序状态 + AppState GetCurrentState(); + + /// + /// 执行指定的应用程序操作 + /// + /// 要执行的操作 + /// 操作执行结果 + Task ExecuteAsync(AppAction action); + } +} \ No newline at end of file diff --git a/Drawer/AI/AgentIntegration/NoOpAppController.cs b/Drawer/AI/AgentIntegration/NoOpAppController.cs new file mode 100644 index 00000000..e8e31c41 --- /dev/null +++ b/Drawer/AI/AgentIntegration/NoOpAppController.cs @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; + +namespace AI.AgentIntegration +{ + /// + /// 无操作 AppController,在未注入真实控制器时使用(如独立运行 AI 模块时)。 + /// + public sealed class NoOpAppController : IAppController + { + public event EventHandler? StateChanged; + + public AppState GetCurrentState() => new AppState(); + + public Task ExecuteAsync(AppAction action) + { + return Task.FromResult(AppActionResult.Fail("未连接应用控制器")); + } + } +} diff --git a/Drawer/AI/App.axaml b/Drawer/AI/App.axaml new file mode 100644 index 00000000..aa6fc580 --- /dev/null +++ b/Drawer/AI/App.axaml @@ -0,0 +1,1012 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +