From 718707fd19ab7c27e38c8807055c80809d25e6dc Mon Sep 17 00:00:00 2001 From: kong <135376906+3316891527@users.noreply.github.com> Date: Thu, 29 Oct 2026 11:27:20 +0000 Subject: [PATCH 1/7] =?UTF-8?q?refactor(tools):=20=E6=94=B6=E5=8F=A3?= =?UTF-8?q?=E4=B8=89=E6=A1=A3=E6=9D=83=E9=99=90=E5=AE=9E=E7=8E=B0=E4=B8=8E?= =?UTF-8?q?=20Shizuku=20=E5=90=8E=E7=AB=AF=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/tools/defaultTool/ToolGetter.kt | 14 +- .../AccessibilityDeviceInfoToolExecutor.kt | 9 - .../AccessibilityFileSystemTools.kt | 9 - .../AccessibilitySystemOperationTools.kt | 10 - .../accessbility/AccessibilityUITools.kt | 790 ----- .../admin/AdminDeviceInfoToolExecutor.kt | 9 - .../defaultTool/admin/AdminFileSystemTools.kt | 2962 ++++++++++++++++- .../admin/AdminSystemOperationTools.kt | 525 ++- .../tools/defaultTool/admin/AdminUITools.kt | 2122 +++++++++++- .../DebuggerDeviceInfoToolExecutor.kt | 10 - .../debugger/DebuggerFileSystemTools.kt | 2930 ---------------- .../debugger/DebuggerSystemOperationTools.kt | 527 --- .../defaultTool/debugger/DebuggerUITools.kt | 1359 -------- .../root/RootDeviceInfoToolExecutor.kt | 9 - .../defaultTool/root/RootFileSystemTools.kt | 9 - .../root/RootSystemOperationTools.kt | 9 - .../tools/defaultTool/root/RootUITools.kt | 5 +- .../defaultTool/standard/StandardUITools.kt | 2 +- .../tools/system/AndroidPermissionLevel.kt | 1 - .../system/action/ActionListenerFactory.kt | 2 +- ...onListener.kt => ShizukuActionListener.kt} | 6 +- .../system/shell/ShellExecutorFactory.kt | 2 +- ...ellExecutor.kt => ShizukuShellExecutor.kt} | 26 +- app/src/main/res/values-en/strings.xml | 4 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-id/strings.xml | 2 +- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-ko/strings.xml | 2 +- app/src/main/res/values-ms/strings.xml | 2 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-ro/strings.xml | 4 +- app/src/main/res/values/strings.xml | 4 +- .../permissions/PermissionCapabilitiesTest.kt | 10 +- .../01-permissions.md | 25 + .../chore/tools-permissions-layout/index.md | 29 + 35 files changed, 5676 insertions(+), 5759 deletions(-) delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityDeviceInfoToolExecutor.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityFileSystemTools.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilitySystemOperationTools.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityUITools.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminDeviceInfoToolExecutor.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerDeviceInfoToolExecutor.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerFileSystemTools.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerSystemOperationTools.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerUITools.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootDeviceInfoToolExecutor.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootFileSystemTools.kt delete mode 100644 app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootSystemOperationTools.kt rename app/src/main/java/com/ai/assistance/operit/core/tools/system/action/{DebuggerActionListener.kt => ShizukuActionListener.kt} (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/{DebuggerShellExecutor.kt => ShizukuShellExecutor.kt} (96%) create mode 100644 docs/TODO/chore/tools-permissions-layout/01-permissions.md create mode 100644 docs/TODO/chore/tools-permissions-layout/index.md diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/ToolGetter.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/ToolGetter.kt index d02c589a91..91ea22b74b 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/ToolGetter.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/ToolGetter.kt @@ -17,8 +17,7 @@ object ToolGetter { */ fun getFileSystemTools(context: Context): StandardFileSystemTools { return when (androidPermissionPreferences.getPreferredPermissionLevel()) { - AndroidPermissionLevel.ROOT -> RootFileSystemTools(context) - AndroidPermissionLevel.ADMIN -> AdminFileSystemTools(context) + AndroidPermissionLevel.ADMIN, AndroidPermissionLevel.ROOT -> AdminFileSystemTools(context) AndroidPermissionLevel.STANDARD -> StandardFileSystemTools(context) null -> StandardFileSystemTools(context) // 默认使用标准权限级别 } @@ -54,8 +53,7 @@ object ToolGetter { */ fun getSystemOperationTools(context: Context): StandardSystemOperationTools { return when (androidPermissionPreferences.getPreferredPermissionLevel()) { - AndroidPermissionLevel.ROOT -> RootSystemOperationTools(context) - AndroidPermissionLevel.ADMIN -> AdminSystemOperationTools(context) + AndroidPermissionLevel.ADMIN, AndroidPermissionLevel.ROOT -> AdminSystemOperationTools(context) AndroidPermissionLevel.STANDARD -> StandardSystemOperationTools(context) null -> StandardSystemOperationTools(context) // 默认使用标准权限级别 } @@ -67,12 +65,8 @@ object ToolGetter { * @return 根据首选权限级别的设备信息工具执行器实现 */ fun getDeviceInfoToolExecutor(context: Context): StandardDeviceInfoToolExecutor { - return when (androidPermissionPreferences.getPreferredPermissionLevel()) { - AndroidPermissionLevel.ROOT -> RootDeviceInfoToolExecutor(context) - AndroidPermissionLevel.ADMIN -> AdminDeviceInfoToolExecutor(context) - AndroidPermissionLevel.STANDARD -> StandardDeviceInfoToolExecutor(context) - null -> StandardDeviceInfoToolExecutor(context) // 默认使用标准权限级别 - } + // 原有各权限版本均没有设备信息特有行为,共享实现按实际能力执行操作。 + return StandardDeviceInfoToolExecutor(context) } /** diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityDeviceInfoToolExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityDeviceInfoToolExecutor.kt deleted file mode 100644 index 79ff4fbfbc..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityDeviceInfoToolExecutor.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.accessbility - -import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardDeviceInfoToolExecutor - -/** 无障碍级别的设备信息工具,继承标准版本 */ -open class AccessibilityDeviceInfoToolExecutor(context: Context) : StandardDeviceInfoToolExecutor(context) { - // 当前阶段不添加新功能,仅继承标准实现 -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityFileSystemTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityFileSystemTools.kt deleted file mode 100644 index e578f318ef..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityFileSystemTools.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.accessbility - -import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardFileSystemTools - -/** 无障碍级别的文件系统工具,继承标准版本 */ -open class AccessibilityFileSystemTools(context: Context) : StandardFileSystemTools(context) { - // 当前阶段不添加新功能,仅继承标准实现 -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilitySystemOperationTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilitySystemOperationTools.kt deleted file mode 100644 index 872085cc32..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilitySystemOperationTools.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.accessbility - -import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardSystemOperationTools - -/** 无障碍级别的系统操作工具,继承标准版本 */ -open class AccessibilitySystemOperationTools(context: Context) : - StandardSystemOperationTools(context) { - // 当前阶段不添加新功能,仅继承标准实现 -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityUITools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityUITools.kt deleted file mode 100644 index b21d94d4dd..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityUITools.kt +++ /dev/null @@ -1,790 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.accessbility - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.SimplifiedUINode -import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.UIActionResultData -import com.ai.assistance.operit.core.tools.UIPageResultData -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardUITools -import com.ai.assistance.operit.data.model.AITool -import com.ai.assistance.operit.data.model.ToolResult -import com.ai.assistance.operit.data.repository.UIHierarchyManager -import com.ai.assistance.operit.util.files.OperitPaths -import java.io.File -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import com.ai.assistance.operit.util.media.ImagePoolManager -import java.io.StringReader -import org.json.JSONObject -import org.xmlpull.v1.XmlPullParser -import org.xmlpull.v1.XmlPullParserFactory -import kotlinx.coroutines.delay - -/** 无障碍级别的UI工具,使用Android无障碍服务API实现UI操作 */ -open class AccessibilityUITools(context: Context) : StandardUITools(context) { - - companion object { - private const val TAG = "AccessibilityUITools" - private const val MAX_RETRY_COUNT = 3 - private const val RETRY_DELAY_MS = 300L - } - - /** - * 检查无障碍服务是否正在运行 - */ - private suspend fun isAccessibilityServiceEnabled(): Boolean { - return UIHierarchyManager.isAccessibilityServiceEnabled(context) - } - - /** - * 为需要无障碍服务的工具创建一个前置检查的包装器 - */ - private suspend fun withAccessibilityCheck(tool: AITool, block: suspend () -> T): T { - if (!isAccessibilityServiceEnabled()) { - throw IllegalStateException("Accessibility Service is not enabled. Please enable it in system settings to use this feature.") - } - return block() - } - - /** - * 获取UI层次结构,失败时重试 - * @return UI层次结构XML字符串,获取失败返回空字符串 - */ - private suspend fun getUIHierarchyWithRetry(): String { - var retryCount = 0 - var uiXml = "" - - while (retryCount < MAX_RETRY_COUNT) { - uiXml = UIHierarchyManager.getUIHierarchy(context) - if (uiXml.isNotEmpty()) { - return uiXml - } - - retryCount++ - if (retryCount < MAX_RETRY_COUNT) { - AppLogger.d(TAG, "获取UI层次结构失败,正在重试 #$retryCount") - delay(RETRY_DELAY_MS) - } - } - - AppLogger.w(TAG, "获取UI层次结构失败,已重试${MAX_RETRY_COUNT}次") - return uiXml - } - - /** Gets the current UI page/window information */ - override suspend fun getPageInfo(tool: AITool): ToolResult { - return try { - withAccessibilityCheck(tool) { - val format = tool.parameters.find { it.name == "format" }?.value ?: "xml" - val detail = tool.parameters.find { it.name == "detail" }?.value ?: "summary" - - if (format !in listOf("xml", "json")) { - return@withAccessibilityCheck ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Invalid format specified. Must be 'xml' or 'json'." - ) - } - - // 使用无障碍服务获取UI数据(带重试) - val uiXml = getUIHierarchyWithRetry() - if (uiXml.isEmpty()) { - return@withAccessibilityCheck ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to retrieve UI data via accessibility service." - ) - } - - // 解析当前窗口信息 - val focusInfo = extractFocusInfoFromAccessibility() - - // 简化布局信息 - val simplifiedLayout = simplifyLayout(uiXml) - - // 创建结构化数据 - val resultData = - UIPageResultData( - packageName = focusInfo.packageName ?: "Unknown", - activityName = focusInfo.activityName ?: "Unknown", - uiElements = simplifiedLayout - ) - - ToolResult(toolName = tool.name, success = true, result = resultData, error = "") - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error getting page info", e) - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error getting page info: ${e.message}" - ) - } - } - - /** 从无障碍服务获取焦点信息 */ - private suspend fun extractFocusInfoFromAccessibility(): FocusInfo { - val focusInfo = FocusInfo() - try { - // 1. 获取UI层次结构的XML快照(带重试) - val hierarchyXml = getUIHierarchyWithRetry() - if (hierarchyXml.isEmpty()) { - AppLogger.w(TAG, "无法获取UI层次结构XML,使用默认值。") - focusInfo.packageName = "android" - // 即使XML获取失败,仍然尝试获取Activity名称 - focusInfo.activityName = UIHierarchyManager.getCurrentActivityName(context) ?: "ForegroundActivity" - return focusInfo - } - - // 2. 从XML中解析包名 - val (packageName, _) = UIHierarchyManager.extractWindowInfo(hierarchyXml) - // 3. 从服务中直接获取当前Activity名称 - val activityName = UIHierarchyManager.getCurrentActivityName(context) - - focusInfo.packageName = packageName - focusInfo.activityName = activityName // 使用从服务获取的Activity名称 - - // 如果没有获取到,使用默认值 - if (focusInfo.packageName == null) focusInfo.packageName = "android" - if (focusInfo.activityName == null) focusInfo.activityName = "ForegroundActivity" - } catch (e: Exception) { - AppLogger.e(TAG, "从XML解析焦点信息时出错", e) - // 设置默认值 - focusInfo.packageName = "android" - focusInfo.activityName = "ForegroundActivity" - } - return focusInfo - } - - /** 简化XML布局为节点树 */ - fun simplifyLayout(xml: String): SimplifiedUINode { - val factory = XmlPullParserFactory.newInstance().apply { isNamespaceAware = false } - val parser = factory.newPullParser().apply { setInput(StringReader(xml)) } - - val nodeStack = mutableListOf() - var rootNode: UINode? = null - - while (parser.eventType != XmlPullParser.END_DOCUMENT) { - when (parser.eventType) { - XmlPullParser.START_TAG -> { - if (parser.name == "node") { - val newNode = createNode(parser) - if (rootNode == null) { - rootNode = newNode - nodeStack.add(newNode) - } else { - nodeStack.lastOrNull()?.children?.add(newNode) - nodeStack.add(newNode) - } - } - } - XmlPullParser.END_TAG -> { - if (parser.name == "node") { - nodeStack.removeLastOrNull() - } - } - } - parser.next() - } - - return rootNode?.toUINode() - ?: SimplifiedUINode( - className = null, - text = null, - contentDesc = null, - resourceId = null, - bounds = null, - isClickable = false, - children = emptyList() - ) - } - - private fun createNode(parser: XmlPullParser): UINode { - // 解析关键属性 - val className = parser.getAttributeValue(null, "class")?.substringAfterLast('.') - val text = parser.getAttributeValue(null, "text")?.replace(" ", "\n") - val contentDesc = parser.getAttributeValue(null, "content-desc") - val resourceId = parser.getAttributeValue(null, "resource-id") - val bounds = parser.getAttributeValue(null, "bounds") - val isClickable = parser.getAttributeValue(null, "clickable") == "true" - - return UINode( - className = className, - text = text, - contentDesc = contentDesc, - resourceId = resourceId, - bounds = bounds, - isClickable = isClickable - ) - } - - /** 点击元素 */ - override suspend fun clickElement(tool: AITool): ToolResult { - return try { - withAccessibilityCheck(tool) { - val resourceId = tool.parameters.find { it.name == "resourceId" }?.value - val className = tool.parameters.find { it.name == "className" }?.value - val contentDesc = tool.parameters.find { it.name == "contentDesc" }?.value - val index = tool.parameters.find { it.name == "index" }?.value?.toIntOrNull() ?: 0 - val bounds = tool.parameters.find { it.name == "bounds" }?.value - - if (resourceId == null && className == null && bounds == null && contentDesc == null) { - return@withAccessibilityCheck ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Missing element identifier. Provide at least one of 'resourceId', 'className', 'contentDesc', or 'bounds'." - ) - } - - // 如果提供了边界坐标,直接解析并点击中心点 - if (bounds != null) { - return@withAccessibilityCheck handleClickByBounds(tool, bounds) - } - - // 获取UI层次结构XML(带重试) - val uiXml = getUIHierarchyWithRetry() - if (uiXml.isEmpty()) { - return@withAccessibilityCheck ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "Unable to get UI hierarchy.") - } - - // 在XML中查找匹配的节点 - val matchedNodes = findNodesInXml(uiXml) { parser -> - val hasSelectors = resourceId != null || className != null || contentDesc != null - if (!hasSelectors) { - return@findNodesInXml false - } - - val actualId = parser.getAttributeValue(null, "resource-id") - val actualClass = parser.getAttributeValue(null, "class") - val actualDesc = parser.getAttributeValue(null, "content-desc") - - if(resourceId != null && (actualId == null || !actualId.endsWith(resourceId))){ - return@findNodesInXml false - } - - if(className != null && (actualClass == null || actualClass != className)){ - return@findNodesInXml false - } - - if(contentDesc != null && (actualDesc == null || !actualDesc.equals(contentDesc, ignoreCase = true))){ - return@findNodesInXml false - } - - true - } - - if (matchedNodes.isEmpty()) { - return@withAccessibilityCheck ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "No matching element found.") - } - - // 检查索引是否有效 - if (index < 0 || index >= matchedNodes.size) { - return@withAccessibilityCheck ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Index out of range. Found ${matchedNodes.size} elements, but requested index $index." - ) - } - - // 获取目标节点的bounds - val targetNodeBounds = matchedNodes[index].bounds - if (targetNodeBounds == null) { - return@withAccessibilityCheck ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "Target element has no bounds.") - } - - // 解析bounds并点击 - handleClickByBounds(tool, targetNodeBounds) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error clicking element", e) - operationOverlay.hide() - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error clicking element: ${e.message}" - ) - } - } - - private suspend fun handleClickByBounds(tool: AITool, bounds: String): ToolResult { - try { - val rect = parseBounds(bounds) - if (rect.isEmpty) { - return ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "Invalid bounds format: $bounds") - } - - val centerX = rect.centerX() - val centerY = rect.centerY() - - withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } - val clickSuccess = performAccessibilityClick(centerX, centerY) - - return if (clickSuccess) { - withContext(Dispatchers.Main) { - operationOverlay.showTap(centerX, centerY) - operationOverlay.hide() - } - ToolResult( - toolName = tool.name, - success = true, - result = UIActionResultData( - actionType = "click", - actionDescription = "Successfully clicked at bounds $bounds", - coordinates = Pair(centerX, centerY) - ) - ) - } else { - operationOverlay.hide() - ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "Failed to click at bounds $bounds via accessibility service.") - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error clicking by bounds", e) - operationOverlay.hide() - return ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "Error clicking at bounds: ${e.message}") - } - } - - private fun findNodesInXml(xml: String, predicate: (parser: XmlPullParser) -> Boolean): List { - val matchedNodes = mutableListOf() - val factory = XmlPullParserFactory.newInstance().apply { isNamespaceAware = false } - val parser = factory.newPullParser().apply { setInput(StringReader(xml)) } - - while (parser.eventType != XmlPullParser.END_DOCUMENT) { - if (parser.eventType == XmlPullParser.START_TAG && parser.name == "node") { - if (predicate(parser)) { - matchedNodes.add( - NodeInfo( - bounds = parser.getAttributeValue(null, "bounds"), - text = parser.getAttributeValue(null, "text") - ) - ) - } - } - parser.next() - } - return matchedNodes - } - - private data class NodeInfo(val bounds: String?, val text: String?) - - /** 设置输入文本 */ - override suspend fun setInputText(tool: AITool): ToolResult { - return try { - withAccessibilityCheck(tool) { - val text = tool.parameters.find { it.name == "text" }?.value ?: "" - - // 通过UIHierarchyManager请求远程服务找到焦点节点的ID - val focusedNodeId = UIHierarchyManager.findFocusedNodeId(context) - if (focusedNodeId.isNullOrEmpty()) { - return@withAccessibilityCheck ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "No focused editable field found." - ) - } - - // 显示反馈 - val rect = parseBounds(focusedNodeId) - if (!rect.isEmpty) { - operationOverlay.showTextInput(rect.centerX(), rect.centerY(), text) - } - - // 通过UIHierarchyManager请求远程服务设置文本 - val result = UIHierarchyManager.setTextOnNode(context, focusedNodeId, text) - - if (result) { - // 成功后主动隐藏overlay - operationOverlay.hide() - ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "textInput", - actionDescription = - "Successfully set input text via accessibility service" - ), - error = "" - ) - } else { - operationOverlay.hide() - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to set text via accessibility service." - ) - } - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error setting input text", e) - operationOverlay.hide() - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error setting input text: ${e.message}" - ) - } - } - - /** 执行轻触操作 */ - override suspend fun tap(tool: AITool): ToolResult { - return try { - withAccessibilityCheck(tool) { - val x = tool.parameters.find { it.name == "x" }?.value?.toIntOrNull() - val y = tool.parameters.find { it.name == "y" }?.value?.toIntOrNull() - - if (x == null || y == null) { - return@withAccessibilityCheck ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Missing or invalid coordinates. Both 'x' and 'y' must be valid integers." - ) - } - - withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } - - // 使用无障碍服务执行点击 - val result = performAccessibilityClick(x, y) - - if (result) { - withContext(Dispatchers.Main) { - operationOverlay.showTap(x, y) - operationOverlay.hide() - } - ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "tap", - actionDescription = - "Successfully tapped at coordinates ($x, $y) via accessibility service", - coordinates = Pair(x, y) - ), - error = "" - ) - } else { - operationOverlay.hide() - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to tap at coordinates via accessibility service." - ) - } - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error tapping at coordinates", e) - operationOverlay.hide() - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error tapping at coordinates: ${e.message}" - ) - } - } - - /** 执行长按操作 */ - override suspend fun longPress(tool: AITool): ToolResult { - return try { - withAccessibilityCheck(tool) { - val x = tool.parameters.find { it.name == "x" }?.value?.toIntOrNull() - val y = tool.parameters.find { it.name == "y" }?.value?.toIntOrNull() - - if (x == null || y == null) { - return@withAccessibilityCheck ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Missing or invalid coordinates. Both 'x' and 'y' must be valid integers." - ) - } - - withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } - - // 使用无障碍服务执行长按 - val result = performAccessibilityLongPress(x, y) - - if (result) { - withContext(Dispatchers.Main) { - operationOverlay.showTap(x, y) - operationOverlay.hide() - } - ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "long_press", - actionDescription = - "Successfully long pressed at coordinates ($x, $y) via accessibility service", - coordinates = Pair(x, y) - ), - error = "" - ) - } else { - operationOverlay.hide() - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to long press at coordinates via accessibility service." - ) - } - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error long pressing at coordinates", e) - operationOverlay.hide() - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error long pressing at coordinates: ${e.message}" - ) - } - } - - /** 执行滑动操作 */ - override suspend fun swipe(tool: AITool): ToolResult { - return try { - withAccessibilityCheck(tool) { - val startX = tool.parameters.find { it.name == "start_x" }?.value?.toIntOrNull() - val startY = tool.parameters.find { it.name == "start_y" }?.value?.toIntOrNull() - val endX = tool.parameters.find { it.name == "end_x" }?.value?.toIntOrNull() - val endY = tool.parameters.find { it.name == "end_y" }?.value?.toIntOrNull() - val duration = tool.parameters.find { it.name == "duration" }?.value?.toIntOrNull() ?: 300 - - if (startX == null || startY == null || endX == null || endY == null) { - return@withAccessibilityCheck ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Missing or invalid coordinates. 'start_x', 'start_y', 'end_x', and 'end_y' must be valid integers." - ) - } - - withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } - - // 使用无障碍服务执行滑动 - val result = performAccessibilitySwipe(startX, startY, endX, endY, duration) - - if (result) { - withContext(Dispatchers.Main) { - operationOverlay.showSwipe(startX, startY, endX, endY) - operationOverlay.hide() - } - ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "swipe", - actionDescription = - "Successfully performed swipe from ($startX, $startY) to ($endX, $endY) via accessibility service" - ), - error = "" - ) - } else { - operationOverlay.hide() - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to perform swipe via accessibility service." - ) - } - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error performing swipe", e) - operationOverlay.hide() - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error performing swipe: ${e.message}" - ) - } - } - - // 使用无障碍服务执行点击的辅助方法 - private suspend fun performAccessibilityClick(x: Int, y: Int): Boolean { - return try { - UIHierarchyManager.performClick(context, x, y) - } catch (e: Exception) { - AppLogger.e(TAG, "Error performing accessibility click", e) - return false - } - } - - // 使用无障碍服务执行长按的辅助方法 - private suspend fun performAccessibilityLongPress(x: Int, y: Int): Boolean { - return try { - UIHierarchyManager.performLongPress(context, x, y) - } catch (e: Exception) { - AppLogger.e(TAG, "Error performing accessibility long press", e) - return false - } - } - - // 使用无障碍服务执行滑动的辅助方法 - private suspend fun performAccessibilitySwipe( - startX: Int, - startY: Int, - endX: Int, - endY: Int, - duration: Int - ): Boolean { - return try { - UIHierarchyManager.performSwipe(context, startX, startY, endX, endY, duration.toLong()) - } catch (e: Exception) { - AppLogger.e(TAG, "Error performing accessibility swipe", e) - return false - } - } - - protected fun accessibilityKeyAction(keyCode: String): Int? = when (keyCode) { - "KEYCODE_BACK" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_BACK - "KEYCODE_HOME" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_HOME - "KEYCODE_RECENTS" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_RECENTS - "KEYCODE_NOTIFICATIONS" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS - "KEYCODE_QUICK_SETTINGS" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS - "KEYCODE_POWER_DIALOG" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_POWER_DIALOG - else -> null - } - - /** 模拟按键操作 */ - override suspend fun pressKey(tool: AITool): ToolResult { - val keyCode = tool.parameters.find { it.name == "key_code" }?.value - - if (keyCode == null) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Missing 'key_code' parameter." - ) - } - - try { - // 将字符串keyCode转换为AccessibilityService中的常量 - val keyAction = accessibilityKeyAction(keyCode) - - if (keyAction != null) { - // 通过UIHierarchyManager请求远程服务执行操作 - val success = UIHierarchyManager.performGlobalAction(context, keyAction) - return if (success) { - ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "keyPress", - actionDescription = - "Successfully pressed key: $keyCode via accessibility service" - ), - error = "" - ) - } else { - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = - "Failed to press key: $keyCode via accessibility service. Not all keys are supported." - ) - } - } else { - // 如果不是标准全局操作,返回不支持的错误 - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = - "Key: $keyCode is not supported via accessibility service. Only system keys like BACK, HOME, etc. are supported." - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error pressing key", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error pressing key: ${e.message ?: "Unknown exception"}" - ) - } - } - - override suspend fun captureScreenshotToFile(tool: AITool): Pair?> { - return try { - val screenshotDir = OperitPaths.cleanOnExitDir() - - val shortName = System.currentTimeMillis().toString().takeLast(4) - val file = File(screenshotDir, "$shortName.png") - - val success = UIHierarchyManager.takeScreenshot(context, file.absolutePath, "png") - if (!success) { - AppLogger.w(TAG, "captureScreenshotForAgent: AIDL takeScreenshot failed") - return Pair(null, null) - } - - val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } - BitmapFactory.decodeFile(file.absolutePath, options) - val dimensions = if (options.outWidth > 0 && options.outHeight > 0) { - Pair(options.outWidth, options.outHeight) - } else { - null - } - - Pair(file.absolutePath, dimensions) - } catch (e: Exception) { - AppLogger.e(TAG, "captureScreenshot via accessibility failed", e) - Pair(null, null) - } - } - - override suspend fun captureScreenshot(tool: AITool): Pair?> { - return captureScreenshotToFile(tool) - } - - override suspend fun captureScreenshotBitmap(tool: AITool): Pair?> { - val (filePath, dimensions) = captureScreenshot(tool) - if (filePath == null) { - return Pair(null, dimensions) - } - - val bitmap = BitmapFactory.decodeFile(filePath) ?: return Pair(null, dimensions) - val resolvedDimensions = dimensions ?: Pair(bitmap.width, bitmap.height) - return Pair(bitmap, resolvedDimensions) - } - - private fun parseBounds(boundsString: String): android.graphics.Rect { - // 解析 "[left,top][right,bottom]" 格式的边界字符串 - val rect = android.graphics.Rect() - try { - val parts = boundsString.replace("[", "").replace("]", ",").split(",") - if (parts.size >= 4) { - rect.left = parts[0].toInt() - rect.top = parts[1].toInt() - rect.right = parts[2].toInt() - rect.bottom = parts[3].toInt() - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error parsing bounds: $boundsString", e) - } - return rect - } -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminDeviceInfoToolExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminDeviceInfoToolExecutor.kt deleted file mode 100644 index 8d23ab6a9d..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminDeviceInfoToolExecutor.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.admin - -import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.debugger.DebuggerDeviceInfoToolExecutor - -/** 管理员级别的设备信息工具,继承调试版本 */ -open class AdminDeviceInfoToolExecutor(context: Context) : DebuggerDeviceInfoToolExecutor(context) { - // 当前阶段不添加新功能,仅继承调试实现 -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminFileSystemTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminFileSystemTools.kt index 7dd851e1bd..2d043eb36a 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminFileSystemTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminFileSystemTools.kt @@ -1,15 +1,2937 @@ package com.ai.assistance.operit.core.tools.defaultTool.admin +import android.content.ActivityNotFoundException +import android.content.ClipData import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.debugger.DebuggerFileSystemTools +import android.content.Intent +import android.webkit.MimeTypeMap +import androidx.core.content.FileProvider +import com.ai.assistance.operit.BuildConfig +import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.DirectoryListingData +import com.ai.assistance.operit.core.tools.FileContentData +import com.ai.assistance.operit.core.tools.FileExistsData +import com.ai.assistance.operit.core.tools.FileInfoData +import com.ai.assistance.operit.core.tools.FileOperationData +import com.ai.assistance.operit.core.tools.FilePartContentData +import com.ai.assistance.operit.core.tools.FindFilesResultData +import com.ai.assistance.operit.core.tools.StringResultData +import com.ai.assistance.operit.core.tools.ToolExecutionLimits +import com.ai.assistance.operit.core.tools.ToolProgressBus +import com.ai.assistance.operit.core.tools.defaultTool.PathValidator import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardFileSystemTools import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver import com.ai.assistance.operit.core.tools.permissions.PermissionOperationRouter +import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor import com.ai.assistance.operit.data.model.AITool +import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.data.model.ToolResult +import com.ai.assistance.operit.util.files.AndroidUserPathUtils +import com.ai.assistance.operit.util.files.FileUtils +import com.ai.assistance.operit.util.logging.AppLogger +import java.io.BufferedInputStream +import java.io.BufferedOutputStream +import java.io.File +import java.io.FileInputStream +import java.io.FileOutputStream +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale +import java.util.concurrent.atomic.AtomicInteger +import java.util.zip.ZipEntry +import java.util.zip.ZipFile +import java.util.zip.ZipInputStream +import java.util.zip.ZipOutputStream +import kotlin.math.exp +import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch + +/** 管理员文件工具按实际授权选择标准或 Shell 操作,Root 复用同一能力路由。 */ +open class AdminFileSystemTools(context: Context) : StandardFileSystemTools(context) { + companion object { + private const val TAG = "AdminFileSystemTools" + internal fun isOperitInternalPath(path: String): Boolean { + val normalizedPath = path.trim() + val appPackage = BuildConfig.APPLICATION_ID + return normalizedPath.startsWith("/data/data/$appPackage") || + AndroidUserPathUtils.isCurrentUserPackageDataPath(normalizedPath, appPackage) + } + } + + /** + * 判断路径是否为Operit应用的内部存储路径 + * 仅针对 Operit 应用自身数据目录路径返回true + */ + protected fun isOperitInternalPath(path: String): Boolean { + return Companion.isOperitInternalPath(path) + } + + private fun shQuote(value: String): String { + return "'" + value.replace("'", "'\"'\"'") + "'" + } + + private fun smoothProgress(count: Int, scale: Float): Float { + if (count <= 0) return 0f + return (1f - exp(-count / scale)).coerceIn(0f, 0.99f) + } + + private fun updateProgressFloor(progressFloor: AtomicInteger, candidate: Int) { + while (true) { + val old = progressFloor.get() + if (candidate <= old) return + if (progressFloor.compareAndSet(old, candidate)) return + } + } + + /** List files in a directory */ + private suspend fun listFilesWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.listFiles(tool) + } + if (isSafEnvironment(environment)) { + return super.listFiles(tool) + } + + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + + // 应用内部路径由标准文件实现处理,保留应用自身访问能力。 + if (isOperitInternalPath(path)) { + return super.listFiles(tool) + } + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Path parameter is required" + ) + } + + return try { + // 确保目录路径末尾有斜杠 + val normalizedPath = if (path.endsWith("/")) path else "$path/" + + // 使用ls -la命令获取详细的文件列表 + AppLogger.d(TAG, "Using ls -la command for path: $normalizedPath") + val listResult = AndroidShellExecutor.executeShellCommand("ls -la '$normalizedPath'") + + if (listResult.success) { + AppLogger.d(TAG, "ls -la command output: ${listResult.stdout}") + + // 解析ls -la命令输出 + val entries = parseDetailedDirectoryListing(listResult.stdout, normalizedPath) + + AppLogger.d(TAG, "Parsed ${entries.size} entries from ls -la output") + + return ToolResult( + toolName = tool.name, + success = true, + result = DirectoryListingData(path, entries), + error = "" + ) + } else { + AppLogger.w(TAG, "ls -la command failed: ${listResult.stderr}") + + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to list directory: ${listResult.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error listing directory", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error listing directory: ${e.message}" + ) + } + } + + /** Parse the output of the ls -la command into structured data */ + protected fun parseDetailedDirectoryListing( + output: String, + path: String + ): List { + val lines = output.trim().split("\n") + val entries = mutableListOf() + + AppLogger.d(TAG, "Parsing ${lines.size} lines from ls -la output") + + // 跳过第一行总计行 + val startIndex = if (lines.isNotEmpty() && lines[0].startsWith("total")) 1 else 0 + + // 日期格式化器,用于解析日期时间字符串 + val dateFormat = java.text.SimpleDateFormat("yyyy-MM-dd HH:mm", java.util.Locale.US) + + for (i in startIndex until lines.size) { + try { + val line = lines[i] + if (line.isBlank()) continue + + // 打印每一行以便调试 + AppLogger.d(TAG, "Parsing line: $line") + + // Android上ls -la输出格式: crwxrw--- 2 u0_a425 media_rw 4056 2025-03-14 + // 06:04 Android + // 符号链接格式: lrwxrwxrwx 1 root root 12 2025-03-14 06:04 filename -> + // /path/to/target + + // 使用正则表达式解析Android上的ls -la输出 + val androidRegex = + """^(\S+)\s+(\d+)\s+(\S+\s*\S*)\s+(\S+)\s+(\d+)\s+(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2})\s+(.+)$""".toRegex() + val androidMatch = androidRegex.find(line) + + if (androidMatch != null) { + // 特定于Android的格式解析 + val permissions = androidMatch.groupValues[1] + val size = androidMatch.groupValues[5].toLongOrNull() ?: 0 + val date = androidMatch.groupValues[6] + val time = androidMatch.groupValues[7] + var name = androidMatch.groupValues[8] + val isDirectory = permissions.startsWith("d") || permissions.startsWith("c") + val isSymlink = permissions.startsWith("l") + + // 处理符号链接格式 "name -> target" + if (isSymlink && name.contains(" -> ")) { + name = name.substringBefore(" -> ") + AppLogger.d(TAG, "Found symlink: $name") + } + + // 跳过 . 和 .. 条目 + if (name == "." || name == "..") continue + + // 将日期和时间转换为时间戳 + val dateTimeStr = "$date $time" + val timestamp = + try { + val parsedDate = dateFormat.parse(dateTimeStr) + parsedDate?.time?.toString() ?: "0" + } catch (e: Exception) { + AppLogger.e(TAG, "Error parsing date: $dateTimeStr", e) + "0" // 解析失败时使用默认时间戳 + } + + AppLogger.d( + TAG, + "Successfully parsed $name with date $dateTimeStr -> timestamp $timestamp" + ) + + entries.add( + DirectoryListingData.FileEntry( + name = name, + isDirectory = isDirectory, + size = size, + permissions = permissions, + lastModified = timestamp // 使用时间戳字符串 + ) + ) + continue + } + + // 如果Android特定格式不匹配,尝试通用格式 + val genericRegex = + """^([\-ld][\w-]{9})\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+([\w\d\s\-:\.]+)\s+(.+)$""".toRegex() + val match = genericRegex.find(line) + + if (match != null) { + val permissions = match.groupValues[1] + val size = match.groupValues[5].toLongOrNull() ?: 0 + val dateTimeStr = match.groupValues[6].trim() + var name = match.groupValues[7] + val isDirectory = permissions.startsWith("d") + val isSymlink = permissions.startsWith("l") + + // 处理符号链接格式 "name -> target" + if (isSymlink && name.contains(" -> ")) { + name = name.substringBefore(" -> ") + AppLogger.d(TAG, "Found symlink (generic): $name") + } + + // 跳过 . 和 .. 条目 + if (name == "." || name == "..") continue + + // 尝试解析通用格式的日期时间 + val timestamp = + try { + if (dateTimeStr.matches( + """^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}$""".toRegex() + ) + ) { + val parsedDate = dateFormat.parse(dateTimeStr) + parsedDate?.time?.toString() ?: "0" + } else { + // 如果不是YYYY-MM-DD HH:MM格式,返回当前时间 + System.currentTimeMillis().toString() + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error parsing generic date: $dateTimeStr", e) + "0" + } + + entries.add( + DirectoryListingData.FileEntry( + name = name, + isDirectory = isDirectory, + size = size, + permissions = permissions, + lastModified = timestamp + ) + ) + } else { + // 如果标准正则表达式也不匹配,使用更宽松的解析方法 + // 权限字段始终是10个字符 + if (line.length < 10) continue + + val permissions = line.substring(0, 10).trim() + val isDirectory = permissions.startsWith("d") || permissions.startsWith("c") + + // 解析剩余部分 + val parts = line.substring(10).trim().split("\\s+".toRegex()) + + if (parts.size < 6) { + AppLogger.w(TAG, "Invalid ls -la format: $line") + continue + } + + // 查找日期部分 - Android上通常是YYYY-MM-DD格式 + val dateIndex = + parts.indexOfFirst { it.matches("""^\d{4}-\d{2}-\d{2}$""".toRegex()) } + + if (dateIndex < 0 || dateIndex + 1 >= parts.size) { + AppLogger.w(TAG, "Cannot find date in line: $line") + continue + } + + // 日期后面的字段通常是时间 (HH:MM) + val timeIndex = dateIndex + 1 + + // 时间后面的所有内容都是文件名 + val nameStartIndex = timeIndex + 1 + if (nameStartIndex >= parts.size) { + AppLogger.w(TAG, "Cannot find filename position: $line") + continue + } + + var name = parts.subList(nameStartIndex, parts.size).joinToString(" ") + val isSymlink = permissions.startsWith("l") + + // 处理符号链接格式 "name -> target" + if (isSymlink && name.contains(" -> ")) { + name = name.substringBefore(" -> ") + AppLogger.d(TAG, "Found symlink (fallback): $name") + } + + // 跳过 . 和 .. 条目 + if (name == "." || name == "..") continue + + // 文件大小通常在用户和组之后,日期之前 + val sizeIndex = dateIndex - 1 + val size = if (sizeIndex >= 0) parts[sizeIndex].toLongOrNull() ?: 0 else 0 + + // 组合日期和时间,并转换为时间戳 + val dateTimeStr = "${parts[dateIndex]} ${parts[timeIndex]}" + val timestamp = + try { + val parsedDate = dateFormat.parse(dateTimeStr) + parsedDate?.time?.toString() ?: "0" + } catch (e: Exception) { + AppLogger.e(TAG, "Error parsing fallback date: $dateTimeStr", e) + "0" + } + + entries.add( + DirectoryListingData.FileEntry( + name = name, + isDirectory = isDirectory, + size = size, + permissions = permissions, + lastModified = timestamp + ) + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error parsing directory entry: ${lines[i]}", e) + // 跳过这一行但继续处理其他行 + } + } + + return entries + } + + /** 将八进制权限格式转换为字符串表示 (如 "rwxr-xr-x") */ + protected fun convertOctalPermToString(octalPerm: String): String { + try { + val permInt = octalPerm.toInt(8) + val permChars = CharArray(9) + + // 所有者权限 + permChars[0] = if (permInt and 0x100 != 0) 'r' else '-' + permChars[1] = if (permInt and 0x80 != 0) 'w' else '-' + permChars[2] = if (permInt and 0x40 != 0) 'x' else '-' + + // 组权限 + permChars[3] = if (permInt and 0x20 != 0) 'r' else '-' + permChars[4] = if (permInt and 0x10 != 0) 'w' else '-' + permChars[5] = if (permInt and 0x8 != 0) 'x' else '-' + + // 其他用户权限 + permChars[6] = if (permInt and 0x4 != 0) 'r' else '-' + permChars[7] = if (permInt and 0x2 != 0) 'w' else '-' + permChars[8] = if (permInt and 0x1 != 0) 'x' else '-' + + return String(permChars) + } catch (e: Exception) { + AppLogger.e(TAG, "Error converting octal permission: $octalPerm", e) + return "???" + } + } + + /** + * Reads the full content of a file as a new tool, handling different file types. + * This function does not enforce a size limit. + */ + private suspend fun readFileFullWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.readFileFull(tool) + } + if (isSafEnvironment(environment)) { + return super.readFileFull(tool) + } + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + val textOnly = tool.parameters.find { it.name == "text_only" }?.value?.toBoolean() ?: false + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + + // 如果是Operit内部存储路径,使用super的高权限方法 + if (isOperitInternalPath(path)) { + return super.readFileFull(tool) + } + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Path parameter is required" + ) + } + + try { + // First check if the file exists using shell command + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -f '$path' && echo 'exists' || echo 'not exists'" + ) + if (existsResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "File does not exist: $path" + ) + } + + // Check file extension + val fileExt = path.substringAfterLast('.', "").lowercase() + + // Handle special file types by calling the parent's handler + val specialReadResult = super.handleSpecialFileRead(tool, path, fileExt) + if (specialReadResult != null) { + // If the parent handled it, return its result. + // But if it failed, we might want to fall back to shell `cat` for some types. + if (specialReadResult.success) { + return specialReadResult + } + // Optional: Could add fallback logic here if superclass fails for some reason + } + + // Check if file is text-like by reading first few bytes (if text_only is enabled) + if (textOnly) { + // First, get a sample of the file + val sampleResult = AndroidShellExecutor.executeShellCommand("head -c 512 '$path'") + if (!sampleResult.success) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to sample file: ${sampleResult.stderr}" + ) + } + + // Analyze the sample bytes + val sampleBytes = sampleResult.stdout.toByteArray() + if (!FileUtils.isTextLike(sampleBytes)) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Skipped non-text file: $path" + ) + } + } + + // For text-like files, use shell `cat` to read full content + val result = AndroidShellExecutor.executeShellCommand("cat '$path'") + if (result.success) { + val sizeResult = + AndroidShellExecutor.executeShellCommand("stat -c %s '$path'") + val size = + sizeResult.stdout.trim().toLongOrNull() + ?: result.stdout.length.toLong() + + return ToolResult( + toolName = tool.name, + success = true, + result = + FileContentData( + path = path, + content = result.stdout, + size = size + ), + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to read file: ${result.stderr}" + ) + } + + } catch (e: Exception) { + AppLogger.e(TAG, "Error reading file", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error reading file: ${e.message}" + ) + } + } + + /** Read file content */ + private suspend fun readFileWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.readFile(tool) + } + if (isSafEnvironment(environment)) { + return super.readFile(tool) + } + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + + // 如果是Operit内部存储路径,使用super的高权限方法 + if (isOperitInternalPath(path)) { + return super.readFile(tool) + } + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Path parameter is required" + ) + } + + try { + val fileExt = path.substringAfterLast('.', "").lowercase() + + // For special types, full read then truncate text is the only way. + if (isSpecialFileType(fileExt)) { + val fullResult = readFileFull(tool) + if (!fullResult.success) return fullResult + + val contentData = fullResult.result as FileContentData + var content = contentData.content + val isTruncated = content.length > ToolExecutionLimits.MAX_FILE_READ_BYTES + if (isTruncated) { + content = content.substring(0, ToolExecutionLimits.MAX_FILE_READ_BYTES) + } + + var contentWithLineNumbers = addLineNumbers(content) + if (isTruncated) { + contentWithLineNumbers += "\n\n... (file content truncated) ..." + } + + return ToolResult( + toolName = tool.name, + success = true, + result = FileContentData(path = path, content = contentWithLineNumbers, size = contentWithLineNumbers.length.toLong()), + error = "" + ) + } + + // For text-based files, read only the beginning. + // Check if file is text-like by analyzing a sample + val sampleResult = AndroidShellExecutor.executeShellCommand("head -c 512 '$path'") + if (sampleResult.success) { + val sampleBytes = sampleResult.stdout.toByteArray() + if (!FileUtils.isTextLike(sampleBytes)) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "File does not appear to be a text file. Use readFileFull tool for special file types." + ) + } + } + + // Check file size to see if truncation is needed + val sizeResult = AndroidShellExecutor.executeShellCommand("stat -c %s '$path'") + val size = sizeResult.stdout.trim().toLongOrNull() ?: 0 + val truncated = size > ToolExecutionLimits.MAX_FILE_READ_BYTES + + val readCommand = "head -c ${ToolExecutionLimits.MAX_FILE_READ_BYTES} '$path'" + val readResult = AndroidShellExecutor.executeShellCommand(readCommand) + + if (!readResult.success) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to read file: ${readResult.stderr}" + ) + } + + var content = readResult.stdout + var contentWithLineNumbers = addLineNumbers(content) + if (truncated) { + contentWithLineNumbers += "\n\n... (file content truncated) ..." + } + + return ToolResult( + toolName = tool.name, + success = true, + result = + FileContentData( + path = path, + content = contentWithLineNumbers, + size = contentWithLineNumbers.length.toLong() + ), + error = "" + ) + } catch (e: Exception) { + AppLogger.e(TAG, "Error reading file", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error reading file: ${e.message}" + ) + } + } + + /** 按行号范围读取文件内容(行号从1开始,包括开始行和结束行) */ + private suspend fun readFilePartWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.readFilePart(tool) + } + if (isSafEnvironment(environment)) { + return super.readFilePart(tool) + } + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + + // 如果是Operit内部存储路径,使用super的高权限方法 + if (isOperitInternalPath(path)) { + return super.readFilePart(tool) + } + val startLineParam = tool.parameters.find { it.name == "start_line" }?.value?.toIntOrNull() ?: 1 + val endLineParam = tool.parameters.find { it.name == "end_line" }?.value?.toIntOrNull() + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Path parameter is required" + ) + } + + return try { + // 0. 特殊文件类型检查 + // 如果是Word/PDF/图片等特殊文件,使用父类(StandardFileSystemTools)的逻辑处理 + // 因为Shell命令(cat/sed)无法正确解析这些二进制格式 + val fileExt = path.substringAfterLast('.', "").lowercase() + if (isSpecialFileType(fileExt)) { + return super.readFilePart(tool) + } + + // 1. Check if file exists + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -f '$path' && echo 'exists' || echo 'not exists'" + ) + if (existsResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "File does not exist: $path" + ) + } + + // 2. Get total number of lines + val wcResult = AndroidShellExecutor.executeShellCommand("cat '$path' | wc -l") + if (!wcResult.success) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to count lines in file: ${wcResult.stderr}" + ) + } + + val totalLines = wcResult.stdout.trim().split(" ")[0].toIntOrNull() ?: 0 + + // 3. 计算实际的行号范围(行号从1开始) + val startLine = maxOf(1, startLineParam).coerceIn(1, maxOf(1, totalLines)) + val endLine = + (endLineParam + ?: (startLine + ToolExecutionLimits.DEFAULT_FILE_READ_PART_LINES - 1)) + .coerceIn(startLine, maxOf(1, totalLines)) + + if (totalLines == 0 || startLine > endLine) { + return ToolResult( + toolName = tool.name, + success = true, + result = + FilePartContentData( + path = path, + content = "", + partIndex = 0, // 保留兼容性,但不再使用 + totalParts = 1, // 保留兼容性,但不再使用 + startLine = startLine - 1, // 转为0-based + endLine = endLine, + totalLines = totalLines + ), + error = "" + ) + } + + // 4. Extract the specific part using sed + val sedCommand = "sed -n '${startLine},${endLine}p' '$path'" + val partResult = AndroidShellExecutor.executeShellCommand(sedCommand) + + if (!partResult.success) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to read file part: ${partResult.stderr}" + ) + } + + val maxFileSizeBytes = ToolExecutionLimits.MAX_FILE_READ_BYTES + var content = partResult.stdout + val isTruncated = content.length > maxFileSizeBytes + if (isTruncated) { + content = content.substring(0, maxFileSizeBytes) + } + + var contentWithLineNumbers = addLineNumbers(content, startLine, totalLines) + if (isTruncated) { + contentWithLineNumbers += "\n\n... (file content truncated) ..." + } + + ToolResult( + toolName = tool.name, + success = true, + result = + FilePartContentData( + path = path, + content = contentWithLineNumbers.trimEnd(), + partIndex = 0, // 保留兼容性,但不再使用 + totalParts = 1, // 保留兼容性,但不再使用 + startLine = startLine - 1, // To 0-indexed for response + endLine = endLine, + totalLines = totalLines + ), + error = "" + ) + } catch (e: Exception) { + AppLogger.e(TAG, "Error reading file part", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error reading file part: ${e.message}" + ) + } + } + + /** + * 重写特殊文件读取逻辑 + * 对于受保护的路径(如 /Android/data),先通过Shell命令复制到缓存目录, + * 再调用父类的解析逻辑。 + */ + override suspend fun handleSpecialFileRead( + tool: AITool, + path: String, + fileExt: String + ): ToolResult? { + val file = File(path) + + if (isOperitInternalPath(path)) { + return super.handleSpecialFileRead(tool, path, fileExt) + } + + // 如果文件可读,直接使用父类逻辑(更高效) + if (file.exists() && file.canRead()) { + return super.handleSpecialFileRead(tool, path, fileExt) + } + + AppLogger.d(TAG, "File not directly readable (permission restricted), trying Shell copy for: $path") + + // 创建临时文件用于中转 + val tempFile = File(context.cacheDir, "shell_copy_${System.currentTimeMillis()}.$fileExt") + + return try { + // 使用cat命令复制文件内容 + // 注意:使用cat而不是cp,因为cp可能保留权限属性导致仍然无法读取 + val copyResult = AndroidShellExecutor.executeShellCommand("cat '$path' > '${tempFile.absolutePath}'") + + if (!copyResult.success) { + AppLogger.w(TAG, "Shell copy failed: ${copyResult.stderr}") + // 复制失败,回退到父类逻辑(虽然很可能也失败,但能返回一致的错误信息) + return super.handleSpecialFileRead(tool, path, fileExt) + } + + // 检查临时文件是否有效 + if (!tempFile.exists() || tempFile.length() == 0L) { + AppLogger.w(TAG, "Temp file is empty or does not exist after copy") + return super.handleSpecialFileRead(tool, path, fileExt) + } + + // 使用临时文件路径调用父类处理逻辑 + val tempToolResult = super.handleSpecialFileRead(tool, tempFile.absolutePath, fileExt) + + // 如果处理成功,修正返回结果中的 path 为原始路径 + if (tempToolResult != null && tempToolResult.success) { + val resultData = tempToolResult.result + if (resultData is FileContentData) { + return tempToolResult.copy( + result = resultData.copy(path = path) + ) + } + } + + tempToolResult + + } catch (e: Exception) { + AppLogger.e(TAG, "Error in shell copy strategy", e) + super.handleSpecialFileRead(tool, path, fileExt) + } finally { + // 清理临时文件 + try { + if (tempFile.exists()) { + tempFile.delete() + } + } catch (e: Exception) { + AppLogger.e(TAG, "Failed to clean up temp file", e) + } + } + } + + /** Write content to a file */ + private suspend fun writeFileWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.writeFile(tool) + } + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + if (isSafEnvironment(environment)) { + return super.writeFile(tool) + } + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + val content = tool.parameters.find { it.name == "content" }?.value ?: "" + val append = tool.parameters.find { it.name == "append" }?.value?.toBoolean() ?: false + + // 如果是Operit内部存储路径,使用super的高权限方法 + if (isOperitInternalPath(path)) { + return super.writeFile(tool) + } + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "write", + path = "", + successful = false, + details = "Path parameter is required" + ), + error = "Path parameter is required" + ) + } + + return try { + // 确保目标目录存在 + val directory = File(path).parent + if (directory != null) { + val mkdirResult = AndroidShellExecutor.executeShellCommand("mkdir -p '$directory'") + if (!mkdirResult.success) { + AppLogger.w(TAG, "Warning: Failed to create parent directory: ${mkdirResult.stderr}") + } + } + + // 直接使用echo命令写入内容 + // 对内容进行base64编码,避免特殊字符问题 + val contentBase64 = + android.util.Base64.encodeToString( + content.toByteArray(), + android.util.Base64.NO_WRAP + ) + + // 使用 base64 写入;大内容分块,失败后不重新提交已写入的数据。 + val redirectOperator = if (append) ">>" else ">" + val maxInlineBase64 = 32768 + val base64ChunkSize = 16384 // 4的倍数,保证base64解码边界正确 + val writeResult = + if (contentBase64.length <= maxInlineBase64) { + AndroidShellExecutor.executeShellCommand( + "echo '$contentBase64' | base64 -d $redirectOperator '$path'" + ) + } else { + var chunkSuccess = true + var firstChunk = true + var index = 0 + while (index < contentBase64.length) { + val end = (index + base64ChunkSize).coerceAtMost(contentBase64.length) + val chunk = contentBase64.substring(index, end) + val chunkRedirect = if (firstChunk) redirectOperator else ">>" + val chunkResult = + AndroidShellExecutor.executeShellCommand( + "echo '$chunk' | base64 -d $chunkRedirect '$path'" + ) + if (!chunkResult.success) { + AppLogger.e( + TAG, + "Failed to write base64 chunk: ${chunkResult.stderr}" + ) + chunkSuccess = false + break + } + firstChunk = false + index = end + } + if (chunkSuccess) { + AndroidShellExecutor.CommandResult(true, "", "", 0) + } else { + AndroidShellExecutor.CommandResult(false, "", "Failed to write base64 chunks") + } + } + + if (!writeResult.success) { + AppLogger.e(TAG, "Failed to write with base64 method: ${writeResult.stderr}") + return ToolResult( + toolName = tool.name, + success = false, + result = FileOperationData( + operation = if (append) "append" else "write", + path = path, + successful = false, + details = "Failed to write to file: ${writeResult.stderr}" + ), + error = "Failed to write to file: ${writeResult.stderr}" + ) + } + + // 验证写入是否成功 + val verifyResult = + AndroidShellExecutor.executeShellCommand( + "test -f '$path' && echo 'exists' || echo 'not exists'" + ) + if (verifyResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = if (append) "append" else "write", + path = path, + successful = false, + details = + "Write command completed but file does not exist. Possible permission issue." + ), + error = + "Write command completed but file does not exist. Possible permission issue." + ) + } + + // 检查文件大小确认内容被写入 + val sizeResult = + AndroidShellExecutor.executeShellCommand( + "stat -c %s '$path' 2>/dev/null || echo '0'" + ) + val size = sizeResult.stdout.trim().toLongOrNull() ?: 0 + if (size == 0L && content.isNotEmpty()) { + // 文件存在但是大小为0,可能写入失败 + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = if (append) "append" else "write", + path = path, + successful = false, + details = + "File was created but appears to be empty. Possible write failure." + ), + error = "File was created but appears to be empty. Possible write failure." + ) + } + + val operation = if (append) "append" else "write" + val details = if (append) "Content appended to $path" else "Content written to $path" + + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = operation, + path = path, + successful = true, + details = details + ), + error = "" + ) + } catch (e: Exception) { + AppLogger.e(TAG, "Error writing to file", e) + + // 提供更具体的错误信息 + val errorMessage = + when { + e is InterruptedException || + e.message?.contains("interrupted", ignoreCase = true) == true -> + "ADB connection interrupted, possibly due to network instability. Please check ADB connection and retry. Error details: ${e.message}" + e is java.net.SocketException || + e.message?.contains("socket", ignoreCase = true) == true -> + "ADB network connection exception, please check if device is still connected and retry. Error details: ${e.message}" + e is java.io.IOException -> "File IO error: ${e.message}. Please check if the file path has write permission." + e.message?.contains("permission", ignoreCase = true) == true -> + "Permission denied, cannot write to file: ${e.message}. Please check if the app has appropriate permissions." + else -> "Error writing to file: ${e.message}" + } + + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = if (append) "append" else "write", + path = path, + successful = false, + details = errorMessage + ), + error = errorMessage + ) + } + } + + /** Delete a file or directory */ + private suspend fun deleteFileWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.deleteFile(tool) + } + + if (isSafEnvironment(environment)) { + return super.deleteFile(tool) + } + + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + + // 如果是Operit内部存储路径,使用super的高权限方法 + if (isOperitInternalPath(path)) { + return super.deleteFile(tool) + } + val recursive = tool.parameters.find { it.name == "recursive" }?.value?.toBoolean() ?: false + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "delete", + path = "", + successful = false, + details = "Path parameter is required" + ), + error = "Path parameter is required" + ) + } + + + return try { + val quotedPath = shQuote(path) + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -e $quotedPath && echo 'exists' || echo 'missing'" + ) + if (existsResult.stdout.trim() != "exists") { + ToolProgressBus.update(tool.name, 1f, "Delete failed") + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "delete", + path = path, + successful = false, + details = "File or directory does not exist: $path" + ), + error = "File or directory does not exist: $path" + ) + } + + val typeResult = + AndroidShellExecutor.executeShellCommand( + "if test -d $quotedPath; then echo 'directory'; elif test -f $quotedPath; then echo 'file'; else echo 'other'; fi" + ) + val isDirectory = typeResult.stdout.trim() == "directory" + + ToolProgressBus.update( + tool.name, + 0.1f, + if (isDirectory) "Deleting directory..." else "Deleting file..." + ) + + val deleteCommand = + if (recursive) "rm -rf $quotedPath" else if (isDirectory) "rmdir $quotedPath" else "rm -f $quotedPath" + val result = AndroidShellExecutor.executeShellCommand(deleteCommand) + + if (result.success && isDirectory && recursive) { + ToolProgressBus.update(tool.name, 0.85f, "Finalizing directory deletion...") + AndroidShellExecutor.executeShellCommand("rmdir $quotedPath") + } + + val verifyDeletedResult = + AndroidShellExecutor.executeShellCommand( + "test -e $quotedPath && echo 'exists' || echo 'missing'" + ) + val deleted = verifyDeletedResult.stdout.trim() != "exists" + + if (result.success && deleted) { + ToolProgressBus.update(tool.name, 1f, "Delete completed") + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "delete", + path = path, + successful = true, + details = "Successfully deleted $path" + ), + error = "" + ) + } else { + val errorMessage = + when { + !result.success && result.stderr.isNotBlank() -> + "Failed to delete: ${result.stderr}" + !deleted -> "Failed to delete: target still exists after delete command" + else -> "Failed to delete: unknown error" + } + ToolProgressBus.update(tool.name, 1f, "Delete failed") + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "delete", + path = path, + successful = false, + details = errorMessage + ), + error = errorMessage + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error deleting file/directory", e) + ToolProgressBus.update(tool.name, 1f, "Delete failed") + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "delete", + path = path, + successful = false, + details = "Error deleting file/directory: ${e.message}" + ), + error = "Error deleting file/directory: ${e.message}" + ) + } + } + + /** Check if a file or directory exists */ + private suspend fun fileExistsWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.fileExists(tool) + } + + if (isSafEnvironment(environment)) { + return super.fileExists(tool) + } + + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + + // 如果是Operit内部存储路径,使用super的高权限方法 + if (isOperitInternalPath(path)) { + return super.fileExists(tool) + } + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Path parameter is required" + ) + } + + return try { + // Check if the path exists + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -e '$path' && echo 'exists' || echo 'not exists'" + ) + val exists = existsResult.success && existsResult.stdout.trim() == "exists" + + if (!exists) { + // If it doesn't exist, return a simple FileExistsData with + // exists=false + return ToolResult( + toolName = tool.name, + success = true, + result = FileExistsData(path = path, exists = false), + error = "" + ) + } + + // If it exists, check if it's a directory + val isDirResult = + AndroidShellExecutor.executeShellCommand( + "test -d '$path' && echo 'true' || echo 'false'" + ) + val isDirectory = isDirResult.success && isDirResult.stdout.trim() == "true" + + // Get the size + val sizeResult = + AndroidShellExecutor.executeShellCommand( + "stat -c %s '$path' 2>/dev/null || echo '0'" + ) + val size = sizeResult.stdout.trim().toLongOrNull() ?: 0 + + return ToolResult( + toolName = tool.name, + success = true, + result = + FileExistsData( + path = path, + exists = true, + isDirectory = isDirectory, + size = size + ), + error = "" + ) + } catch (e: Exception) { + AppLogger.e(TAG, "Error checking file existence", e) + return ToolResult( + toolName = tool.name, + success = false, + result = + FileExistsData( + path = path, + exists = false, + isDirectory = false, + size = 0 + ), + error = "Error checking file existence: ${e.message}" + ) + } + } + + /** Move or rename a file or directory */ + private suspend fun moveFileWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.moveFile(tool) + } + val sourcePath = tool.parameters.find { it.name == "source" }?.value ?: "" + val destPath = tool.parameters.find { it.name == "destination" }?.value ?: "" + if (isSafEnvironment(environment)) { + return super.moveFile(tool) + } + PathValidator.validateAndroidPath(sourcePath, tool.name)?.let { return it } + PathValidator.validateAndroidPath(destPath, tool.name)?.let { return it } + + // 如果源文件或目标文件在Operit内部存储,使用super的高权限方法 + if (isOperitInternalPath(sourcePath) || isOperitInternalPath(destPath)) { + return super.moveFile(tool) + } + PathValidator.validateAndroidPath(destPath, tool.name, "destination")?.let { return it } + + if (sourcePath.isBlank() || destPath.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "move", + path = sourcePath, + successful = false, + details = "Source and destination parameters are required" + ), + error = "Source and destination parameters are required" + ) + } + + + return try { + val result = AndroidShellExecutor.executeShellCommand("mv '$sourcePath' '$destPath'") + + if (result.success) { + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "move", + path = sourcePath, + successful = true, + details = "Successfully moved $sourcePath to $destPath" + ), + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "move", + path = sourcePath, + successful = false, + details = "Failed to move file: ${result.stderr}" + ), + error = "Failed to move file: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error moving file", e) + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "move", + path = sourcePath, + successful = false, + details = "Error moving file: ${e.message}" + ), + error = "Error moving file: ${e.message}" + ) + } + } + + /** Copy a file or directory */ + private suspend fun copyFileWithShell(tool: AITool): ToolResult { + // 检查是否是 Linux 环境或跨环境操作 + val environment = tool.parameters.find { it.name == "environment" }?.value + val sourceEnvironment = tool.parameters.find { it.name == "source_environment" }?.value + val destEnvironment = tool.parameters.find { it.name == "dest_environment" }?.value + + // 确定源和目标环境 + val srcEnv = sourceEnvironment ?: environment ?: "android" + val dstEnv = destEnvironment ?: environment ?: "android" + + // 如果是 Linux 环境或跨环境操作,委托给父类处理 + if (srcEnv.lowercase() == "linux" || dstEnv.lowercase() == "linux") { + return super.copyFile(tool) + } + + val sourcePath = tool.parameters.find { it.name == "source" }?.value ?: "" + val destPath = tool.parameters.find { it.name == "destination" }?.value ?: "" + val recursive = tool.parameters.find { it.name == "recursive" }?.value?.toBoolean() ?: true + if (sourcePath.startsWith("content://", ignoreCase = true) || destPath.startsWith("content://", ignoreCase = true)) { + return super.copyFile(tool) + } + PathValidator.validateAndroidPath(sourcePath, tool.name, "source")?.let { return it } + PathValidator.validateAndroidPath(destPath, tool.name, "destination")?.let { return it } + + // 如果源文件或目标文件在Operit内部存储,使用super的高权限方法 + if (isOperitInternalPath(sourcePath) || isOperitInternalPath(destPath)) { + return super.copyFile(tool) + } + + if (sourcePath.isBlank() || destPath.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "copy", + path = sourcePath, + successful = false, + details = "Source and destination parameters are required" + ), + error = "Source and destination parameters are required" + ) + } + + return try { + // 首先检查源路径是否存在 + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -e '$sourcePath' && echo 'exists' || echo 'not exists'" + ) + if (existsResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "copy", + path = sourcePath, + successful = false, + details = "Source path does not exist: $sourcePath" + ), + error = "Source path does not exist: $sourcePath" + ) + } + + // 检查是否为目录 + val isDirResult = + AndroidShellExecutor.executeShellCommand( + "test -d '$sourcePath' && echo 'true' || echo 'false'" + ) + val isDirectory = isDirResult.stdout.trim() == "true" + + // 确保目标父目录存在 + val destParentDir = destPath.substringBeforeLast('/') + if (destParentDir.isNotEmpty()) { + AndroidShellExecutor.executeShellCommand("mkdir -p '$destParentDir'") + } + + // 根据是否为目录选择不同的复制命令 + val copyCommand = + if (isDirectory && recursive) { + "cp -r '$sourcePath' '$destPath'" + } else if (!isDirectory) { + "cp '$sourcePath' '$destPath'" + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "copy", + path = sourcePath, + successful = false, + details = + "Cannot copy directory without recursive flag" + ), + error = "Cannot copy directory without recursive flag" + ) + } + + val result = AndroidShellExecutor.executeShellCommand(copyCommand) + + if (result.success) { + // 验证复制是否成功 + val verifyResult = + AndroidShellExecutor.executeShellCommand( + "test -e '$destPath' && echo 'exists' || echo 'not exists'" + ) + if (verifyResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "copy", + path = sourcePath, + successful = false, + details = + "Copy command completed but destination does not exist" + ), + error = "Copy command completed but destination does not exist" + ) + } + + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "copy", + path = sourcePath, + successful = true, + details = + "Successfully copied ${if (isDirectory) "directory" else "file"} $sourcePath to $destPath" + ), + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "copy", + path = sourcePath, + successful = false, + details = "Failed to copy: ${result.stderr}" + ), + error = "Failed to copy: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error copying file/directory", e) + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "copy", + path = sourcePath, + successful = false, + details = "Error copying file/directory: ${e.message}" + ), + error = "Error copying file/directory: ${e.message}" + ) + } + } + + /** Create a directory */ + private suspend fun makeDirectoryWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.makeDirectory(tool) + } + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + if (isSafEnvironment(environment)) { + return super.makeDirectory(tool) + } + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + + // 如果是Operit内部存储路径,使用super的高权限方法 + if (isOperitInternalPath(path)) { + return super.makeDirectory(tool) + } + val createParents = + tool.parameters.find { it.name == "create_parents" }?.value?.toBoolean() ?: false + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "mkdir", + path = "", + successful = false, + details = "Path parameter is required" + ), + error = "Path parameter is required" + ) + } + + return try { + // 首先检查目录是否已存在 + val checkDirResult = + AndroidShellExecutor.executeShellCommand( + "test -d '$path' && echo 'exists' || echo 'not exists'" + ) + + if (checkDirResult.success && checkDirResult.stdout.trim() == "exists") { + // 目录已存在,返回成功 + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "mkdir", + path = path, + successful = true, + details = "Directory already exists: $path" + ), + error = "" + ) + } + + val mkdirCommand = if (createParents) "mkdir -p '$path'" else "mkdir '$path'" + val result = AndroidShellExecutor.executeShellCommand(mkdirCommand) + + if (result.success) { + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "mkdir", + path = path, + successful = true, + details = "Successfully created directory $path" + ), + error = "" + ) + } else { + // 创建失败后再次检查是否已存在(可能在执行过程中被创建) + val recheckDirResult = + AndroidShellExecutor.executeShellCommand( + "test -d '$path' && echo 'exists' || echo 'not exists'" + ) + + if (recheckDirResult.success && recheckDirResult.stdout.trim() == "exists") { + // 目录已存在,返回成功 + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "mkdir", + path = path, + successful = true, + details = "Directory already exists: $path" + ), + error = "" + ) + } + + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "mkdir", + path = path, + successful = false, + details = "Failed to create directory: ${result.stderr}" + ), + error = "Failed to create directory: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error creating directory", e) + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "mkdir", + path = path, + successful = false, + details = "Error creating directory: ${e.message}" + ), + error = "Error creating directory: ${e.message}" + ) + } + } + + /** Search for files matching a pattern */ + private suspend fun findFilesWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.findFiles(tool) + } + + if (isSafEnvironment(environment)) { + return super.findFiles(tool) + } + + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + val pattern = tool.parameters.find { it.name == "pattern" }?.value ?: "" + + if (isOperitInternalPath(path)) { + return super.findFiles(tool) + } + + if (path.isBlank() || pattern.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = + FindFilesResultData( + path = path, + pattern = pattern, + files = emptyList() + ), + error = "Path and pattern parameters are required" + ) + } + + return try { + ToolProgressBus.update(tool.name, 0.02f, "Searching (device)...") + // Add options for different search modes + val usePathPattern = + tool.parameters.find { it.name == "use_path_pattern" }?.value?.toBoolean() + ?: false + val caseInsensitive = + tool.parameters.find { it.name == "case_insensitive" }?.value?.toBoolean() + ?: false + + val isFileResult = + AndroidShellExecutor.executeShellCommand( + "test -f ${shQuote(path)} && echo file || echo not_file" + ) + if (isFileResult.success && isFileResult.stdout.trim() == "file") { + val fileName = path.substringAfterLast('/') + val testString = if (usePathPattern) path else fileName + val regex = globToRegex(pattern, caseInsensitive) + val files = if (regex.matches(testString)) listOf(path) else emptyList() + + ToolProgressBus.update(tool.name, 1f, "Search completed, found ${files.size}") + + return ToolResult( + toolName = tool.name, + success = true, + result = FindFilesResultData(path = path, pattern = pattern, files = files), + error = "" + ) + } + + // Add depth control parameter (default to -1 for unlimited depth/fully + // recursive) + val maxDepth = + tool.parameters.find { it.name == "max_depth" }?.value?.toIntOrNull() ?: -1 + + // Determine which search option to use + val searchOption = + if (usePathPattern) { + if (caseInsensitive) "-ipath" else "-path" + } else { + if (caseInsensitive) "-iname" else "-name" + } + + // Properly escape the pattern if quotes are required + val escapedPattern = pattern.replace("'", "'\\''") + val patternForCommand = "'$escapedPattern'" + + // Build the command with depth control if specified + val depthOption = if (maxDepth >= 0) "-maxdepth $maxDepth" else "" + val command = + "find '${if(path.endsWith("/")) path else "$path/"}' $depthOption $searchOption $patternForCommand" + + val files = mutableListOf() + val foundCount = AtomicInteger(0) + val progressFloor = AtomicInteger(2) + val stderrBuilder = StringBuilder() + + val process = AndroidShellExecutor.startShellProcess(command) + try { + val exitCode = coroutineScope { + val stdoutJob = launch { + process.stdout.collect { line -> + val v = line.trim() + if (v.isNotEmpty()) { + files.add(v) + val found = foundCount.incrementAndGet() + val p = (smoothProgress(found, 250f) * 100).toInt().coerceIn(0, 99) + updateProgressFloor(progressFloor, p) + if (found % 20 == 0) { + ToolProgressBus.update( + tool.name, + progressFloor.get() / 100f, + "Searching... found $found" + ) + } + } + } + } + val stderrJob = launch { + process.stderr.collect { line -> + if (line.isNotBlank()) { + stderrBuilder.appendLine(line) + } + } + } + val tickerJob = launch { + while (isActive && process.isAlive) { + delay(500) + val current = progressFloor.get() + if (current < 95) { + progressFloor.compareAndSet(current, current + 1) + ToolProgressBus.update( + tool.name, + progressFloor.get() / 100f, + "Searching... found ${foundCount.get()}" + ) + } + } + } + + val code = process.waitFor() + stdoutJob.cancelAndJoin() + stderrJob.cancelAndJoin() + tickerJob.cancelAndJoin() + code + } + + if (exitCode != 0) { + val err = stderrBuilder.toString().trim() + return ToolResult( + toolName = tool.name, + success = false, + result = FindFilesResultData(path = path, pattern = pattern, files = emptyList()), + error = if (err.isNotBlank()) err else "find command failed with exitCode=$exitCode" + ) + } + } finally { + if (process.isAlive) { + process.destroy() + } + } + + ToolProgressBus.update(tool.name, 1f, "Search completed, found ${files.size}") + + return ToolResult( + toolName = tool.name, + success = true, + result = FindFilesResultData(path = path, pattern = pattern, files = files), + error = "" + ) + } catch (e: Exception) { + AppLogger.e(TAG, "Error searching for files", e) + ToolProgressBus.update(tool.name, 1f, "Search failed") + return ToolResult( + toolName = tool.name, + success = false, + result = + FindFilesResultData( + path = path, + pattern = pattern, + files = emptyList() + ), + error = "Error searching for files: ${e.message}" + ) + } + } + + /** Get file information */ + private suspend fun fileInfoWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.fileInfo(tool) + } + + if (isSafEnvironment(environment)) { + return super.fileInfo(tool) + } + + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + + // 如果是Operit内部存储路径,使用super的高权限方法 + if (isOperitInternalPath(path)) { + return super.fileInfo(tool) + } + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileInfoData( + path = "", + exists = false, + fileType = "", + size = 0, + permissions = "", + owner = "", + group = "", + lastModified = "", + rawStatOutput = "" + ), + error = "Path parameter is required" + ) + } + + return try { + // Check if file exists + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -e '$path' && echo 'exists' || echo 'not exists'" + ) + if (existsResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileInfoData( + path = path, + exists = false, + fileType = "", + size = 0, + permissions = "", + owner = "", + group = "", + lastModified = "", + rawStatOutput = "" + ), + error = "File or directory does not exist: $path" + ) + } + + // Get file details using stat + val statResult = AndroidShellExecutor.executeShellCommand("stat '$path'") + + if (statResult.success) { + // Get file type + val fileTypeResult = + AndroidShellExecutor.executeShellCommand( + "test -d '$path' && echo 'directory' || (test -f '$path' && echo 'file' || echo 'other')" + ) + val fileType = fileTypeResult.stdout.trim() + + // Get file size + val sizeResult = + AndroidShellExecutor.executeShellCommand( + "stat -c %s '$path' 2>/dev/null || echo '0'" + ) + val size = sizeResult.stdout.trim().toLongOrNull() ?: 0 + + // Get file permissions + val permissionsResult = + AndroidShellExecutor.executeShellCommand( + "stat -c %A '$path' 2>/dev/null || echo ''" + ) + val permissions = permissionsResult.stdout.trim() + + // Get owner and group + val ownerResult = + AndroidShellExecutor.executeShellCommand( + "stat -c %U '$path' 2>/dev/null || echo ''" + ) + val owner = ownerResult.stdout.trim() + + val groupResult = + AndroidShellExecutor.executeShellCommand( + "stat -c %G '$path' 2>/dev/null || echo ''" + ) + val group = groupResult.stdout.trim() + + // Get last modified time + val modifiedResult = + AndroidShellExecutor.executeShellCommand( + "stat -c %Y '$path' 2>/dev/null || echo ''" + ) + val lastModifiedEpochSec = modifiedResult.stdout.trim().toLongOrNull() + val lastModified = + if (lastModifiedEpochSec != null && lastModifiedEpochSec > 0) { + SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US) + .format(Date(lastModifiedEpochSec * 1000L)) + } else { + "" + } + + return ToolResult( + toolName = tool.name, + success = true, + result = + FileInfoData( + path = path, + exists = true, + fileType = fileType, + size = size, + permissions = permissions, + owner = owner, + group = group, + lastModified = lastModified, + rawStatOutput = statResult.stdout + ), + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileInfoData( + path = path, + exists = true, + fileType = "", + size = 0, + permissions = "", + owner = "", + group = "", + lastModified = "", + rawStatOutput = "" + ), + error = "Failed to get file information: ${statResult.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error getting file information", e) + return ToolResult( + toolName = tool.name, + success = false, + result = + FileInfoData( + path = path, + exists = false, + fileType = "", + size = 0, + permissions = "", + owner = "", + group = "", + lastModified = "", + rawStatOutput = "" + ), + error = "Error getting file information: ${e.message}" + ) + } + } + + /** Zip files or directories */ + private suspend fun zipFilesWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.zipFiles(tool) + } + val sourcePath = tool.parameters.find { it.name == "source" }?.value ?: "" + val zipPath = tool.parameters.find { it.name == "destination" }?.value ?: "" + val includeRootDirectoryParameter = tool.parameters.find { it.name == "include_root_directory" } + val includeRootDirectory = + if (includeRootDirectoryParameter == null) { + true + } else { + includeRootDirectoryParameter.value.toBooleanStrictOrNull() + ?: return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "include_root_directory must be true or false" + ) + } + PathValidator.validateAndroidPath(sourcePath, tool.name, "source")?.let { return it } + PathValidator.validateAndroidPath(zipPath, tool.name, "destination")?.let { return it } + + if (isOperitInternalPath(sourcePath) || isOperitInternalPath(zipPath)) { + return super.zipFiles(tool) + } + + if (sourcePath.isBlank() || zipPath.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Source and destination parameters are required" + ) + } + + return try { + val archiveSourcePath = + sourcePath.trimEnd('/').let { + if (it.isEmpty() && sourcePath.startsWith("/")) "/" else it + } + // First, check if the source path exists + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -e ${shQuote(archiveSourcePath)} && echo 'exists' || echo 'not exists'" + ) + if (existsResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Source file or directory does not exist: $sourcePath" + ) + } + + // Check if source is a directory + val isDirResult = + AndroidShellExecutor.executeShellCommand( + "test -d ${shQuote(archiveSourcePath)} && echo 'true' || echo 'false'" + ) + val isDirectory = isDirResult.stdout.trim() == "true" + + // Create parent directory for zip file if needed + val zipDir = File(zipPath).parent + if (zipDir != null) { + AndroidShellExecutor.executeShellCommand("mkdir -p ${shQuote(zipDir)}") + } + + // Use Java's ZipOutputStream to create the zip file + // We'll use ADB to copy files to/from the device and process locally + val sourceFile = File(archiveSourcePath) + + // Initialize buffer for file copy + val buffer = ByteArray(1024) + + // Create temporary file for processing - using external files directory for + // better + // permissions + val tempDir = context.getExternalFilesDir(null) ?: context.cacheDir + val tempSourceFile = File(tempDir, "temp_source_${System.currentTimeMillis()}") + val tempZipFile = File(tempDir, "temp_zip_${System.currentTimeMillis()}.zip") + + try { + // Make sure the temp directory exists + tempDir.mkdirs() + + if (isDirectory) { + // For directories, we need to list all files and add them + // to the zip + val listResult = + AndroidShellExecutor.executeShellCommand("find ${shQuote(archiveSourcePath)} -type f") + val fileList = listResult.stdout.trim().split("\n").filter { it.isNotEmpty() } + + // Create ZIP output stream + val fos = FileOutputStream(tempZipFile) + val zos = ZipOutputStream(BufferedOutputStream(fos)) + + try { + for (filePath in fileList) { + // Get the file path relative to the source + // directory + val pathInsideSource = + if (archiveSourcePath == "/") { + filePath.removePrefix("/") + } else { + filePath.removePrefix("$archiveSourcePath/") + } + val relativePath = + if (includeRootDirectory && sourceFile.name.isNotEmpty()) { + "${sourceFile.name}/$pathInsideSource" + } else { + pathInsideSource + } + + // Copy the file from device to temp file + val pullResult = + AndroidShellExecutor.executeShellCommand( + "cat ${shQuote(filePath)} > ${shQuote(tempSourceFile.absolutePath)}" + ) + if (!pullResult.success) { + continue // Skip this file if we + // can't pull it + } + + // Add the file to the ZIP + val fis = FileInputStream(tempSourceFile) + val bis = BufferedInputStream(fis) + + try { + // Add ZIP entry + val entry = ZipEntry(relativePath) + zos.putNextEntry(entry) + + // Write file content to ZIP + var len: Int + while (bis.read(buffer).also { len = it } > 0) { + zos.write(buffer, 0, len) + } + + zos.closeEntry() + } finally { + bis.close() + fis.close() + tempSourceFile.delete() + } + } + } finally { + zos.close() + fos.close() + } + } else { + // For a single file, simpler process + // Copy the file from device to temp file + val pullResult = + AndroidShellExecutor.executeShellCommand( + "cat ${shQuote(archiveSourcePath)} > ${shQuote(tempSourceFile.absolutePath)}" + ) + if (!pullResult.success) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to read source file: ${pullResult.stderr}" + ) + } + + // Create zip file with single entry + val fos = FileOutputStream(tempZipFile) + val zos = ZipOutputStream(BufferedOutputStream(fos)) + + try { + val fis = FileInputStream(tempSourceFile) + val bis = BufferedInputStream(fis) + + try { + // Add ZIP entry + val entry = ZipEntry(sourceFile.name) + zos.putNextEntry(entry) + + // Write file content to ZIP + var len: Int + while (bis.read(buffer).also { len = it } > 0) { + zos.write(buffer, 0, len) + } + + zos.closeEntry() + } finally { + bis.close() + fis.close() + } + } finally { + zos.close() + fos.close() + } + } + + // Log information about the temp ZIP file + AppLogger.d( + TAG, + "Temp ZIP file created at: ${tempZipFile.absolutePath}, size: ${tempZipFile.length()} bytes" + ) + + // Push the ZIP file to the destination + val pushResult = + AndroidShellExecutor.executeShellCommand( + "cat ${shQuote(tempZipFile.absolutePath)} > ${shQuote(zipPath)}" + ) + if (!pushResult.success) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to write ZIP file: ${pushResult.stderr}" + ) + } + + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "zip", + path = sourcePath, + successful = true, + details = "Successfully compressed $sourcePath to $zipPath" + ), + error = "" + ) + } finally { + // Clean up temporary files + tempSourceFile.delete() + tempZipFile.delete() + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error compressing files", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error compressing files: ${e.message}" + ) + } + } + + /** Unzip a zip file */ + private suspend fun unzipFilesWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.unzipFiles(tool) + } + val zipPath = tool.parameters.find { it.name == "source" }?.value ?: "" + val destPath = tool.parameters.find { it.name == "destination" }?.value ?: "" + PathValidator.validateAndroidPath(zipPath, tool.name, "source")?.let { return it } + PathValidator.validateAndroidPath(destPath, tool.name, "destination")?.let { return it } + + if (isOperitInternalPath(zipPath) || isOperitInternalPath(destPath)) { + return super.unzipFiles(tool) + } + + val actualZipPath = zipPath + val actualDestPath = destPath + + if (zipPath.isBlank() || destPath.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Source and destination parameters are required" + ) + } + + return try { + ToolProgressBus.update(tool.name, -1f, "Unzipping...") + // Check if the zip file exists + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -f ${shQuote(zipPath)} && echo 'exists' || echo 'not exists'" + ) + if (existsResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Zip file does not exist: $zipPath" + ) + } + + // Create destination directory if it doesn't exist + AndroidShellExecutor.executeShellCommand("mkdir -p ${shQuote(destPath)};") + + val deviceUnzipCommands = + listOf( + "unzip -o ${shQuote(zipPath)} -d ${shQuote(destPath)}", + "toybox unzip -o ${shQuote(zipPath)} -d ${shQuote(destPath)}", + "busybox unzip -o ${shQuote(zipPath)} -d ${shQuote(destPath)}" + ) + + for (cmd in deviceUnzipCommands) { + try { + ToolProgressBus.update(tool.name, 0.02f, "Unzipping (device)...") + val extractedCount = AtomicInteger(0) + val progressFloor = AtomicInteger(2) + val stderrBuilder = StringBuilder() + + val process = AndroidShellExecutor.startShellProcess("$cmd;") + try { + val exitCode = coroutineScope { + val stdoutJob = launch { + process.stdout.collect { line -> + val t = line.trimStart() + val isProgressLine = + t.startsWith("inflating:") || + t.startsWith("extracting:") || + t.startsWith("creating:") || + t.startsWith(" inflating:") || + t.startsWith(" extracting:") + + if (isProgressLine) { + val extracted = extractedCount.incrementAndGet() + val p = (smoothProgress(extracted, 120f) * 100).toInt().coerceIn(0, 99) + updateProgressFloor(progressFloor, p) + if (extracted % 10 == 0) { + ToolProgressBus.update( + tool.name, + progressFloor.get() / 100f, + "Unzipping... extracted $extracted" + ) + } + } + } + } + val stderrJob = launch { + process.stderr.collect { line -> + if (line.isNotBlank()) { + stderrBuilder.appendLine(line) + } + + val t = line.trimStart() + val isProgressLine = + t.startsWith("inflating:") || + t.startsWith("extracting:") || + t.startsWith("creating:") || + t.startsWith(" inflating:") || + t.startsWith(" extracting:") + + if (isProgressLine) { + val extracted = extractedCount.incrementAndGet() + val p = (smoothProgress(extracted, 120f) * 100).toInt().coerceIn(0, 99) + updateProgressFloor(progressFloor, p) + if (extracted % 10 == 0) { + ToolProgressBus.update( + tool.name, + progressFloor.get() / 100f, + "Unzipping... extracted $extracted" + ) + } + } + } + } + val tickerJob = launch { + while (isActive && process.isAlive) { + delay(500) + val current = progressFloor.get() + if (current < 95) { + progressFloor.compareAndSet(current, current + 1) + ToolProgressBus.update( + tool.name, + progressFloor.get() / 100f, + "Unzipping..." + ) + } + } + } + + val code = process.waitFor() + stdoutJob.cancelAndJoin() + stderrJob.cancelAndJoin() + tickerJob.cancelAndJoin() + code + } + + if (exitCode == 0) { + ToolProgressBus.update(tool.name, 1f, "Unzip completed") + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "unzip", + path = zipPath, + successful = true, + details = "Successfully extracted $zipPath to $destPath" + ), + error = "" + ) + } + } finally { + if (process.isAlive) { + process.destroy() + } + } + } catch (e: Exception) { + AppLogger.w(TAG, "Device-side unzip failed for cmd: $cmd", e) + } + } + + // Create temporary files for processing - using external files directory + // for better + // permissions + val tempDir = context.getExternalFilesDir(null) ?: context.cacheDir + val tempZipFile = File(tempDir, "temp_zip_${System.currentTimeMillis()}.zip") + + try { + // Make sure the temp directory exists + tempDir.mkdirs() + + // Copy the zip file from device to temp file + val pullResult = + AndroidShellExecutor.executeShellCommand( + "cat ${shQuote(zipPath)} > ${shQuote(tempZipFile.absolutePath)}" + ) + if (!pullResult.success) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to read zip file: ${pullResult.stderr}" + ) + } + + // Log information about the temp ZIP file + AppLogger.d( + TAG, + "Temp ZIP file loaded at: ${tempZipFile.absolutePath}, size: ${tempZipFile.length()} bytes" + ) + + val totalEntries = try { + ZipFile(tempZipFile).use { it.size() } + } catch (_: Exception) { + null + } + var processedEntries = 0 + + // Extract files using ZipInputStream + val buffer = ByteArray(64 * 1024) + val zipInputStream = + ZipInputStream(BufferedInputStream(FileInputStream(tempZipFile))) + + try { + var zipEntry: ZipEntry? = zipInputStream.nextEntry + while (zipEntry != null) { + val fileName = zipEntry.name + if (fileName.startsWith("/") || fileName.contains("..") || fileName.contains("\\")) { + zipInputStream.closeEntry() + zipEntry = zipInputStream.nextEntry + continue + } + + val newFile = File(tempDir, fileName) + + val newFileCanonical = newFile.canonicalPath + val tempDirCanonical = tempDir.canonicalPath + File.separator + if (!newFileCanonical.startsWith(tempDirCanonical)) { + zipInputStream.closeEntry() + zipEntry = zipInputStream.nextEntry + continue + } + + // Skip directories, but make sure they exist + if (zipEntry.isDirectory) { + newFile.mkdirs() + val dirPath = "$destPath/$fileName" + AndroidShellExecutor.executeShellCommand("mkdir -p ${shQuote(dirPath)};") + zipInputStream.closeEntry() + zipEntry = zipInputStream.nextEntry + continue + } + + // Create parent directories if needed + val filePath = "$destPath/$fileName" + val parentDirPath = File(filePath).parent + if (parentDirPath != null) { + AndroidShellExecutor.executeShellCommand("mkdir -p ${shQuote(parentDirPath)};") + } + + newFile.parentFile?.mkdirs() + + // Extract file + val fileOutputStream = FileOutputStream(newFile) + + try { + var len: Int + while (zipInputStream.read(buffer).also { len = it } > 0) { + fileOutputStream.write(buffer, 0, len) + } + } finally { + fileOutputStream.close() + } + + // Copy the extracted file to device + val pushResult = + AndroidShellExecutor.executeShellCommand( + "cat ${shQuote(newFile.absolutePath)} > ${shQuote(filePath)}" + ) + if (!pushResult.success) { + AppLogger.w(TAG, "Failed to copy extracted file: $fileName to $filePath") + // Continue with next file + } + + // Clean up temp file + newFile.delete() + + zipInputStream.closeEntry() + processedEntries++ + val progress = + if (totalEntries != null && totalEntries > 0) { + (processedEntries.toFloat() / totalEntries.toFloat()).coerceIn(0f, 1f) + } else { + -1f + } + val msg = + if (totalEntries != null && totalEntries > 0) { + "Unzipping... ($processedEntries/$totalEntries)" + } else { + "Unzipping..." + } + ToolProgressBus.update(tool.name, progress, msg) + zipEntry = zipInputStream.nextEntry + } + } finally { + zipInputStream.close() + } + + ToolProgressBus.update(tool.name, 1f, "Unzip completed") + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "unzip", + path = zipPath, + successful = true, + details = "Successfully extracted $zipPath to $destPath" + ), + error = "" + ) + } finally { + tempZipFile.delete() + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error extracting zip file", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error extracting zip file: ${e.message}" + ) + } finally { + ToolProgressBus.clear() + } + } + + /** 打开文件 使用系统默认应用打开文件 */ + private suspend fun openFileWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.openFile(tool) + } + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + + if (isOperitInternalPath(path)) { + return super.openFile(tool) + } + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "open", + path = "", + successful = false, + details = "Must provide path parameter" + ), + error = "Must provide path parameter" + ) + } + + return try { + // 首先检查文件是否存在 + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -f '$path' && echo 'exists' || echo 'not exists'" + ) + if (existsResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "open", + path = path, + successful = false, + details = "File does not exist: $path" + ), + error = "File does not exist: $path" + ) + } + + // 获取文件MIME类型 + val mimeTypeResult = + AndroidShellExecutor.executeShellCommand("file --mime-type -b '$path'") + val mimeType = + if (mimeTypeResult.success) mimeTypeResult.stdout.trim() + else "application/octet-stream" + + // 使用Android intent打开文件 + val command = "am start -a android.intent.action.VIEW -d 'file://$path' -t '$mimeType'" + val result = AndroidShellExecutor.executeShellCommand(command) + + if (result.success) { + return ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "open", + path = path, + successful = true, + details = "Opened file with system app: $path" + ), + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "open", + path = path, + successful = false, + details = "Failed to open file: ${result.stderr}" + ), + error = "Failed to open file: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error opening file", e) + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "open", + path = path, + successful = false, + details = "Error opening file: ${e.message}" + ), + error = "Error opening file: ${e.message}" + ) + } + } + + /** 分享文件 调用系统分享功能 */ + private suspend fun shareFileWithShell(tool: AITool): ToolResult { + val environment = tool.parameters.find { it.name == "environment" }?.value + if (environment == "linux") { + return super.shareFile(tool) + } + val path = tool.parameters.find { it.name == "path" }?.value ?: "" + PathValidator.validateAndroidPath(path, tool.name)?.let { return it } + val title = tool.parameters.find { it.name == "title" }?.value ?: "Share File" + + if (isOperitInternalPath(path)) { + return super.shareFile(tool) + } + + if (path.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "share", + path = "", + successful = false, + details = "Must provide path parameter" + ), + error = "Must provide path parameter" + ) + } + + return try { + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -f ${shQuote(path)} && echo 'exists' || echo 'not exists'" + ) + if (existsResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "share", + path = path, + successful = false, + details = "File does not exist: $path" + ), + error = "File does not exist: $path" + ) + } + + val stagingRoot = (context.getExternalFilesDir(null) ?: context.cacheDir) + val stagingDir = File(stagingRoot, "share_tmp") + if (!stagingDir.exists()) { + stagingDir.mkdirs() + } + + val sourceName = File(path).name.ifBlank { "shared_file" } + val stagedFile = File(stagingDir, "${System.currentTimeMillis()}_$sourceName") + val copyResult = + AndroidShellExecutor.executeShellCommand( + "cat ${shQuote(path)} > ${shQuote(stagedFile.absolutePath)}" + ) + + if (!copyResult.success || !stagedFile.exists()) { + return ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "share", + path = path, + successful = false, + details = "Failed to prepare file for sharing: ${copyResult.stderr}" + ), + error = "Failed to prepare file for sharing: ${copyResult.stderr}" + ) + } + + val extension = stagedFile.extension.lowercase(Locale.US) + val mimeType = + if (extension.isNotEmpty()) { + MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) + ?: "application/octet-stream" + } else { + "application/octet-stream" + } + + val authority = "${context.packageName}.fileprovider" + val contentUri = FileProvider.getUriForFile(context, authority, stagedFile) + val shareIntent = + Intent(Intent.ACTION_SEND).apply { + type = mimeType + putExtra(Intent.EXTRA_STREAM, contentUri) + putExtra(Intent.EXTRA_SUBJECT, title) + clipData = + ClipData.newUri( + context.contentResolver, + stagedFile.name, + contentUri + ) + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + } + val chooserIntent = + Intent.createChooser(shareIntent, title).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + context.startActivity(chooserIntent) + + ToolResult( + toolName = tool.name, + success = true, + result = + FileOperationData( + operation = "share", + path = path, + successful = true, + details = "Opened share interface, sharing file: $path" + ), + error = "" + ) + } catch (e: ActivityNotFoundException) { + AppLogger.e(TAG, "No activity found to handle sharing file: $path", e) + ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "share", + path = path, + successful = false, + details = "No application found to share this file type." + ), + error = "No application found to share this file type." + ) + } catch (e: Exception) { + AppLogger.e(TAG, "Error sharing file", e) + ToolResult( + toolName = tool.name, + success = false, + result = + FileOperationData( + operation = "share", + path = path, + successful = false, + details = "Error sharing file: ${e.message}" + ), + error = "Error sharing file: ${e.message}" + ) + } + } + + /** 下载文件 从网络URL下载文件到指定路径 */ + private suspend fun downloadFileWithShell(tool: AITool): ToolResult { + return super.downloadFile(tool) + } + + /** Write base64 encoded content to a binary file */ + +// if (path.isBlank()) { +// return ToolResult( +// toolName = tool.name, +// success = false, +// result = +// FileOperationData( +// operation = "write_binary", +// path = "", +// successful = false, +// details = "Path parameter is required" +// ), +// error = "Path parameter is required" +// ) +// } + +// return try { +// // Ensure parent directory exists +// val directory = File(path).parent +// if (directory != null) { +// AndroidShellExecutor.executeShellCommand("mkdir -p '$directory'") +// } + +// // Write content using echo and base64 decode +// val writeResult = +// AndroidShellExecutor.executeShellCommand( +// "echo '$base64Content' | base64 -d > '$path'" +// ) + +// if (!writeResult.success) { +// return ToolResult( +// toolName = tool.name, +// success = false, +// result = +// FileOperationData( +// operation = "write_binary", +// path = path, +// successful = false, +// details = "Failed to write binary file: ${writeResult.stderr}" +// ), +// error = "Failed to write binary file: ${writeResult.stderr}" +// ) +// } + +// // Verify write was successful +// val sizeResult = +// AndroidShellExecutor.executeShellCommand("stat -c %s '$path' 2>/dev/null || echo '0'") +// val size = sizeResult.stdout.trim().toLongOrNull() ?: 0 +// val originalSize = +// android.util.Base64.decode(base64Content, android.util.Base64.NO_WRAP).size + +// if (size.toLong() != originalSize.toLong()) { +// return ToolResult( +// toolName = tool.name, +// success = false, +// result = +// FileOperationData( +// operation = "write_binary", +// path = path, +// successful = false, +// details = "Write completed but file size mismatch. Expected: $originalSize, Got: $size. Possible write failure." +// ), +// error = "Write completed but file size mismatch. Expected: $originalSize, Got: $size. Possible write failure." +// ) +// } + +// return ToolResult( +// toolName = tool.name, +// success = true, +// result = +// FileOperationData( +// operation = "write_binary", +// path = path, +// successful = true, +// details = "Binary content written to $path" +// ), +// error = "" +// ) +// } catch (e: Exception) { +// AppLogger.e(TAG, "Error writing binary file", e) +// return ToolResult( +// toolName = tool.name, +// success = false, +// result = +// FileOperationData( +// operation = "write_binary", +// path = path, +// successful = false, +// details = "Error writing binary file: ${e.message}" +// ), +// error = "Error writing binary file: ${e.message}" +// ) +// } +// } + + // 路由与具体操作放在同一工具中,避免通过历史权限等级继承改变分派。 -/** 管理员文件工具在每次操作前选择可用后端,复用现有标准和 Shell 实现。 */ -open class AdminFileSystemTools(context: Context) : DebuggerFileSystemTools(context) { private val standardTools = StandardFileSystemTools(context) private suspend fun route( @@ -25,53 +2947,53 @@ open class AdminFileSystemTools(context: Context) : DebuggerFileSystemTools(cont ) override suspend fun listFiles(tool: AITool): ToolResult = - route(true, { super.listFiles(tool) }, { standardTools.listFiles(tool) }) + route(true, { listFilesWithShell(tool) }, { standardTools.listFiles(tool) }) override suspend fun readFileFull(tool: AITool): ToolResult = - route(true, { super.readFileFull(tool) }, { standardTools.readFileFull(tool) }) + route(true, { readFileFullWithShell(tool) }, { standardTools.readFileFull(tool) }) override suspend fun readFile(tool: AITool): ToolResult = - route(true, { super.readFile(tool) }, { standardTools.readFile(tool) }) + route(true, { readFileWithShell(tool) }, { standardTools.readFile(tool) }) override suspend fun readFilePart(tool: AITool): ToolResult = - route(true, { super.readFilePart(tool) }, { standardTools.readFilePart(tool) }) + route(true, { readFilePartWithShell(tool) }, { standardTools.readFilePart(tool) }) override suspend fun fileExists(tool: AITool): ToolResult = - route(true, { super.fileExists(tool) }, { standardTools.fileExists(tool) }) + route(true, { fileExistsWithShell(tool) }, { standardTools.fileExists(tool) }) override suspend fun findFiles(tool: AITool): ToolResult = - route(true, { super.findFiles(tool) }, { standardTools.findFiles(tool) }) + route(true, { findFilesWithShell(tool) }, { standardTools.findFiles(tool) }) override suspend fun fileInfo(tool: AITool): ToolResult = - route(true, { super.fileInfo(tool) }, { standardTools.fileInfo(tool) }) + route(true, { fileInfoWithShell(tool) }, { standardTools.fileInfo(tool) }) override suspend fun writeFile(tool: AITool): ToolResult = - route(false, { super.writeFile(tool) }, { standardTools.writeFile(tool) }) + route(false, { writeFileWithShell(tool) }, { standardTools.writeFile(tool) }) override suspend fun deleteFile(tool: AITool): ToolResult = - route(false, { super.deleteFile(tool) }, { standardTools.deleteFile(tool) }) + route(false, { deleteFileWithShell(tool) }, { standardTools.deleteFile(tool) }) override suspend fun moveFile(tool: AITool): ToolResult = - route(false, { super.moveFile(tool) }, { standardTools.moveFile(tool) }) + route(false, { moveFileWithShell(tool) }, { standardTools.moveFile(tool) }) override suspend fun copyFile(tool: AITool): ToolResult = - route(false, { super.copyFile(tool) }, { standardTools.copyFile(tool) }) + route(false, { copyFileWithShell(tool) }, { standardTools.copyFile(tool) }) override suspend fun makeDirectory(tool: AITool): ToolResult = - route(false, { super.makeDirectory(tool) }, { standardTools.makeDirectory(tool) }) + route(false, { makeDirectoryWithShell(tool) }, { standardTools.makeDirectory(tool) }) override suspend fun zipFiles(tool: AITool): ToolResult = - route(false, { super.zipFiles(tool) }, { standardTools.zipFiles(tool) }) + route(false, { zipFilesWithShell(tool) }, { standardTools.zipFiles(tool) }) override suspend fun unzipFiles(tool: AITool): ToolResult = - route(false, { super.unzipFiles(tool) }, { standardTools.unzipFiles(tool) }) + route(false, { unzipFilesWithShell(tool) }, { standardTools.unzipFiles(tool) }) override suspend fun openFile(tool: AITool): ToolResult = - route(false, { super.openFile(tool) }, { standardTools.openFile(tool) }) + route(false, { openFileWithShell(tool) }, { standardTools.openFile(tool) }) override suspend fun shareFile(tool: AITool): ToolResult = - route(false, { super.shareFile(tool) }, { standardTools.shareFile(tool) }) + route(false, { shareFileWithShell(tool) }, { standardTools.shareFile(tool) }) override suspend fun downloadFile(tool: AITool): ToolResult = - route(false, { super.downloadFile(tool) }, { standardTools.downloadFile(tool) }) + route(false, { downloadFileWithShell(tool) }, { standardTools.downloadFile(tool) }) } diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminSystemOperationTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminSystemOperationTools.kt index c17312da43..101d5a2fe1 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminSystemOperationTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminSystemOperationTools.kt @@ -1,9 +1,526 @@ package com.ai.assistance.operit.core.tools.defaultTool.admin import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.debugger.DebuggerSystemOperationTools +import com.ai.assistance.operit.core.tools.AppOperationData +import com.ai.assistance.operit.core.tools.NotificationData +import com.ai.assistance.operit.core.tools.StringResultData +import com.ai.assistance.operit.core.tools.SystemSettingData +import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardSystemOperationTools +import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver +import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor +import com.ai.assistance.operit.data.model.AITool +import com.ai.assistance.operit.data.model.ToolResult +import com.ai.assistance.operit.util.logging.AppLogger -/** 管理员级别的系统操作工具,继承调试版本 */ -open class AdminSystemOperationTools(context: Context) : DebuggerSystemOperationTools(context) { - // 当前阶段不添加新功能,仅继承调试实现 +/** 管理员系统工具按现有授权能力执行 Shell 或标准系统操作。 */ +open class AdminSystemOperationTools(private val context: Context) : StandardSystemOperationTools(context) { + + private val TAG = "DebuggerSystemTools" + + override suspend fun modifySystemSetting(tool: AITool): ToolResult { + if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { + return super.modifySystemSetting(tool) + } + + val setting = tool.parameters.find { it.name == "setting" }?.value ?: "" + val value = tool.parameters.find { it.name == "value" }?.value ?: "" + val namespace = tool.parameters.find { it.name == "namespace" }?.value ?: "system" + + if (setting.isBlank() || value.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Must provide setting and value parameters" + ) + } + + val validNamespaces = listOf("system", "secure", "global") + if (!validNamespaces.contains(namespace)) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Namespace must be one of: ${validNamespaces.joinToString(", ")}" + ) + } + + return try { + val command = "settings put $namespace $setting $value" + val result = AndroidShellExecutor.executeShellCommand(command) + + if (result.success) { + val resultData = + SystemSettingData(namespace = namespace, setting = setting, value = value) + + return ToolResult( + toolName = tool.name, + success = true, + result = resultData, + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to set setting: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error modifying system setting", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error modifying system setting: ${e.message}" + ) + } + } + + override suspend fun getSystemSetting(tool: AITool): ToolResult { + if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { + return super.getSystemSetting(tool) + } + + val setting = tool.parameters.find { it.name == "setting" }?.value ?: "" + val namespace = tool.parameters.find { it.name == "namespace" }?.value ?: "system" + + if (setting.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Must provide setting parameter" + ) + } + + val validNamespaces = listOf("system", "secure", "global") + if (!validNamespaces.contains(namespace)) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Namespace must be one of: ${validNamespaces.joinToString(", ")}" + ) + } + + return try { + val command = "settings get $namespace $setting" + val result = AndroidShellExecutor.executeShellCommand(command) + + if (result.success) { + val resultData = + SystemSettingData( + namespace = namespace, + setting = setting, + value = result.stdout.trim() + ) + + return ToolResult( + toolName = tool.name, + success = true, + result = resultData, + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to get setting: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error getting system setting", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error getting system setting: ${e.message}" + ) + } + } + + override suspend fun installApp(tool: AITool): ToolResult { + if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { + return super.installApp(tool) + } + + val apkPath = tool.parameters.find { it.name == "path" }?.value ?: "" + + if (apkPath.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Must provide apk_path parameter" + ) + } + + if (AdminFileSystemTools.isOperitInternalPath(apkPath)) { + AppLogger.d( + TAG, + "installApp detected Operit internal path, using standard application access" + ) + return super.installApp(tool) + } + + val existsResult = + AndroidShellExecutor.executeShellCommand( + "test -f $apkPath && echo 'exists' || echo 'not exists'" + ) + if (existsResult.stdout.trim() != "exists") { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "APK file does not exist: $apkPath" + ) + } + + return try { + val command = "pm install -r $apkPath" + val result = AndroidShellExecutor.executeShellCommand(command) + + if (result.success && result.stdout.contains("Success")) { + val resultData = + AppOperationData( + operationType = "install", + packageName = apkPath, + success = true + ) + + return ToolResult( + toolName = tool.name, + success = true, + result = resultData, + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Installation failed: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error installing app", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error installing app: ${e.message}" + ) + } + } + + override suspend fun uninstallApp(tool: AITool): ToolResult { + if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { + return super.uninstallApp(tool) + } + + val packageName = tool.parameters.find { it.name == "package_name" }?.value ?: "" + val keepData = tool.parameters.find { it.name == "keep_data" }?.value?.toBoolean() ?: false + + if (packageName.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Must provide package_name parameter" + ) + } + + val checkCommand = "pm list packages | grep -c \"$packageName\"" + val checkResult = AndroidShellExecutor.executeShellCommand(checkCommand) + + if (checkResult.stdout.trim() == "0") { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "App not installed: $packageName" + ) + } + + return try { + val command = + if (keepData) { + "pm uninstall -k $packageName" + } else { + "pm uninstall $packageName" + } + + val result = AndroidShellExecutor.executeShellCommand(command) + + if (result.success && result.stdout.contains("Success")) { + val details = if (keepData) "(keep data)" else "" + val resultData = + AppOperationData( + operationType = "uninstall", + packageName = packageName, + success = true, + details = details + ) + + return ToolResult( + toolName = tool.name, + success = true, + result = resultData, + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Uninstallation failed: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error uninstalling app", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error uninstalling app: ${e.message}" + ) + } + } + + override suspend fun startApp(tool: AITool): ToolResult { + if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { + return super.startApp(tool) + } + + val packageName = tool.parameters.find { it.name == "package_name" }?.value ?: "" + val activity = tool.parameters.find { it.name == "activity" }?.value ?: "" + + if (packageName.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Must provide package_name parameter" + ) + } + + return try { + val command: String + if (activity.isBlank()) { + // 使用 am start 命令而不是 monkey,避免修改系统设置(如屏幕旋转) + // 先获取应用的主 Activity,然后使用 -n 参数启动 + val resolveCmd = "cmd package resolve-activity --brief $packageName 2>/dev/null | tail -n 1" + val resolveResult = AndroidShellExecutor.executeShellCommand(resolveCmd) + + if (resolveResult.success && resolveResult.stdout.isNotBlank()) { + val output = resolveResult.stdout.trim() + // resolve-activity 返回格式可能是:package/activity 或只有 activity + // 也可能返回多行,最后一行是组件名 + val lines = output.lines().filter { it.isNotBlank() && !it.startsWith("name=") } + val mainActivity = lines.lastOrNull()?.trim() ?: output.trim() + + // 如果返回的是完整组件名(package/activity),直接使用 + command = if (mainActivity.contains('/')) { + "am start -n $mainActivity" + } else { + // 如果只返回了 Activity 名,拼接包名 + "am start -n $packageName/$mainActivity" + } + AppLogger.d(TAG, "Resolved main Activity: $mainActivity, using command: $command") + } else { + // 如果无法解析 Activity,返回错误 + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Cannot resolve app main Activity. Please provide activity parameter or ensure app is properly installed. Package: $packageName" + ) + } + } else { + command = "am start -n $packageName/$activity" + } + + val result = AndroidShellExecutor.executeShellCommand(command) + + if (result.success) { + val details = if (activity.isNotBlank()) "Activity: $activity" else "" + val resultData = + AppOperationData( + operationType = "start", + packageName = packageName, + success = true, + details = details + ) + + return ToolResult( + toolName = tool.name, + success = true, + result = resultData, + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to start app: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error starting app", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error starting app: ${e.message}" + ) + } + } + + override suspend fun stopApp(tool: AITool): ToolResult { + if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { + return super.stopApp(tool) + } + + val packageName = tool.parameters.find { it.name == "package_name" }?.value ?: "" + + if (packageName.isBlank()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Must provide package_name parameter" + ) + } + + return try { + val command = "am force-stop $packageName" + val result = AndroidShellExecutor.executeShellCommand(command) + + if (result.success) { + val resultData = + AppOperationData( + operationType = "stop", + packageName = packageName, + success = true + ) + + return ToolResult( + toolName = tool.name, + success = true, + result = resultData, + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to stop app: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error stopping app", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error stopping app: ${e.message}" + ) + } + } + + override suspend fun getNotifications(tool: AITool): ToolResult { + if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { + return super.getNotifications(tool) + } + + val limit = tool.parameters.find { it.name == "limit" }?.value?.toIntOrNull() ?: 10 + val includeOngoing = + tool.parameters.find { it.name == "include_ongoing" }?.value?.toBoolean() ?: false + + return try { + val command = + if (includeOngoing) { + "dumpsys notification --noredact | grep -E 'pkg=|text=' | head -${limit * 2}" + } else { + "dumpsys notification --noredact | grep -v 'ongoing' | grep -E 'pkg=|text=' | head -${limit * 2}" + } + + val result = AndroidShellExecutor.executeShellCommand(command) + + if (result.success) { + val lines = result.stdout.split("\n") + val notifications = mutableListOf() + + var currentPackage = "" + var currentText = "" + + for (line in lines) { + when { + line.contains("pkg=") -> { + if (currentPackage.isNotEmpty() && currentText.isNotEmpty()) { + notifications.add( + NotificationData.Notification( + packageName = currentPackage, + text = currentText, + timestamp = System.currentTimeMillis() + ) + ) + currentText = "" + } + + val pkgMatch = Regex("pkg=(\\S+)").find(line) + currentPackage = pkgMatch?.groupValues?.getOrNull(1) ?: "" + } + line.contains("text=") -> { + val textMatch = Regex("text=(.+)").find(line) + currentText = textMatch?.groupValues?.getOrNull(1) ?: "" + } + } + } + + if (currentPackage.isNotEmpty() && currentText.isNotEmpty()) { + notifications.add( + NotificationData.Notification( + packageName = currentPackage, + text = currentText, + timestamp = System.currentTimeMillis() + ) + ) + } + + val resultData = + NotificationData( + notifications = notifications, + timestamp = System.currentTimeMillis() + ) + + return ToolResult( + toolName = tool.name, + success = true, + result = resultData, + error = "" + ) + } else { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to get notifications: ${result.stderr}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error getting notifications", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error getting notifications: ${e.message}" + ) + } + } } diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminUITools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminUITools.kt index 00f73d3118..e51a064513 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminUITools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminUITools.kt @@ -1,9 +1,2123 @@ package com.ai.assistance.operit.core.tools.defaultTool.admin +import android.annotation.SuppressLint +import android.content.ClipData +import android.content.ClipboardManager import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.debugger.DebuggerUITools +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import com.ai.assistance.operit.core.tools.SimplifiedUINode +import com.ai.assistance.operit.core.tools.StringResultData +import com.ai.assistance.operit.core.tools.UIActionResultData +import com.ai.assistance.operit.core.tools.UIPageResultData +import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardUITools +import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver +import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor +import com.ai.assistance.operit.core.tools.system.ShellIdentity +import com.ai.assistance.operit.core.tools.system.uiautomator.UiAutomatorDumpGuard +import com.ai.assistance.operit.data.model.AITool +import com.ai.assistance.operit.data.model.ToolResult +import com.ai.assistance.operit.data.repository.UIHierarchyManager +import com.ai.assistance.operit.util.files.OperitPaths +import com.ai.assistance.operit.util.logging.AppLogger +import com.ai.assistance.operit.util.media.ImagePoolManager +import java.io.File +import java.io.StringReader +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.withContext +import org.json.JSONObject +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserFactory -/** 管理员级别的UI工具,继承调试版本 */ -open class AdminUITools(context: Context) : DebuggerUITools(context) { - // 当前阶段不添加新功能,仅继承调试实现 +/** 管理员 UI 工具在一次操作前按实际授权选择无障碍或 Shell,Root 复用公共能力。 */ +open class AdminUITools(context: Context) : StandardUITools(context) { + + companion object { + private const val TAG = "AdminUITools" + private const val MAX_RETRY_COUNT = 3 + private const val RETRY_DELAY_MS = 300L + } + + protected open val uiShellIdentity: ShellIdentity? = null + + protected suspend fun executeUiShellCommand(command: String): AndroidShellExecutor.CommandResult { + // 读取页面和按元素点击共用入口;Root 子类也必须保存并恢复调用前的旋转设置。 + if (command.startsWith("uiautomator dump ")) { + return UiAutomatorDumpGuard.execute(command) { protectedCommand -> + AndroidShellExecutor.executeShellCommand(protectedCommand, uiShellIdentity) + } + } + return AndroidShellExecutor.executeShellCommand(command, uiShellIdentity) + } + + protected suspend fun shouldUseAccessibility(tool: AITool): Boolean = + !hasDisplayParam(tool) && PermissionCapabilityResolver.uiSnapshot(context).canUseAccessibility + + /** 是否包含 display 相关参数(有的话强制走 Shell,不走无障碍) */ + private fun hasDisplayParam(tool: AITool): Boolean { + return tool.parameters.any { param -> + param.name.equals("display", ignoreCase = true) + } + } + + private fun getDisplayArg(tool: AITool): String { + val display = tool.parameters.find { it.name.equals("display", ignoreCase = true) }?.value?.trim() + return if (!display.isNullOrEmpty()) "-d $display " else "" + } + + /** 使用Shell命令实现点击操作 */ + override suspend fun tap(tool: AITool): ToolResult { + if (shouldUseAccessibility(tool)) { + AppLogger.d(TAG, "无障碍服务已启用,使用无障碍点击") + return tapWithAccessibility(tool) + } + + val x = tool.parameters.find { it.name == "x" }?.value?.toIntOrNull() + val y = tool.parameters.find { it.name == "y" }?.value?.toIntOrNull() + + if (x == null || y == null) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = + "Missing or invalid coordinates. Both 'x' and 'y' must be valid integers." + ) + } + withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } + + // 使用Shell命令执行点击 + try { + AppLogger.d(TAG, "Attempting to tap at coordinates: ($x, $y) via shell command") + val command = "input ${getDisplayArg(tool)}tap $x $y" + val result = executeUiShellCommand(command) + + if (result.success) { + AppLogger.d(TAG, "Tap successful at coordinates: ($x, $y)") + withContext(Dispatchers.Main) { + operationOverlay.showTap(x, y) + operationOverlay.hide() + } + return ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "tap", + actionDescription = + "Successfully tapped at coordinates ($x, $y) via shell command", + coordinates = Pair(x, y) + ), + error = "" + ) + } else { + AppLogger.e(TAG, "Tap failed at coordinates: ($x, $y), error: ${result.stderr}") + withContext(Dispatchers.Main) { + operationOverlay.hide() // 隐藏反馈(在主线程上执行) + } + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = + "Failed to tap at coordinates ($x, $y): ${result.stderr ?: "Unknown error"}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error tapping at coordinates ($x, $y)", e) + withContext(Dispatchers.Main) { + operationOverlay.hide() // 隐藏反馈(在主线程上执行) + } + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error tapping at coordinates: ${e.message ?: "Unknown exception"}" + ) + } + } + + override suspend fun longPress(tool: AITool): ToolResult { + if (shouldUseAccessibility(tool)) { + AppLogger.d(TAG, "无障碍服务已启用,使用无障碍长按") + return longPressWithAccessibility(tool) + } + + val x = tool.parameters.find { it.name == "x" }?.value?.toIntOrNull() + val y = tool.parameters.find { it.name == "y" }?.value?.toIntOrNull() + + if (x == null || y == null) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Missing or invalid coordinates. Both 'x' and 'y' must be valid integers." + ) + } + withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } + + try { + AppLogger.d(TAG, "Attempting to long press at coordinates: ($x, $y) via shell command") + // Use swipe to simulate long press + val command = "input ${getDisplayArg(tool)}swipe $x $y $x $y 800" + val result = executeUiShellCommand(command) + + if (result.success) { + AppLogger.d(TAG, "Long press successful at coordinates: ($x, $y)") + withContext(Dispatchers.Main) { + operationOverlay.showTap(x, y) + operationOverlay.hide() + } + return ToolResult( + toolName = tool.name, + success = true, + result = UIActionResultData( + actionType = "long_press", + actionDescription = "Successfully long pressed at ($x, $y) via shell command", + coordinates = Pair(x, y) + ), + error = "" + ) + } else { + AppLogger.e(TAG, "Long press failed at coordinates: ($x, $y), error: ${result.stderr}") + withContext(Dispatchers.Main) { operationOverlay.hide() } + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to long press at coordinates ($x, $y): ${result.stderr ?: "Unknown error"}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error long pressing at coordinates ($x, $y)", e) + withContext(Dispatchers.Main) { operationOverlay.hide() } + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error long pressing at coordinates: ${e.message ?: "Unknown exception"}" + ) + } + } + + /** 使用Shell命令实现滑动操作 */ + override suspend fun swipe(tool: AITool): ToolResult { + if (shouldUseAccessibility(tool)) { + AppLogger.d(TAG, "无障碍服务已启用,使用无障碍滑动") + return swipeWithAccessibility(tool) + } + + val startX = tool.parameters.find { it.name == "start_x" }?.value?.toIntOrNull() + val startY = tool.parameters.find { it.name == "start_y" }?.value?.toIntOrNull() + val endX = tool.parameters.find { it.name == "end_x" }?.value?.toIntOrNull() + val endY = tool.parameters.find { it.name == "end_y" }?.value?.toIntOrNull() + val duration = tool.parameters.find { it.name == "duration" }?.value?.toIntOrNull() ?: 300 + + if (startX == null || startY == null || endX == null || endY == null) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = + "Missing or invalid coordinates. 'start_x', 'start_y', 'end_x', and 'end_y' must be valid integers." + ) + } + withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } + + try { + AppLogger.d( + TAG, + "Attempting to swipe from ($startX, $startY) to ($endX, $endY) with duration $duration ms via shell command" + ) + val command = "input ${getDisplayArg(tool)}swipe $startX $startY $endX $endY $duration" + val result = executeUiShellCommand(command) + + if (result.success) { + AppLogger.d(TAG, "Swipe successful from ($startX, $startY) to ($endX, $endY)") + withContext(Dispatchers.Main) { + operationOverlay.showSwipe(startX, startY, endX, endY) + operationOverlay.hide() + } + return ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "swipe", + actionDescription = + "Successfully performed swipe from ($startX, $startY) to ($endX, $endY) via shell command" + ), + error = "" + ) + } else { + AppLogger.e(TAG, "Swipe failed: ${result.stderr}") + withContext(Dispatchers.Main) { + operationOverlay.hide() // 隐藏反馈(在主线程上执行) + } + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to perform swipe: ${result.stderr ?: "Unknown error"}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error performing swipe", e) + withContext(Dispatchers.Main) { + operationOverlay.hide() // 隐藏反馈(在主线程上执行) + } + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error performing swipe: ${e.message ?: "Unknown exception"}" + ) + } + } + + /** 使用Shell命令点击元素 */ + override suspend fun clickElement(tool: AITool): ToolResult { + if (shouldUseAccessibility(tool)) { + AppLogger.d(TAG, "无障碍服务已启用,使用无障碍点击元素") + return clickElementWithAccessibility(tool) + } + + val resourceId = tool.parameters.find { it.name == "resourceId" }?.value + val className = tool.parameters.find { it.name == "className" }?.value + val contentDesc = tool.parameters.find { it.name == "contentDesc" }?.value + // index kept for future use + tool.parameters.find { it.name == "index" }?.value?.toIntOrNull() ?: 0 + val bounds = tool.parameters.find { it.name == "bounds" }?.value + + if (resourceId == null && className == null && bounds == null && contentDesc == null) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = + "Missing element identifier. Provide at least one of: 'resourceId', 'className', 'contentDesc', or 'bounds'." + ) + } + + // 如果提供了边界坐标,直接点击 + if (bounds != null) { + try { + // 解析边界坐标格式 [left,top][right,bottom] + val boundsPattern = "\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]".toRegex() + val matchResult = boundsPattern.find(bounds) + + if (matchResult == null || matchResult.groupValues.size < 5) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Invalid bounds format. Should be: [left,top][right,bottom]" + ) + } + + // 提取坐标 + val x1 = matchResult.groupValues[1].toInt() + val y1 = matchResult.groupValues[2].toInt() + val x2 = matchResult.groupValues[3].toInt() + val y2 = matchResult.groupValues[4].toInt() + + // 计算中心点 + val centerX = (x1 + x2) / 2 + val centerY = (y1 + y2) / 2 + + // 利用tap方法点击中心点 + val tapTool = + AITool( + name = "tap", + parameters = + listOf( + com.ai.assistance.operit.data.model.ToolParameter( + "x", + centerX.toString() + ), + com.ai.assistance.operit.data.model.ToolParameter( + "y", + centerY.toString() + ) + ) + ) + + return tap(tapTool) + } catch (e: Exception) { + AppLogger.e(TAG, "Error processing bounds", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error processing bounds: ${e.message}" + ) + } + } + + // 使用uiautomator获取和点击元素 + return clickElementWithUiautomator(tool) + } + + /** 使用Shell命令设置输入文本 */ + override suspend fun setInputText(tool: AITool): ToolResult { + if (shouldUseAccessibility(tool)) { + AppLogger.d(TAG, "无障碍服务已启用,使用无障碍设置文本") + return setInputTextWithAccessibility(tool) + } + + val text = tool.parameters.find { it.name == "text" }?.value ?: "" + + try { + // 获取屏幕中心作为文本输入的位置 + val displayMetrics = context.resources.displayMetrics + val centerX = displayMetrics.widthPixels / 2 + val centerY = displayMetrics.heightPixels / 2 + + // 显示文本输入反馈(在主线程上执行) + withContext(Dispatchers.Main) { operationOverlay.showTextInput(centerX, centerY, text) } + + // 使用KEYCODE_CLEAR清除字段,这比模拟CTRL+A和DEL更直接 + AppLogger.d(TAG, "Clearing text field with KEYCODE_CLEAR") + val clearCommand = "input ${getDisplayArg(tool)}keyevent KEYCODE_CLEAR" + executeUiShellCommand(clearCommand) + + // 短暂延迟 + kotlinx.coroutines.delay(300) + + // 如果文本为空,只需清除字段 + if (text.isEmpty()) { + // 成功后主动隐藏overlay + withContext(Dispatchers.Main) { operationOverlay.hide() } + return ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "textInput", + actionDescription = + "Successfully cleared input field via shell command" + ), + error = "" + ) + } + + // 使用原生复制和ADB粘贴来输入文本,这比'input text'更可靠 + AppLogger.d(TAG, "Setting text to clipboard and pasting via ADB: $text") + withContext(Dispatchers.Main) { + val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText("operit_input", text) + clipboard.setPrimaryClip(clip) + } + + // 短暂延迟以确保剪贴板操作完成 + kotlinx.coroutines.delay(100) + + // 执行粘贴命令 + val pasteCommand = "input ${getDisplayArg(tool)}keyevent KEYCODE_PASTE" + val pasteResult = executeUiShellCommand(pasteCommand) + + if (pasteResult.success) { + // 成功后主动隐藏overlay + withContext(Dispatchers.Main) { operationOverlay.hide() } + return ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "textInput", + actionDescription = + "Successfully set input text to: $text via clipboard paste" + ), + error = "" + ) + } else { + withContext(Dispatchers.Main) { + operationOverlay.hide() // 隐藏反馈(在主线程上执行) + } + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to paste text from clipboard: ${pasteResult.stderr ?: "Unknown error"}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error setting input text", e) + withContext(Dispatchers.Main) { + operationOverlay.hide() // 隐藏反馈(在主线程上执行) + } + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error setting input text: ${e.message ?: "Unknown exception"}" + ) + } + } + + /** 使用Shell命令实现按键操作 */ + override suspend fun pressKey(tool: AITool): ToolResult { + val keyCode = tool.parameters.find { it.name == "key_code" }?.value + + if (keyCode == null) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Missing 'key_code' parameter." + ) + } + + if (shouldUseAccessibility(tool) && + (accessibilityKeyAction(keyCode) != null || + !PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) + ) { + return pressKeyWithAccessibility(tool) + } + + val command = "input ${getDisplayArg(tool)}keyevent $keyCode" + + return try { + val result = executeUiShellCommand(command) + + if (result.success) { + ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "keyPress", + actionDescription = + "Successfully pressed key: $keyCode via shell command" + ), + error = "" + ) + } else { + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to press key: ${result.stderr ?: "Unknown error"}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error pressing key", e) + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error pressing key: ${e.message ?: "Unknown exception"}" + ) + } + } + + override suspend fun captureScreenshotToFile(tool: AITool): Pair?> { + if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { + return if (hasDisplayParam(tool)) Pair(null, null) else captureScreenshotToFileWithAccessibility(tool) + } + return try { + val screenshotDir = OperitPaths.cleanOnExitDir() + + val shortName = System.currentTimeMillis().toString().takeLast(4) + val file = File(screenshotDir, "$shortName.png") + + // 1) Debugger 模式下优先尝试 Shell 模式 (ADB) 截图 + AppLogger.d(TAG, "captureScreenshotToFile: Attempting shell screencap") + val command = "screencap -p ${file.absolutePath}" + val result = executeUiShellCommand(command) + + if (result.success && file.exists()) { + val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } + BitmapFactory.decodeFile(file.absolutePath, options) + val dimensions = if (options.outWidth > 0 && options.outHeight > 0) { + Pair(options.outWidth, options.outHeight) + } else { + null + } + AppLogger.d(TAG, "captureScreenshotToFile: Shell screencap success") + return Pair(file.absolutePath, dimensions) + } + + // 2) 如果 Shell 失败,作为回退尝试无障碍截图 (调用父类) + AppLogger.w(TAG, "captureScreenshotToFile: Shell screencap failed, falling back to accessibility") + if (hasDisplayParam(tool)) Pair(null, null) else captureScreenshotToFileWithAccessibility(tool) + } catch (e: Exception) { + AppLogger.e(TAG, "captureScreenshotToFile failed in Debugger", e) + Pair(null, null) + } + } + + override suspend fun captureScreenshot(tool: AITool): Pair?> { + return captureScreenshotToFile(tool) + } + + override suspend fun captureScreenshotBitmap(tool: AITool): Pair?> { + val (filePath, dimensions) = captureScreenshot(tool) + if (filePath == null) { + return Pair(null, dimensions) + } + + val bitmap = BitmapFactory.decodeFile(filePath) ?: return Pair(null, dimensions) + val resolvedDimensions = dimensions ?: Pair(bitmap.width, bitmap.height) + return Pair(bitmap, resolvedDimensions) + } + + /** 使用Shell命令获取页面信息 */ + override suspend fun getPageInfo(tool: AITool): ToolResult { + if (shouldUseAccessibility(tool)) { + AppLogger.d(TAG, "无障碍服务已启用,使用无障碍获取页面信息") + val result = getPageInfoWithAccessibility(tool) + if (result.success || !PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) return result + } + + val format = tool.parameters.find { it.name == "format" }?.value ?: "xml" + // detail kept for future use + tool.parameters.find { it.name == "detail" }?.value ?: "summary" + + if (format !in listOf("xml", "json")) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Invalid format specified. Must be 'xml' or 'json'." + ) + } + + return try { + // 获取UI数据 + val uiData = getUIDataFromShell(tool) + if (uiData == null) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to retrieve UI data." + ) + } + + // 解析当前窗口信息 + val focusInfo = extractFocusInfoFromShell(uiData.windowInfo) + + // 简化布局信息 + val simplifiedLayout = simplifyLayoutFromXml(uiData.uiXml) + + // 创建结构化数据 + val resultData = + UIPageResultData( + packageName = focusInfo.packageName ?: "Unknown", + activityName = focusInfo.activityName ?: "Unknown", + uiElements = simplifiedLayout + ) + + ToolResult(toolName = tool.name, success = true, result = resultData, error = "") + } catch (e: Exception) { + AppLogger.e(TAG, "Error getting page info", e) + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error getting page info: ${e.message}" + ) + } + } + + /** UI数据类,保存XML和窗口信息 */ + private data class UIData(val uiXml: String, val windowInfo: String) + + /** 获取UI数据,使用Shell命令,严格遵守工具参数中的 display(如有) */ + private suspend fun getUIDataFromShell(tool: AITool): UIData? { + return try { + // 使用ADB命令获取UI dump + AppLogger.d(TAG, "使用ADB命令获取UI数据") + + val displayId = tool.parameters + .find { it.name.equals("display", ignoreCase = true) } + ?.value + ?.trim() + ?.takeIf { it.isNotEmpty() } + + // 执行UI dump命令,只有在显式提供 display 参数时才使用 --display-id + val dumpResult = if (displayId != null) { + val cmd = "uiautomator dump --display-id $displayId /sdcard/window_dump.xml" + AppLogger.d(TAG, "UI dump using explicit display-id=$displayId") + executeUiShellCommand(cmd) + } else { + executeUiShellCommand("uiautomator dump /sdcard/window_dump.xml") + } + + if (!dumpResult.success) { + AppLogger.e(TAG, "uiautomator dump失败: ${dumpResult.stderr}") + return null + } + AppLogger.d(TAG, "uiautomator dump成功: ${dumpResult.stdout}") + + // 读取dump文件内容 + val readResult = executeUiShellCommand("cat /sdcard/window_dump.xml") + if (!readResult.success) { + AppLogger.e(TAG, "读取UI dump文件失败: ${readResult.stderr}") + return null + } + + // 获取窗口信息 + var windowInfo = getWindowInfoFromShell() + + // 如果窗口信息为空,尝试延迟后重试一次 + if (windowInfo.isEmpty()) { + AppLogger.w(TAG, "首次获取窗口信息失败,延迟500ms后重试") + kotlinx.coroutines.delay(500) + windowInfo = getWindowInfoFromShell() + } + + UIData(readResult.stdout, windowInfo) + } catch (e: Exception) { + AppLogger.e(TAG, "获取UI数据时出错", e) + null + } + } + + /** 获取窗口信息,使用多种命令尝试 */ + private suspend fun getWindowInfoFromShell(): String { + // 尝试多种命令来获取窗口信息 + val commands = + listOf( + // 标准命令,获取当前焦点和焦点应用 + "dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp'", + // 备用命令,只获取当前焦点 + "dumpsys window | grep -E 'mCurrentFocus'", + // 备用命令,只获取焦点应用 + "dumpsys window | grep -E 'mFocusedApp'", + // 最后的备用命令,尝试获取任何窗口信息 + "dumpsys window | grep -E 'Window #|Focus'", + // 极端情况下,尝试获取前台应用包名 + "dumpsys activity recents | grep 'Recent #0' -A2" + ) + + // 依次尝试每个命令,直到有一个成功 + for (command in commands) { + try { + val result = executeUiShellCommand(command) + if (result.success && result.stdout.isNotEmpty()) { + AppLogger.d(TAG, "成功获取窗口信息: ${result.stdout.take(100)}") + return result.stdout + } + // 如果命令执行失败或返回空结果,尝试下一个命令 + AppLogger.w(TAG, "窗口信息命令 '$command' 失败或返回空结果") + } catch (e: Exception) { + AppLogger.e(TAG, "执行窗口信息命令 '$command' 出错", e) + // 继续尝试下一个命令 + } + } + + // 所有命令都失败时,尝试获取topActivity作为最后的手段 + try { + val topActivityCommand = + "dumpsys activity activities | grep -E 'topResumedActivity|topActivity'" + val result = executeUiShellCommand(topActivityCommand) + if (result.success && result.stdout.isNotEmpty()) { + AppLogger.d(TAG, "使用topActivity作为窗口信息替代: ${result.stdout.take(100)}") + return result.stdout + } + } catch (e: Exception) { + AppLogger.e(TAG, "获取topActivity失败", e) + } + + AppLogger.e(TAG, "所有获取窗口信息的尝试均失败") + return "" + } + + /** UI节点数据类,仅在Shell实现中使用 */ + private data class UINodeShell( + val className: String?, + val text: String?, + val contentDesc: String?, + val resourceId: String?, + val bounds: String?, + val isClickable: Boolean, + val children: MutableList = mutableListOf() + ) + + /** 简化布局,从XML中提取UI元素,Shell版本 */ + private fun simplifyLayoutFromXml(xml: String): SimplifiedUINode { + val factory = XmlPullParserFactory.newInstance().apply { isNamespaceAware = false } + val parser = factory.newPullParser().apply { setInput(StringReader(xml)) } + + val nodeStack = mutableListOf() + var rootNode: UINodeShell? = null + + while (parser.eventType != XmlPullParser.END_DOCUMENT) { + when (parser.eventType) { + XmlPullParser.START_TAG -> { + if (parser.name == "node") { + val newNode = createNodeShell(parser) + if (rootNode == null) { + rootNode = newNode + nodeStack.add(newNode) + } else { + nodeStack.lastOrNull()?.children?.add(newNode) + nodeStack.add(newNode) + } + } + } + XmlPullParser.END_TAG -> { + if (parser.name == "node") { + nodeStack.removeLastOrNull() + } + } + } + parser.next() + } + + // 创建默认根节点,如果解析失败 + return rootNode?.toUINodeSimplified() + ?: SimplifiedUINode( + className = null, + text = null, + contentDesc = null, + resourceId = null, + bounds = null, + isClickable = false, + children = emptyList() + ) + } + + // 转换内部UINodeShell为SimplifiedUINode + private fun UINodeShell.toUINodeSimplified(): SimplifiedUINode { + return SimplifiedUINode( + className = className, + text = text, + contentDesc = contentDesc, + resourceId = resourceId, + bounds = bounds, + isClickable = isClickable, + children = children.map { it.toUINodeSimplified() } + ) + } + + private fun createNodeShell(parser: XmlPullParser): UINodeShell { + // 解析关键属性 + val className = parser.getAttributeValue(null, "class")?.substringAfterLast('.') + val text = parser.getAttributeValue(null, "text")?.replace(" ", "\n") + val contentDesc = parser.getAttributeValue(null, "content-desc") + val resourceId = parser.getAttributeValue(null, "resource-id") + val bounds = parser.getAttributeValue(null, "bounds") + val isClickable = parser.getAttributeValue(null, "clickable") == "true" + + return UINodeShell( + className = className, + text = text, + contentDesc = contentDesc, + resourceId = resourceId, + bounds = bounds, + isClickable = isClickable + ) + } + + /** 窗口焦点信息数据类 */ + private data class FocusInfoShell( + var packageName: String? = null, + var activityName: String? = null + ) + + /** 从窗口焦点数据中提取包名和活动名 */ + private fun extractFocusInfoFromShell(windowInfo: String): FocusInfoShell { + val result = FocusInfoShell() + + try { + if (windowInfo.isBlank()) { + AppLogger.w(TAG, "Window info is empty, cannot extract focus information") + // 即使窗口信息为空,也设置默认值,确保不会返回Unknown + result.packageName = "android" + result.activityName = "ForegroundActivity" + return result + } + + AppLogger.d(TAG, "Window info for extraction: ${windowInfo.take(200)}") + + // 尝试不同的提取方法,按照特异性顺序 + if (!extractFromCurrentFocusShell(windowInfo, result) && + !extractFromFocusedAppShell(windowInfo, result) && + !extractFromLauncherInfoShell(windowInfo, result) && + !extractFromTopActivityShell(windowInfo, result) && + !extractUsingGenericPatternsShell(windowInfo, result) + ) { + + AppLogger.w(TAG, "Could not extract focus information using any method") + } + + // 最后的回退:如果我们仍然无法确定任何信息,使用默认值 + if (result.packageName == null) { + if (windowInfo.contains("statusbar") || windowInfo.contains("SystemUI")) { + result.packageName = "com.android.systemui" + result.activityName = "SystemUI" + AppLogger.d(TAG, "Using SystemUI fallback") + } else if (windowInfo.contains("recents")) { + result.packageName = "com.android.systemui" + result.activityName = "Recents" + AppLogger.d(TAG, "Using Recents fallback") + } else { + result.packageName = "android" + result.activityName = "ForegroundActivity" + AppLogger.d(TAG, "Using last-resort fallback values") + } + } + + // 记录提取结果 + AppLogger.d( + TAG, + "Final extraction result - package: ${result.packageName}, activity: ${result.activityName}" + ) + } catch (e: Exception) { + AppLogger.e(TAG, "Error parsing window info", e) + // 确保即使出现异常,我们也有至少一些默认值 + if (result.packageName == null) result.packageName = "android" + if (result.activityName == null) result.activityName = "ForegroundActivity" + } + + return result + } + + /** + * 从mCurrentFocus格式提取 例如:mCurrentFocus=Window{1234567 u0 + * com.example.app/com.example.app.MainActivity} + */ + private fun extractFromCurrentFocusShell(windowInfo: String, result: FocusInfoShell): Boolean { + // 尝试多种mCurrentFocus格式模式 + val currentFocusPatterns = + listOf( + // 标准格式,具有包/活动(同时也支持 mFocusedWindow) + "(?:mCurrentFocus|mFocusedWindow)=.*?\\{.*?\\s+([a-zA-Z0-9_.]+)/([^\\s}]+)".toRegex(), + // 有时会看到的替代格式 + "(?:mCurrentFocus|mFocusedWindow)=.*?\\s+([a-zA-Z0-9_.]+)/([^\\s}]+)\\}".toRegex(), + // 只有包名的格式(活动将单独处理) + "(?:mCurrentFocus|mFocusedWindow)=.*?\\{.*?\\s+([a-zA-Z0-9_.]+)(?:/|\\s)".toRegex() + ) + + for (pattern in currentFocusPatterns) { + val match = pattern.find(windowInfo) + if (match != null) { + if (match.groupValues.size >= 3) { + // 包含包和活动的模式 + result.packageName = match.groupValues[1] + result.activityName = match.groupValues[2] + AppLogger.d(TAG, "Extracted from mCurrentFocus pattern (full): ${pattern.pattern}") + return true + } else if (match.groupValues.size >= 2) { + // 只有包名的模式 + result.packageName = match.groupValues[1] + AppLogger.d(TAG, "Extracted package from mCurrentFocus pattern: ${pattern.pattern}") + // 返回false以允许其他方法提取活动名称 + return false + } + } + } + return false + } + + /** + * 从mFocusedApp格式提取 例如:mFocusedApp=AppWindowToken{token=Token{12345 ActivityRecord{67890 u0 + * com.example.app/.MainActivity t123}}} + */ + private fun extractFromFocusedAppShell(windowInfo: String, result: FocusInfoShell): Boolean { + // mFocusedApp格式的多种模式 + val focusedAppPatterns = + listOf( + // 带有ActivityRecord的标准格式 + "mFocusedApp=.*?ActivityRecord\\{.*?\\s+([a-zA-Z0-9_.]+)/\\.?([^\\s}]+)".toRegex(), + // 处理类似于 mFocusedApp=null 后的真实输出行 + "ActivityRecord\\{.*?\\s+([a-zA-Z0-9_.]+)/\\.?([^\\s}]+)".toRegex(), + // 有时会看到的替代格式 + "mFocusedApp=.*?\\s+([a-zA-Z0-9_.]+)/\\.?([^\\s}]+)\\s".toRegex(), + // 只有包名的格式 + "mFocusedApp=.*?\\s+([a-zA-Z0-9_.]+)(?:/|\\s)".toRegex() + ) + + for (pattern in focusedAppPatterns) { + val match = pattern.find(windowInfo) + if (match != null) { + if (match.groupValues.size >= 3) { + // 包含包和活动的完全匹配 + result.packageName = match.groupValues[1] + result.activityName = match.groupValues[2] + AppLogger.d(TAG, "Extracted from mFocusedApp pattern (full): ${pattern.pattern}") + return true + } else if (match.groupValues.size >= 2) { + // 只有包的部分匹配 + result.packageName = match.groupValues[1] + AppLogger.d(TAG, "Extracted package from mFocusedApp pattern: ${pattern.pattern}") + // 返回false以允许通过其他方法提取活动名称 + return false + } + } + } + return false + } + + /** 为启动器窗口提取信息 例如:mCurrentFocus=Window{1a23bc4 u0 Launcher} */ + private fun extractFromLauncherInfoShell(windowInfo: String, result: FocusInfoShell): Boolean { + // 查找启动器特定模式 + if (windowInfo.contains("mCurrentFocus") && windowInfo.contains("Launcher")) { + val launcherPatterns = + listOf( + "\\{.*?\\s+([a-zA-Z0-9_.]+\\.launcher)/".toRegex(), + "\\{.*?\\s+([a-zA-Z0-9_.]+\\.home)/".toRegex(), + "\\{.*?\\s+Launcher\\}".toRegex() + ) + + for (pattern in launcherPatterns) { + val match = pattern.find(windowInfo) + if (match != null && match.groupValues.size >= 2) { + result.packageName = match.groupValues[1] + result.activityName = "Launcher" + AppLogger.d(TAG, "Extracted launcher info") + return true + } + } + + // 如果我们检测到Launcher但无法提取特定的包, + // 使用默认的启动器包和名称 + result.packageName = "com.android.launcher3" + result.activityName = "Launcher" + AppLogger.d(TAG, "Using default launcher info") + return true + } + return false + } + + /** + * 从topActivity/topResumedActivity输出格式提取 + * 例如:topActivity=ComponentInfo{com.example.app/.MainActivity} + */ + private fun extractFromTopActivityShell(windowInfo: String, result: FocusInfoShell): Boolean { + // topActivity格式的模式 + val topActivityPatterns = + listOf( + "topActivity=ComponentInfo\\{([a-zA-Z0-9_.]+)/\\.?([^}]+)\\}".toRegex(), + "topResumedActivity=ComponentInfo\\{([a-zA-Z0-9_.]+)/\\.?([^}]+)\\}".toRegex(), + "ResumedActivity:\\s+\\{([a-zA-Z0-9_.]+)/\\.?([^\\s}]+)".toRegex() + ) + + for (pattern in topActivityPatterns) { + val match = pattern.find(windowInfo) + if (match != null && match.groupValues.size >= 3) { + result.packageName = match.groupValues[1] + result.activityName = match.groupValues[2] + AppLogger.d(TAG, "Extracted from topActivity pattern: ${pattern.pattern}") + return true + } + } + + // 还要查找Recent tasks格式 + val recentPattern = "Recent #0.*?\\{([a-zA-Z0-9_.]+)/\\.?([^\\s}]+)".toRegex() + val recentMatch = recentPattern.find(windowInfo) + if (recentMatch != null && recentMatch.groupValues.size >= 3) { + result.packageName = recentMatch.groupValues[1] + result.activityName = recentMatch.groupValues[2] + AppLogger.d(TAG, "Extracted from Recent tasks pattern") + return true + } + + return false + } + + /** 作为后备使用更通用的模式提取 */ + private fun extractUsingGenericPatternsShell( + windowInfo: String, + result: FocusInfoShell + ): Boolean { + var foundAny = false + + // 尝试用各种模式提取包名 + if (result.packageName == null) { + // 查找常见的包模式,如com.android.something + val packagePatterns = + listOf( + "\\s([a-zA-Z][a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+){2,})/".toRegex(), // com.example.app/ + "\\s([a-zA-Z][a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+){2,})\\s".toRegex(), // com.example.app (空格后) + "([a-zA-Z][a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+){2,})".toRegex() // 只查找任何包名类似的名称 + ) + + for (pattern in packagePatterns) { + val match = pattern.find(windowInfo) + if (match != null && match.groupValues.size >= 2) { + val potentialPackage = match.groupValues[1] + // 验证这看起来像一个真实的包(避免匹配随机字符串) + if (potentialPackage.split(".").size >= 3 && + !potentialPackage.contains("@") && + !potentialPackage.startsWith("1") && + !potentialPackage.startsWith("0") + ) { + + result.packageName = potentialPackage + foundAny = true + AppLogger.d(TAG, "Found package name using fallback pattern: ${pattern.pattern}") + break + } + } + } + } + + // 如果我们还没有活动名称,尝试提取它 + if (result.activityName == null) { + // 查找活动名称模式 + val activityPatterns = + listOf( + "/\\.?([A-Z][a-zA-Z0-9_]+Activity)".toRegex(), // /.MainActivity or + // /MainActivity + "/([^\\s/}]+)".toRegex(), // 斜杠后的任何段 + "\\.([A-Z][a-zA-Z0-9_]+)".toRegex() // .MainActivity + ) + + for (pattern in activityPatterns) { + val match = pattern.find(windowInfo) + if (match != null && match.groupValues.size >= 2) { + val activityName = match.groupValues[1] + // 验证它看起来像一个活动名称(以大写字母开头) + if (activityName.isNotEmpty() && + activityName[0].isUpperCase() && + !activityName.contains("@") + ) { + + result.activityName = activityName + foundAny = true + AppLogger.d(TAG, "Found activity name using fallback pattern: ${pattern.pattern}") + break + } + } + } + } + + // 特殊情况处理:如果我们有包名但没有活动名称 + if (result.packageName != null && result.activityName == null) { + // 尝试根据包猜测主活动名称 + val packageParts = result.packageName!!.split(".") + if (packageParts.isNotEmpty()) { + val lastPart = packageParts.last().replaceFirstChar { if (it.isLowerCase()) it.titlecase(java.util.Locale.getDefault()) else it.toString() } + result.activityName = "${lastPart}Activity" + AppLogger.d(TAG, "Guessed activity name from package: ${result.activityName}") + foundAny = true + } + } + + // 如果我们找到了包或活动,将其视为部分成功 + return foundAny + } + + + + /** 使用uiautomator点击元素 */ + private suspend fun clickElementWithUiautomator(tool: AITool): ToolResult { + AppLogger.d(TAG, "Using uiautomator to click element") + + val resourceId = tool.parameters.find { it.name == "resourceId" }?.value + val className = tool.parameters.find { it.name == "className" }?.value + val contentDesc = tool.parameters.find { it.name == "contentDesc" }?.value + val index = tool.parameters.find { it.name == "index" }?.value?.toIntOrNull() ?: 0 + val partialMatch = + tool.parameters.find { it.name == "partialMatch" }?.value?.toBoolean() ?: false + + try { + // 先尝试获取UI dump + AppLogger.d(TAG, "Dumping UI hierarchy to find element") + val dumpCommand = "uiautomator dump /sdcard/window_dump.xml" + val result = executeUiShellCommand(dumpCommand) + + if (!result.success) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to dump UI hierarchy: ${result.stderr ?: "Unknown error"}" + ) + } + + // 读取dump文件 + val readCommand = "cat /sdcard/window_dump.xml" + val readResult = executeUiShellCommand(readCommand) + + if (!readResult.success) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to read UI dump: ${readResult.stderr ?: "Unknown error"}" + ) + } + + val xml = readResult.stdout + + // 使用XML Parser查找匹配的元素(取代有问题的正则方式) + val hasSelectors = resourceId != null || className != null || contentDesc != null + if (!hasSelectors) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "No element selector provided." + ) + } + + // 用XmlPullParser逐节点匹配,避免正则跨节点匹配的问题 + data class MatchedNode(val bounds: String?) + val matchingNodes = mutableListOf() + + try { + val factory = XmlPullParserFactory.newInstance().apply { isNamespaceAware = false } + val parser = factory.newPullParser().apply { setInput(StringReader(xml)) } + + while (parser.eventType != XmlPullParser.END_DOCUMENT) { + if (parser.eventType == XmlPullParser.START_TAG && parser.name == "node") { + val actualId = parser.getAttributeValue(null, "resource-id") + val actualClass = parser.getAttributeValue(null, "class") + val actualDesc = parser.getAttributeValue(null, "content-desc") + val actualBounds = parser.getAttributeValue(null, "bounds") + + var matches = true + + if (resourceId != null) { + if (actualId == null) { + matches = false + } else if (partialMatch) { + matches = actualId.contains(resourceId) + } else { + // 支持短ID (expand_search) 和完整ID (tv.danmaku.bili:id/expand_search) + matches = actualId == resourceId || actualId.endsWith(":id/$resourceId") + } + } + + if (matches && className != null) { + if (actualClass == null) { + matches = false + } else if (partialMatch) { + matches = actualClass.contains(className) + } else { + // 支持短类名 (ImageView) 和完整类名 (android.widget.ImageView) + matches = actualClass == className || actualClass.endsWith(".$className") + } + } + + if (matches && contentDesc != null) { + if (actualDesc == null) { + matches = false + } else if (partialMatch) { + matches = actualDesc.contains(contentDesc, ignoreCase = true) + } else { + matches = actualDesc.equals(contentDesc, ignoreCase = true) + } + } + + if (matches) { + matchingNodes.add(MatchedNode(bounds = actualBounds)) + } + } + parser.next() + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error parsing UI XML", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to parse UI hierarchy XML: ${e.message}" + ) + } + + if (matchingNodes.isEmpty()) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "No matching element found." + ) + } + + if (index < 0 || index >= matchingNodes.size) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = + "Index out of range. Found ${matchingNodes.size} elements, but requested index $index." + ) + } + + // 获取指定索引的节点bounds + val nodeBounds = matchingNodes[index].bounds + if (nodeBounds == null) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Target element has no bounds." + ) + } + + // 提取边界坐标 + val boundsPattern = "\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]".toRegex() + val boundsMatch = boundsPattern.find(nodeBounds) + if (boundsMatch == null || boundsMatch.groupValues.size < 5) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to extract bounds from the element: $nodeBounds" + ) + } + + // 提取坐标 + val x1 = boundsMatch.groupValues[1].toInt() + val y1 = boundsMatch.groupValues[2].toInt() + val x2 = boundsMatch.groupValues[3].toInt() + val y2 = boundsMatch.groupValues[4].toInt() + + // 计算中心点 + val centerX = (x1 + x2) / 2 + val centerY = (y1 + y2) / 2 + + withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } + + val tapCommand = "input tap $centerX $centerY" + val tapResult = executeUiShellCommand(tapCommand) + + if (tapResult.success) { + val identifierDescription = + when { + resourceId != null -> " with resource ID: $resourceId" + contentDesc != null -> " with content description: $contentDesc" + else -> " with class name: $className" + } + + val matchCount = + if (matchingNodes.size > 1) { + " (index $index of ${matchingNodes.size} matches)" + } else "" + + withContext(Dispatchers.Main) { + operationOverlay.showTap(centerX, centerY) + operationOverlay.hide() + } + return ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "click", + actionDescription = + "Successfully clicked element$identifierDescription$matchCount at coordinates ($centerX, $centerY) via shell command", + coordinates = Pair(centerX, centerY), + elementId = resourceId ?: className ?: contentDesc + ), + error = "" + ) + } else { + withContext(Dispatchers.Main) { + operationOverlay.hide() + } + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to click element: ${tapResult.stderr ?: "Unknown error"}" + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error clicking element with uiautomator", e) + withContext(Dispatchers.Main) { + operationOverlay.hide() + } + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error clicking element: ${e.message ?: "Unknown exception"}" + ) + } finally { + // 清理临时文件 + try { + Runtime.getRuntime().exec("rm /sdcard/window_dump.xml") + } catch (cleanupEx: Exception) { + AppLogger.e(TAG, "Error cleaning up temp file", cleanupEx) + } + } + } + + /** 从边界字符串提取中心坐标 返回中心点坐标,或null如果格式无效 */ + protected fun extractCenterCoordinates(bounds: String): Pair? { + val boundsPattern = "\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]".toRegex() + val matchResult = boundsPattern.find(bounds) ?: return null + + if (matchResult.groupValues.size < 5) return null + + // 提取坐标 + val x1 = matchResult.groupValues[1].toInt() + val y1 = matchResult.groupValues[2].toInt() + val x2 = matchResult.groupValues[3].toInt() + val y2 = matchResult.groupValues[4].toInt() + + // 计算并返回中心点 + val centerX = (x1 + x2) / 2 + val centerY = (y1 + y2) / 2 + + return Pair(centerX, centerY) + } + + // 无障碍是管理员的执行能力,以下方法不再形成独立权限等级。 + + + + /** + * 检查无障碍服务是否正在运行 + */ + private suspend fun isAccessibilityServiceEnabled(): Boolean { + return UIHierarchyManager.isAccessibilityServiceEnabled(context) + } + + /** + * 为需要无障碍服务的工具创建一个前置检查的包装器 + */ + private suspend fun withAccessibilityCheck(tool: AITool, block: suspend () -> T): T { + if (!isAccessibilityServiceEnabled()) { + throw IllegalStateException("Accessibility Service is not enabled. Please enable it in system settings to use this feature.") + } + return block() + } + + /** + * 获取UI层次结构,失败时重试 + * @return UI层次结构XML字符串,获取失败返回空字符串 + */ + private suspend fun getUIHierarchyWithRetry(): String { + var retryCount = 0 + var uiXml = "" + + while (retryCount < MAX_RETRY_COUNT) { + uiXml = UIHierarchyManager.getUIHierarchy(context) + if (uiXml.isNotEmpty()) { + return uiXml + } + + retryCount++ + if (retryCount < MAX_RETRY_COUNT) { + AppLogger.d(TAG, "获取UI层次结构失败,正在重试 #$retryCount") + delay(RETRY_DELAY_MS) + } + } + + AppLogger.w(TAG, "获取UI层次结构失败,已重试${MAX_RETRY_COUNT}次") + return uiXml + } + + /** Gets the current UI page/window information */ + private suspend fun getPageInfoWithAccessibility(tool: AITool): ToolResult { + return try { + withAccessibilityCheck(tool) { + val format = tool.parameters.find { it.name == "format" }?.value ?: "xml" + val detail = tool.parameters.find { it.name == "detail" }?.value ?: "summary" + + if (format !in listOf("xml", "json")) { + return@withAccessibilityCheck ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Invalid format specified. Must be 'xml' or 'json'." + ) + } + + // 使用无障碍服务获取UI数据(带重试) + val uiXml = getUIHierarchyWithRetry() + if (uiXml.isEmpty()) { + return@withAccessibilityCheck ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to retrieve UI data via accessibility service." + ) + } + + // 解析当前窗口信息 + val focusInfo = extractFocusInfoFromAccessibility() + + // 简化布局信息 + val simplifiedLayout = simplifyLayout(uiXml) + + // 创建结构化数据 + val resultData = + UIPageResultData( + packageName = focusInfo.packageName ?: "Unknown", + activityName = focusInfo.activityName ?: "Unknown", + uiElements = simplifiedLayout + ) + + ToolResult(toolName = tool.name, success = true, result = resultData, error = "") + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error getting page info", e) + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error getting page info: ${e.message}" + ) + } + } + + /** 从无障碍服务获取焦点信息 */ + private suspend fun extractFocusInfoFromAccessibility(): FocusInfo { + val focusInfo = FocusInfo() + try { + // 1. 获取UI层次结构的XML快照(带重试) + val hierarchyXml = getUIHierarchyWithRetry() + if (hierarchyXml.isEmpty()) { + AppLogger.w(TAG, "无法获取UI层次结构XML,使用默认值。") + focusInfo.packageName = "android" + // 即使XML获取失败,仍然尝试获取Activity名称 + focusInfo.activityName = UIHierarchyManager.getCurrentActivityName(context) ?: "ForegroundActivity" + return focusInfo + } + + // 2. 从XML中解析包名 + val (packageName, _) = UIHierarchyManager.extractWindowInfo(hierarchyXml) + // 3. 从服务中直接获取当前Activity名称 + val activityName = UIHierarchyManager.getCurrentActivityName(context) + + focusInfo.packageName = packageName + focusInfo.activityName = activityName // 使用从服务获取的Activity名称 + + // 如果没有获取到,使用默认值 + if (focusInfo.packageName == null) focusInfo.packageName = "android" + if (focusInfo.activityName == null) focusInfo.activityName = "ForegroundActivity" + } catch (e: Exception) { + AppLogger.e(TAG, "从XML解析焦点信息时出错", e) + // 设置默认值 + focusInfo.packageName = "android" + focusInfo.activityName = "ForegroundActivity" + } + return focusInfo + } + + /** 简化XML布局为节点树 */ + fun simplifyLayout(xml: String): SimplifiedUINode { + val factory = XmlPullParserFactory.newInstance().apply { isNamespaceAware = false } + val parser = factory.newPullParser().apply { setInput(StringReader(xml)) } + + val nodeStack = mutableListOf() + var rootNode: UINode? = null + + while (parser.eventType != XmlPullParser.END_DOCUMENT) { + when (parser.eventType) { + XmlPullParser.START_TAG -> { + if (parser.name == "node") { + val newNode = createNode(parser) + if (rootNode == null) { + rootNode = newNode + nodeStack.add(newNode) + } else { + nodeStack.lastOrNull()?.children?.add(newNode) + nodeStack.add(newNode) + } + } + } + XmlPullParser.END_TAG -> { + if (parser.name == "node") { + nodeStack.removeLastOrNull() + } + } + } + parser.next() + } + + return rootNode?.toUINode() + ?: SimplifiedUINode( + className = null, + text = null, + contentDesc = null, + resourceId = null, + bounds = null, + isClickable = false, + children = emptyList() + ) + } + + private fun createNode(parser: XmlPullParser): UINode { + // 解析关键属性 + val className = parser.getAttributeValue(null, "class")?.substringAfterLast('.') + val text = parser.getAttributeValue(null, "text")?.replace(" ", "\n") + val contentDesc = parser.getAttributeValue(null, "content-desc") + val resourceId = parser.getAttributeValue(null, "resource-id") + val bounds = parser.getAttributeValue(null, "bounds") + val isClickable = parser.getAttributeValue(null, "clickable") == "true" + + return UINode( + className = className, + text = text, + contentDesc = contentDesc, + resourceId = resourceId, + bounds = bounds, + isClickable = isClickable + ) + } + + /** 点击元素 */ + private suspend fun clickElementWithAccessibility(tool: AITool): ToolResult { + return try { + withAccessibilityCheck(tool) { + val resourceId = tool.parameters.find { it.name == "resourceId" }?.value + val className = tool.parameters.find { it.name == "className" }?.value + val contentDesc = tool.parameters.find { it.name == "contentDesc" }?.value + val index = tool.parameters.find { it.name == "index" }?.value?.toIntOrNull() ?: 0 + val bounds = tool.parameters.find { it.name == "bounds" }?.value + + if (resourceId == null && className == null && bounds == null && contentDesc == null) { + return@withAccessibilityCheck ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Missing element identifier. Provide at least one of 'resourceId', 'className', 'contentDesc', or 'bounds'." + ) + } + + // 如果提供了边界坐标,直接解析并点击中心点 + if (bounds != null) { + return@withAccessibilityCheck handleClickByBounds(tool, bounds) + } + + // 获取UI层次结构XML(带重试) + val uiXml = getUIHierarchyWithRetry() + if (uiXml.isEmpty()) { + return@withAccessibilityCheck ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "Unable to get UI hierarchy.") + } + + // 在XML中查找匹配的节点 + val matchedNodes = findNodesInXml(uiXml) { parser -> + val hasSelectors = resourceId != null || className != null || contentDesc != null + if (!hasSelectors) { + return@findNodesInXml false + } + + val actualId = parser.getAttributeValue(null, "resource-id") + val actualClass = parser.getAttributeValue(null, "class") + val actualDesc = parser.getAttributeValue(null, "content-desc") + + if(resourceId != null && (actualId == null || !actualId.endsWith(resourceId))){ + return@findNodesInXml false + } + + if(className != null && (actualClass == null || actualClass != className)){ + return@findNodesInXml false + } + + if(contentDesc != null && (actualDesc == null || !actualDesc.equals(contentDesc, ignoreCase = true))){ + return@findNodesInXml false + } + + true + } + + if (matchedNodes.isEmpty()) { + return@withAccessibilityCheck ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "No matching element found.") + } + + // 检查索引是否有效 + if (index < 0 || index >= matchedNodes.size) { + return@withAccessibilityCheck ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Index out of range. Found ${matchedNodes.size} elements, but requested index $index." + ) + } + + // 获取目标节点的bounds + val targetNodeBounds = matchedNodes[index].bounds + if (targetNodeBounds == null) { + return@withAccessibilityCheck ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "Target element has no bounds.") + } + + // 解析bounds并点击 + handleClickByBounds(tool, targetNodeBounds) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error clicking element", e) + operationOverlay.hide() + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error clicking element: ${e.message}" + ) + } + } + + private suspend fun handleClickByBounds(tool: AITool, bounds: String): ToolResult { + try { + val rect = parseBounds(bounds) + if (rect.isEmpty) { + return ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "Invalid bounds format: $bounds") + } + + val centerX = rect.centerX() + val centerY = rect.centerY() + + withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } + val clickSuccess = performAccessibilityClick(centerX, centerY) + + return if (clickSuccess) { + withContext(Dispatchers.Main) { + operationOverlay.showTap(centerX, centerY) + operationOverlay.hide() + } + ToolResult( + toolName = tool.name, + success = true, + result = UIActionResultData( + actionType = "click", + actionDescription = "Successfully clicked at bounds $bounds", + coordinates = Pair(centerX, centerY) + ) + ) + } else { + operationOverlay.hide() + ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "Failed to click at bounds $bounds via accessibility service.") + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error clicking by bounds", e) + operationOverlay.hide() + return ToolResult(toolName = tool.name, success = false, result = StringResultData(""), error = "Error clicking at bounds: ${e.message}") + } + } + + private fun findNodesInXml(xml: String, predicate: (parser: XmlPullParser) -> Boolean): List { + val matchedNodes = mutableListOf() + val factory = XmlPullParserFactory.newInstance().apply { isNamespaceAware = false } + val parser = factory.newPullParser().apply { setInput(StringReader(xml)) } + + while (parser.eventType != XmlPullParser.END_DOCUMENT) { + if (parser.eventType == XmlPullParser.START_TAG && parser.name == "node") { + if (predicate(parser)) { + matchedNodes.add( + NodeInfo( + bounds = parser.getAttributeValue(null, "bounds"), + text = parser.getAttributeValue(null, "text") + ) + ) + } + } + parser.next() + } + return matchedNodes + } + + private data class NodeInfo(val bounds: String?, val text: String?) + + /** 设置输入文本 */ + private suspend fun setInputTextWithAccessibility(tool: AITool): ToolResult { + return try { + withAccessibilityCheck(tool) { + val text = tool.parameters.find { it.name == "text" }?.value ?: "" + + // 通过UIHierarchyManager请求远程服务找到焦点节点的ID + val focusedNodeId = UIHierarchyManager.findFocusedNodeId(context) + if (focusedNodeId.isNullOrEmpty()) { + return@withAccessibilityCheck ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "No focused editable field found." + ) + } + + // 显示反馈 + val rect = parseBounds(focusedNodeId) + if (!rect.isEmpty) { + operationOverlay.showTextInput(rect.centerX(), rect.centerY(), text) + } + + // 通过UIHierarchyManager请求远程服务设置文本 + val result = UIHierarchyManager.setTextOnNode(context, focusedNodeId, text) + + if (result) { + // 成功后主动隐藏overlay + operationOverlay.hide() + ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "textInput", + actionDescription = + "Successfully set input text via accessibility service" + ), + error = "" + ) + } else { + operationOverlay.hide() + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to set text via accessibility service." + ) + } + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error setting input text", e) + operationOverlay.hide() + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error setting input text: ${e.message}" + ) + } + } + + /** 执行轻触操作 */ + private suspend fun tapWithAccessibility(tool: AITool): ToolResult { + return try { + withAccessibilityCheck(tool) { + val x = tool.parameters.find { it.name == "x" }?.value?.toIntOrNull() + val y = tool.parameters.find { it.name == "y" }?.value?.toIntOrNull() + + if (x == null || y == null) { + return@withAccessibilityCheck ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Missing or invalid coordinates. Both 'x' and 'y' must be valid integers." + ) + } + + withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } + + // 使用无障碍服务执行点击 + val result = performAccessibilityClick(x, y) + + if (result) { + withContext(Dispatchers.Main) { + operationOverlay.showTap(x, y) + operationOverlay.hide() + } + ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "tap", + actionDescription = + "Successfully tapped at coordinates ($x, $y) via accessibility service", + coordinates = Pair(x, y) + ), + error = "" + ) + } else { + operationOverlay.hide() + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to tap at coordinates via accessibility service." + ) + } + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error tapping at coordinates", e) + operationOverlay.hide() + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error tapping at coordinates: ${e.message}" + ) + } + } + + /** 执行长按操作 */ + private suspend fun longPressWithAccessibility(tool: AITool): ToolResult { + return try { + withAccessibilityCheck(tool) { + val x = tool.parameters.find { it.name == "x" }?.value?.toIntOrNull() + val y = tool.parameters.find { it.name == "y" }?.value?.toIntOrNull() + + if (x == null || y == null) { + return@withAccessibilityCheck ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Missing or invalid coordinates. Both 'x' and 'y' must be valid integers." + ) + } + + withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } + + // 使用无障碍服务执行长按 + val result = performAccessibilityLongPress(x, y) + + if (result) { + withContext(Dispatchers.Main) { + operationOverlay.showTap(x, y) + operationOverlay.hide() + } + ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "long_press", + actionDescription = + "Successfully long pressed at coordinates ($x, $y) via accessibility service", + coordinates = Pair(x, y) + ), + error = "" + ) + } else { + operationOverlay.hide() + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to long press at coordinates via accessibility service." + ) + } + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error long pressing at coordinates", e) + operationOverlay.hide() + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error long pressing at coordinates: ${e.message}" + ) + } + } + + /** 执行滑动操作 */ + private suspend fun swipeWithAccessibility(tool: AITool): ToolResult { + return try { + withAccessibilityCheck(tool) { + val startX = tool.parameters.find { it.name == "start_x" }?.value?.toIntOrNull() + val startY = tool.parameters.find { it.name == "start_y" }?.value?.toIntOrNull() + val endX = tool.parameters.find { it.name == "end_x" }?.value?.toIntOrNull() + val endY = tool.parameters.find { it.name == "end_y" }?.value?.toIntOrNull() + val duration = tool.parameters.find { it.name == "duration" }?.value?.toIntOrNull() ?: 300 + + if (startX == null || startY == null || endX == null || endY == null) { + return@withAccessibilityCheck ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Missing or invalid coordinates. 'start_x', 'start_y', 'end_x', and 'end_y' must be valid integers." + ) + } + + withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } + + // 使用无障碍服务执行滑动 + val result = performAccessibilitySwipe(startX, startY, endX, endY, duration) + + if (result) { + withContext(Dispatchers.Main) { + operationOverlay.showSwipe(startX, startY, endX, endY) + operationOverlay.hide() + } + ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "swipe", + actionDescription = + "Successfully performed swipe from ($startX, $startY) to ($endX, $endY) via accessibility service" + ), + error = "" + ) + } else { + operationOverlay.hide() + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Failed to perform swipe via accessibility service." + ) + } + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error performing swipe", e) + operationOverlay.hide() + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error performing swipe: ${e.message}" + ) + } + } + + // 使用无障碍服务执行点击的辅助方法 + private suspend fun performAccessibilityClick(x: Int, y: Int): Boolean { + return try { + UIHierarchyManager.performClick(context, x, y) + } catch (e: Exception) { + AppLogger.e(TAG, "Error performing accessibility click", e) + return false + } + } + + // 使用无障碍服务执行长按的辅助方法 + private suspend fun performAccessibilityLongPress(x: Int, y: Int): Boolean { + return try { + UIHierarchyManager.performLongPress(context, x, y) + } catch (e: Exception) { + AppLogger.e(TAG, "Error performing accessibility long press", e) + return false + } + } + + // 使用无障碍服务执行滑动的辅助方法 + private suspend fun performAccessibilitySwipe( + startX: Int, + startY: Int, + endX: Int, + endY: Int, + duration: Int + ): Boolean { + return try { + UIHierarchyManager.performSwipe(context, startX, startY, endX, endY, duration.toLong()) + } catch (e: Exception) { + AppLogger.e(TAG, "Error performing accessibility swipe", e) + return false + } + } + + protected fun accessibilityKeyAction(keyCode: String): Int? = when (keyCode) { + "KEYCODE_BACK" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_BACK + "KEYCODE_HOME" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_HOME + "KEYCODE_RECENTS" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_RECENTS + "KEYCODE_NOTIFICATIONS" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS + "KEYCODE_QUICK_SETTINGS" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS + "KEYCODE_POWER_DIALOG" -> android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_POWER_DIALOG + else -> null + } + + /** 模拟按键操作 */ + private suspend fun pressKeyWithAccessibility(tool: AITool): ToolResult { + val keyCode = tool.parameters.find { it.name == "key_code" }?.value + + if (keyCode == null) { + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Missing 'key_code' parameter." + ) + } + + try { + // 将字符串keyCode转换为AccessibilityService中的常量 + val keyAction = accessibilityKeyAction(keyCode) + + if (keyAction != null) { + // 通过UIHierarchyManager请求远程服务执行操作 + val success = UIHierarchyManager.performGlobalAction(context, keyAction) + return if (success) { + ToolResult( + toolName = tool.name, + success = true, + result = + UIActionResultData( + actionType = "keyPress", + actionDescription = + "Successfully pressed key: $keyCode via accessibility service" + ), + error = "" + ) + } else { + ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = + "Failed to press key: $keyCode via accessibility service. Not all keys are supported." + ) + } + } else { + // 如果不是标准全局操作,返回不支持的错误 + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = + "Key: $keyCode is not supported via accessibility service. Only system keys like BACK, HOME, etc. are supported." + ) + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error pressing key", e) + return ToolResult( + toolName = tool.name, + success = false, + result = StringResultData(""), + error = "Error pressing key: ${e.message ?: "Unknown exception"}" + ) + } + } + + private suspend fun captureScreenshotToFileWithAccessibility(tool: AITool): Pair?> { + return try { + val screenshotDir = OperitPaths.cleanOnExitDir() + + val shortName = System.currentTimeMillis().toString().takeLast(4) + val file = File(screenshotDir, "$shortName.png") + + val success = UIHierarchyManager.takeScreenshot(context, file.absolutePath, "png") + if (!success) { + AppLogger.w(TAG, "captureScreenshotForAgent: AIDL takeScreenshot failed") + return Pair(null, null) + } + + val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } + BitmapFactory.decodeFile(file.absolutePath, options) + val dimensions = if (options.outWidth > 0 && options.outHeight > 0) { + Pair(options.outWidth, options.outHeight) + } else { + null + } + + Pair(file.absolutePath, dimensions) + } catch (e: Exception) { + AppLogger.e(TAG, "captureScreenshot via accessibility failed", e) + Pair(null, null) + } + } + + private suspend fun captureScreenshotWithAccessibility(tool: AITool): Pair?> { + return captureScreenshotToFile(tool) + } + + private suspend fun captureScreenshotBitmapWithAccessibility(tool: AITool): Pair?> { + val (filePath, dimensions) = captureScreenshot(tool) + if (filePath == null) { + return Pair(null, dimensions) + } + + val bitmap = BitmapFactory.decodeFile(filePath) ?: return Pair(null, dimensions) + val resolvedDimensions = dimensions ?: Pair(bitmap.width, bitmap.height) + return Pair(bitmap, resolvedDimensions) + } + + private fun parseBounds(boundsString: String): android.graphics.Rect { + // 解析 "[left,top][right,bottom]" 格式的边界字符串 + val rect = android.graphics.Rect() + try { + val parts = boundsString.replace("[", "").replace("]", ",").split(",") + if (parts.size >= 4) { + rect.left = parts[0].toInt() + rect.top = parts[1].toInt() + rect.right = parts[2].toInt() + rect.bottom = parts[3].toInt() + } + } catch (e: Exception) { + AppLogger.e(TAG, "Error parsing bounds: $boundsString", e) + } + return rect + } } diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerDeviceInfoToolExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerDeviceInfoToolExecutor.kt deleted file mode 100644 index 2f7a134df3..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerDeviceInfoToolExecutor.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.debugger - -import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.accessbility.AccessibilityDeviceInfoToolExecutor - -/** 调试级别的设备信息工具,继承无障碍版本 */ -open class DebuggerDeviceInfoToolExecutor(context: Context) : - AccessibilityDeviceInfoToolExecutor(context) { - // 当前阶段不添加新功能,仅继承无障碍实现 -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerFileSystemTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerFileSystemTools.kt deleted file mode 100644 index 89bc40e8fe..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerFileSystemTools.kt +++ /dev/null @@ -1,2930 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.debugger - -import android.content.ActivityNotFoundException -import android.content.ClipData -import android.content.Context -import android.content.Intent -import android.webkit.MimeTypeMap -import androidx.core.content.FileProvider -import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.DirectoryListingData -import com.ai.assistance.operit.core.tools.FileContentData -import com.ai.assistance.operit.core.tools.FileExistsData -import com.ai.assistance.operit.core.tools.FileInfoData -import com.ai.assistance.operit.core.tools.FileOperationData -import com.ai.assistance.operit.core.tools.FilePartContentData -import com.ai.assistance.operit.core.tools.FindFilesResultData -import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutionLimits -import com.ai.assistance.operit.BuildConfig -import com.ai.assistance.operit.core.tools.defaultTool.accessbility.AccessibilityFileSystemTools -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor -import com.ai.assistance.operit.data.model.AITool -import com.ai.assistance.operit.data.model.ToolParameter -import com.ai.assistance.operit.data.model.ToolResult -import com.ai.assistance.operit.core.tools.defaultTool.PathValidator -import java.io.BufferedInputStream -import java.io.BufferedOutputStream -import java.io.File -import java.io.FileInputStream -import java.io.FileOutputStream -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale -import java.util.concurrent.atomic.AtomicInteger -import java.util.zip.ZipEntry -import java.util.zip.ZipFile -import java.util.zip.ZipInputStream -import java.util.zip.ZipOutputStream -import kotlin.math.exp -import com.ai.assistance.operit.util.files.FileUtils -import com.ai.assistance.operit.core.tools.ToolProgressBus -import com.ai.assistance.operit.util.files.AndroidUserPathUtils -import kotlinx.coroutines.cancelAndJoin -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import kotlinx.coroutines.flow.collect - -/** 调试者级别的文件系统工具,继承无障碍版本 */ -open class DebuggerFileSystemTools(context: Context) : AccessibilityFileSystemTools(context) { - companion object { - private const val TAG = "DebuggerFileSystemTools" - internal fun isOperitInternalPath(path: String): Boolean { - val normalizedPath = path.trim() - val appPackage = BuildConfig.APPLICATION_ID - return normalizedPath.startsWith("/data/data/$appPackage") || - AndroidUserPathUtils.isCurrentUserPackageDataPath(normalizedPath, appPackage) - } - } - - /** - * 判断路径是否为Operit应用的内部存储路径 - * 仅针对 Operit 应用自身数据目录路径返回true - */ - protected fun isOperitInternalPath(path: String): Boolean { - return Companion.isOperitInternalPath(path) - } - - private fun shQuote(value: String): String { - return "'" + value.replace("'", "'\"'\"'") + "'" - } - - private fun smoothProgress(count: Int, scale: Float): Float { - if (count <= 0) return 0f - return (1f - exp(-count / scale)).coerceIn(0f, 0.99f) - } - - private fun updateProgressFloor(progressFloor: AtomicInteger, candidate: Int) { - while (true) { - val old = progressFloor.get() - if (candidate <= old) return - if (progressFloor.compareAndSet(old, candidate)) return - } - } - - /** List files in a directory */ - override suspend fun listFiles(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.listFiles(tool) - } - if (isSafEnvironment(environment)) { - return super.listFiles(tool) - } - - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - - // 如果是Operit内部存储路径,使用super(AccessibilityFileSystemTools)的高权限方法 - if (isOperitInternalPath(path)) { - return super.listFiles(tool) - } - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Path parameter is required" - ) - } - - return try { - // 确保目录路径末尾有斜杠 - val normalizedPath = if (path.endsWith("/")) path else "$path/" - - // 使用ls -la命令获取详细的文件列表 - AppLogger.d(TAG, "Using ls -la command for path: $normalizedPath") - val listResult = AndroidShellExecutor.executeShellCommand("ls -la '$normalizedPath'") - - if (listResult.success) { - AppLogger.d(TAG, "ls -la command output: ${listResult.stdout}") - - // 解析ls -la命令输出 - val entries = parseDetailedDirectoryListing(listResult.stdout, normalizedPath) - - AppLogger.d(TAG, "Parsed ${entries.size} entries from ls -la output") - - return ToolResult( - toolName = tool.name, - success = true, - result = DirectoryListingData(path, entries), - error = "" - ) - } else { - AppLogger.w(TAG, "ls -la command failed: ${listResult.stderr}") - - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to list directory: ${listResult.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error listing directory", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error listing directory: ${e.message}" - ) - } - } - - /** Parse the output of the ls -la command into structured data */ - protected fun parseDetailedDirectoryListing( - output: String, - path: String - ): List { - val lines = output.trim().split("\n") - val entries = mutableListOf() - - AppLogger.d(TAG, "Parsing ${lines.size} lines from ls -la output") - - // 跳过第一行总计行 - val startIndex = if (lines.isNotEmpty() && lines[0].startsWith("total")) 1 else 0 - - // 日期格式化器,用于解析日期时间字符串 - val dateFormat = java.text.SimpleDateFormat("yyyy-MM-dd HH:mm", java.util.Locale.US) - - for (i in startIndex until lines.size) { - try { - val line = lines[i] - if (line.isBlank()) continue - - // 打印每一行以便调试 - AppLogger.d(TAG, "Parsing line: $line") - - // Android上ls -la输出格式: crwxrw--- 2 u0_a425 media_rw 4056 2025-03-14 - // 06:04 Android - // 符号链接格式: lrwxrwxrwx 1 root root 12 2025-03-14 06:04 filename -> - // /path/to/target - - // 使用正则表达式解析Android上的ls -la输出 - val androidRegex = - """^(\S+)\s+(\d+)\s+(\S+\s*\S*)\s+(\S+)\s+(\d+)\s+(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2})\s+(.+)$""".toRegex() - val androidMatch = androidRegex.find(line) - - if (androidMatch != null) { - // 特定于Android的格式解析 - val permissions = androidMatch.groupValues[1] - val size = androidMatch.groupValues[5].toLongOrNull() ?: 0 - val date = androidMatch.groupValues[6] - val time = androidMatch.groupValues[7] - var name = androidMatch.groupValues[8] - val isDirectory = permissions.startsWith("d") || permissions.startsWith("c") - val isSymlink = permissions.startsWith("l") - - // 处理符号链接格式 "name -> target" - if (isSymlink && name.contains(" -> ")) { - name = name.substringBefore(" -> ") - AppLogger.d(TAG, "Found symlink: $name") - } - - // 跳过 . 和 .. 条目 - if (name == "." || name == "..") continue - - // 将日期和时间转换为时间戳 - val dateTimeStr = "$date $time" - val timestamp = - try { - val parsedDate = dateFormat.parse(dateTimeStr) - parsedDate?.time?.toString() ?: "0" - } catch (e: Exception) { - AppLogger.e(TAG, "Error parsing date: $dateTimeStr", e) - "0" // 解析失败时使用默认时间戳 - } - - AppLogger.d( - TAG, - "Successfully parsed $name with date $dateTimeStr -> timestamp $timestamp" - ) - - entries.add( - DirectoryListingData.FileEntry( - name = name, - isDirectory = isDirectory, - size = size, - permissions = permissions, - lastModified = timestamp // 使用时间戳字符串 - ) - ) - continue - } - - // 如果Android特定格式不匹配,尝试通用格式 - val genericRegex = - """^([\-ld][\w-]{9})\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+([\w\d\s\-:\.]+)\s+(.+)$""".toRegex() - val match = genericRegex.find(line) - - if (match != null) { - val permissions = match.groupValues[1] - val size = match.groupValues[5].toLongOrNull() ?: 0 - val dateTimeStr = match.groupValues[6].trim() - var name = match.groupValues[7] - val isDirectory = permissions.startsWith("d") - val isSymlink = permissions.startsWith("l") - - // 处理符号链接格式 "name -> target" - if (isSymlink && name.contains(" -> ")) { - name = name.substringBefore(" -> ") - AppLogger.d(TAG, "Found symlink (generic): $name") - } - - // 跳过 . 和 .. 条目 - if (name == "." || name == "..") continue - - // 尝试解析通用格式的日期时间 - val timestamp = - try { - if (dateTimeStr.matches( - """^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}$""".toRegex() - ) - ) { - val parsedDate = dateFormat.parse(dateTimeStr) - parsedDate?.time?.toString() ?: "0" - } else { - // 如果不是YYYY-MM-DD HH:MM格式,返回当前时间 - System.currentTimeMillis().toString() - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error parsing generic date: $dateTimeStr", e) - "0" - } - - entries.add( - DirectoryListingData.FileEntry( - name = name, - isDirectory = isDirectory, - size = size, - permissions = permissions, - lastModified = timestamp - ) - ) - } else { - // 如果标准正则表达式也不匹配,使用更宽松的解析方法 - // 权限字段始终是10个字符 - if (line.length < 10) continue - - val permissions = line.substring(0, 10).trim() - val isDirectory = permissions.startsWith("d") || permissions.startsWith("c") - - // 解析剩余部分 - val parts = line.substring(10).trim().split("\\s+".toRegex()) - - if (parts.size < 6) { - AppLogger.w(TAG, "Invalid ls -la format: $line") - continue - } - - // 查找日期部分 - Android上通常是YYYY-MM-DD格式 - val dateIndex = - parts.indexOfFirst { it.matches("""^\d{4}-\d{2}-\d{2}$""".toRegex()) } - - if (dateIndex < 0 || dateIndex + 1 >= parts.size) { - AppLogger.w(TAG, "Cannot find date in line: $line") - continue - } - - // 日期后面的字段通常是时间 (HH:MM) - val timeIndex = dateIndex + 1 - - // 时间后面的所有内容都是文件名 - val nameStartIndex = timeIndex + 1 - if (nameStartIndex >= parts.size) { - AppLogger.w(TAG, "Cannot find filename position: $line") - continue - } - - var name = parts.subList(nameStartIndex, parts.size).joinToString(" ") - val isSymlink = permissions.startsWith("l") - - // 处理符号链接格式 "name -> target" - if (isSymlink && name.contains(" -> ")) { - name = name.substringBefore(" -> ") - AppLogger.d(TAG, "Found symlink (fallback): $name") - } - - // 跳过 . 和 .. 条目 - if (name == "." || name == "..") continue - - // 文件大小通常在用户和组之后,日期之前 - val sizeIndex = dateIndex - 1 - val size = if (sizeIndex >= 0) parts[sizeIndex].toLongOrNull() ?: 0 else 0 - - // 组合日期和时间,并转换为时间戳 - val dateTimeStr = "${parts[dateIndex]} ${parts[timeIndex]}" - val timestamp = - try { - val parsedDate = dateFormat.parse(dateTimeStr) - parsedDate?.time?.toString() ?: "0" - } catch (e: Exception) { - AppLogger.e(TAG, "Error parsing fallback date: $dateTimeStr", e) - "0" - } - - entries.add( - DirectoryListingData.FileEntry( - name = name, - isDirectory = isDirectory, - size = size, - permissions = permissions, - lastModified = timestamp - ) - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error parsing directory entry: ${lines[i]}", e) - // 跳过这一行但继续处理其他行 - } - } - - return entries - } - - /** 将八进制权限格式转换为字符串表示 (如 "rwxr-xr-x") */ - protected fun convertOctalPermToString(octalPerm: String): String { - try { - val permInt = octalPerm.toInt(8) - val permChars = CharArray(9) - - // 所有者权限 - permChars[0] = if (permInt and 0x100 != 0) 'r' else '-' - permChars[1] = if (permInt and 0x80 != 0) 'w' else '-' - permChars[2] = if (permInt and 0x40 != 0) 'x' else '-' - - // 组权限 - permChars[3] = if (permInt and 0x20 != 0) 'r' else '-' - permChars[4] = if (permInt and 0x10 != 0) 'w' else '-' - permChars[5] = if (permInt and 0x8 != 0) 'x' else '-' - - // 其他用户权限 - permChars[6] = if (permInt and 0x4 != 0) 'r' else '-' - permChars[7] = if (permInt and 0x2 != 0) 'w' else '-' - permChars[8] = if (permInt and 0x1 != 0) 'x' else '-' - - return String(permChars) - } catch (e: Exception) { - AppLogger.e(TAG, "Error converting octal permission: $octalPerm", e) - return "???" - } - } - - /** - * Reads the full content of a file as a new tool, handling different file types. - * This function does not enforce a size limit. - */ - override suspend fun readFileFull(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.readFileFull(tool) - } - if (isSafEnvironment(environment)) { - return super.readFileFull(tool) - } - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - val textOnly = tool.parameters.find { it.name == "text_only" }?.value?.toBoolean() ?: false - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - - // 如果是Operit内部存储路径,使用super的高权限方法 - if (isOperitInternalPath(path)) { - return super.readFileFull(tool) - } - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Path parameter is required" - ) - } - - try { - // First check if the file exists using shell command - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -f '$path' && echo 'exists' || echo 'not exists'" - ) - if (existsResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "File does not exist: $path" - ) - } - - // Check file extension - val fileExt = path.substringAfterLast('.', "").lowercase() - - // Handle special file types by calling the parent's handler - val specialReadResult = super.handleSpecialFileRead(tool, path, fileExt) - if (specialReadResult != null) { - // If the parent handled it, return its result. - // But if it failed, we might want to fall back to shell `cat` for some types. - if (specialReadResult.success) { - return specialReadResult - } - // Optional: Could add fallback logic here if superclass fails for some reason - } - - // Check if file is text-like by reading first few bytes (if text_only is enabled) - if (textOnly) { - // First, get a sample of the file - val sampleResult = AndroidShellExecutor.executeShellCommand("head -c 512 '$path'") - if (!sampleResult.success) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to sample file: ${sampleResult.stderr}" - ) - } - - // Analyze the sample bytes - val sampleBytes = sampleResult.stdout.toByteArray() - if (!FileUtils.isTextLike(sampleBytes)) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Skipped non-text file: $path" - ) - } - } - - // For text-like files, use shell `cat` to read full content - val result = AndroidShellExecutor.executeShellCommand("cat '$path'") - if (result.success) { - val sizeResult = - AndroidShellExecutor.executeShellCommand("stat -c %s '$path'") - val size = - sizeResult.stdout.trim().toLongOrNull() - ?: result.stdout.length.toLong() - - return ToolResult( - toolName = tool.name, - success = true, - result = - FileContentData( - path = path, - content = result.stdout, - size = size - ), - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to read file: ${result.stderr}" - ) - } - - } catch (e: Exception) { - AppLogger.e(TAG, "Error reading file", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error reading file: ${e.message}" - ) - } - } - - /** Read file content */ - override suspend fun readFile(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.readFile(tool) - } - if (isSafEnvironment(environment)) { - return super.readFile(tool) - } - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - - // 如果是Operit内部存储路径,使用super的高权限方法 - if (isOperitInternalPath(path)) { - return super.readFile(tool) - } - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Path parameter is required" - ) - } - - try { - val fileExt = path.substringAfterLast('.', "").lowercase() - - // For special types, full read then truncate text is the only way. - if (isSpecialFileType(fileExt)) { - val fullResult = readFileFull(tool) - if (!fullResult.success) return fullResult - - val contentData = fullResult.result as FileContentData - var content = contentData.content - val isTruncated = content.length > ToolExecutionLimits.MAX_FILE_READ_BYTES - if (isTruncated) { - content = content.substring(0, ToolExecutionLimits.MAX_FILE_READ_BYTES) - } - - var contentWithLineNumbers = addLineNumbers(content) - if (isTruncated) { - contentWithLineNumbers += "\n\n... (file content truncated) ..." - } - - return ToolResult( - toolName = tool.name, - success = true, - result = FileContentData(path = path, content = contentWithLineNumbers, size = contentWithLineNumbers.length.toLong()), - error = "" - ) - } - - // For text-based files, read only the beginning. - // Check if file is text-like by analyzing a sample - val sampleResult = AndroidShellExecutor.executeShellCommand("head -c 512 '$path'") - if (sampleResult.success) { - val sampleBytes = sampleResult.stdout.toByteArray() - if (!FileUtils.isTextLike(sampleBytes)) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "File does not appear to be a text file. Use readFileFull tool for special file types." - ) - } - } - - // Check file size to see if truncation is needed - val sizeResult = AndroidShellExecutor.executeShellCommand("stat -c %s '$path'") - val size = sizeResult.stdout.trim().toLongOrNull() ?: 0 - val truncated = size > ToolExecutionLimits.MAX_FILE_READ_BYTES - - val readCommand = "head -c ${ToolExecutionLimits.MAX_FILE_READ_BYTES} '$path'" - val readResult = AndroidShellExecutor.executeShellCommand(readCommand) - - if (!readResult.success) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to read file: ${readResult.stderr}" - ) - } - - var content = readResult.stdout - var contentWithLineNumbers = addLineNumbers(content) - if (truncated) { - contentWithLineNumbers += "\n\n... (file content truncated) ..." - } - - return ToolResult( - toolName = tool.name, - success = true, - result = - FileContentData( - path = path, - content = contentWithLineNumbers, - size = contentWithLineNumbers.length.toLong() - ), - error = "" - ) - } catch (e: Exception) { - AppLogger.e(TAG, "Error reading file", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error reading file: ${e.message}" - ) - } - } - - /** 按行号范围读取文件内容(行号从1开始,包括开始行和结束行) */ - override suspend fun readFilePart(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.readFilePart(tool) - } - if (isSafEnvironment(environment)) { - return super.readFilePart(tool) - } - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - - // 如果是Operit内部存储路径,使用super的高权限方法 - if (isOperitInternalPath(path)) { - return super.readFilePart(tool) - } - val startLineParam = tool.parameters.find { it.name == "start_line" }?.value?.toIntOrNull() ?: 1 - val endLineParam = tool.parameters.find { it.name == "end_line" }?.value?.toIntOrNull() - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Path parameter is required" - ) - } - - return try { - // 0. 特殊文件类型检查 - // 如果是Word/PDF/图片等特殊文件,使用父类(StandardFileSystemTools)的逻辑处理 - // 因为Shell命令(cat/sed)无法正确解析这些二进制格式 - val fileExt = path.substringAfterLast('.', "").lowercase() - if (isSpecialFileType(fileExt)) { - return super.readFilePart(tool) - } - - // 1. Check if file exists - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -f '$path' && echo 'exists' || echo 'not exists'" - ) - if (existsResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "File does not exist: $path" - ) - } - - // 2. Get total number of lines - val wcResult = AndroidShellExecutor.executeShellCommand("cat '$path' | wc -l") - if (!wcResult.success) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to count lines in file: ${wcResult.stderr}" - ) - } - - val totalLines = wcResult.stdout.trim().split(" ")[0].toIntOrNull() ?: 0 - - // 3. 计算实际的行号范围(行号从1开始) - val startLine = maxOf(1, startLineParam).coerceIn(1, maxOf(1, totalLines)) - val endLine = - (endLineParam - ?: (startLine + ToolExecutionLimits.DEFAULT_FILE_READ_PART_LINES - 1)) - .coerceIn(startLine, maxOf(1, totalLines)) - - if (totalLines == 0 || startLine > endLine) { - return ToolResult( - toolName = tool.name, - success = true, - result = - FilePartContentData( - path = path, - content = "", - partIndex = 0, // 保留兼容性,但不再使用 - totalParts = 1, // 保留兼容性,但不再使用 - startLine = startLine - 1, // 转为0-based - endLine = endLine, - totalLines = totalLines - ), - error = "" - ) - } - - // 4. Extract the specific part using sed - val sedCommand = "sed -n '${startLine},${endLine}p' '$path'" - val partResult = AndroidShellExecutor.executeShellCommand(sedCommand) - - if (!partResult.success) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to read file part: ${partResult.stderr}" - ) - } - - val maxFileSizeBytes = ToolExecutionLimits.MAX_FILE_READ_BYTES - var content = partResult.stdout - val isTruncated = content.length > maxFileSizeBytes - if (isTruncated) { - content = content.substring(0, maxFileSizeBytes) - } - - var contentWithLineNumbers = addLineNumbers(content, startLine, totalLines) - if (isTruncated) { - contentWithLineNumbers += "\n\n... (file content truncated) ..." - } - - ToolResult( - toolName = tool.name, - success = true, - result = - FilePartContentData( - path = path, - content = contentWithLineNumbers.trimEnd(), - partIndex = 0, // 保留兼容性,但不再使用 - totalParts = 1, // 保留兼容性,但不再使用 - startLine = startLine - 1, // To 0-indexed for response - endLine = endLine, - totalLines = totalLines - ), - error = "" - ) - } catch (e: Exception) { - AppLogger.e(TAG, "Error reading file part", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error reading file part: ${e.message}" - ) - } - } - - /** - * 重写特殊文件读取逻辑 - * 对于受保护的路径(如 /Android/data),先通过Shell命令复制到缓存目录, - * 再调用父类的解析逻辑。 - */ - override suspend fun handleSpecialFileRead( - tool: AITool, - path: String, - fileExt: String - ): ToolResult? { - val file = File(path) - - if (isOperitInternalPath(path)) { - return super.handleSpecialFileRead(tool, path, fileExt) - } - - // 如果文件可读,直接使用父类逻辑(更高效) - if (file.exists() && file.canRead()) { - return super.handleSpecialFileRead(tool, path, fileExt) - } - - AppLogger.d(TAG, "File not directly readable (permission restricted), trying Shell copy for: $path") - - // 创建临时文件用于中转 - val tempFile = File(context.cacheDir, "shell_copy_${System.currentTimeMillis()}.$fileExt") - - return try { - // 使用cat命令复制文件内容 - // 注意:使用cat而不是cp,因为cp可能保留权限属性导致仍然无法读取 - val copyResult = AndroidShellExecutor.executeShellCommand("cat '$path' > '${tempFile.absolutePath}'") - - if (!copyResult.success) { - AppLogger.w(TAG, "Shell copy failed: ${copyResult.stderr}") - // 复制失败,回退到父类逻辑(虽然很可能也失败,但能返回一致的错误信息) - return super.handleSpecialFileRead(tool, path, fileExt) - } - - // 检查临时文件是否有效 - if (!tempFile.exists() || tempFile.length() == 0L) { - AppLogger.w(TAG, "Temp file is empty or does not exist after copy") - return super.handleSpecialFileRead(tool, path, fileExt) - } - - // 使用临时文件路径调用父类处理逻辑 - val tempToolResult = super.handleSpecialFileRead(tool, tempFile.absolutePath, fileExt) - - // 如果处理成功,修正返回结果中的 path 为原始路径 - if (tempToolResult != null && tempToolResult.success) { - val resultData = tempToolResult.result - if (resultData is FileContentData) { - return tempToolResult.copy( - result = resultData.copy(path = path) - ) - } - } - - tempToolResult - - } catch (e: Exception) { - AppLogger.e(TAG, "Error in shell copy strategy", e) - super.handleSpecialFileRead(tool, path, fileExt) - } finally { - // 清理临时文件 - try { - if (tempFile.exists()) { - tempFile.delete() - } - } catch (e: Exception) { - AppLogger.e(TAG, "Failed to clean up temp file", e) - } - } - } - - /** Write content to a file */ - override suspend fun writeFile(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.writeFile(tool) - } - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - if (isSafEnvironment(environment)) { - return super.writeFile(tool) - } - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - val content = tool.parameters.find { it.name == "content" }?.value ?: "" - val append = tool.parameters.find { it.name == "append" }?.value?.toBoolean() ?: false - - // 如果是Operit内部存储路径,使用super的高权限方法 - if (isOperitInternalPath(path)) { - return super.writeFile(tool) - } - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "write", - path = "", - successful = false, - details = "Path parameter is required" - ), - error = "Path parameter is required" - ) - } - - return try { - // 确保目标目录存在 - val directory = File(path).parent - if (directory != null) { - val mkdirResult = AndroidShellExecutor.executeShellCommand("mkdir -p '$directory'") - if (!mkdirResult.success) { - AppLogger.w(TAG, "Warning: Failed to create parent directory: ${mkdirResult.stderr}") - } - } - - // 直接使用echo命令写入内容 - // 对内容进行base64编码,避免特殊字符问题 - val contentBase64 = - android.util.Base64.encodeToString( - content.toByteArray(), - android.util.Base64.NO_WRAP - ) - - // 使用 base64 写入;大内容分块,失败后不重新提交已写入的数据。 - val redirectOperator = if (append) ">>" else ">" - val maxInlineBase64 = 32768 - val base64ChunkSize = 16384 // 4的倍数,保证base64解码边界正确 - val writeResult = - if (contentBase64.length <= maxInlineBase64) { - AndroidShellExecutor.executeShellCommand( - "echo '$contentBase64' | base64 -d $redirectOperator '$path'" - ) - } else { - var chunkSuccess = true - var firstChunk = true - var index = 0 - while (index < contentBase64.length) { - val end = (index + base64ChunkSize).coerceAtMost(contentBase64.length) - val chunk = contentBase64.substring(index, end) - val chunkRedirect = if (firstChunk) redirectOperator else ">>" - val chunkResult = - AndroidShellExecutor.executeShellCommand( - "echo '$chunk' | base64 -d $chunkRedirect '$path'" - ) - if (!chunkResult.success) { - AppLogger.e( - TAG, - "Failed to write base64 chunk: ${chunkResult.stderr}" - ) - chunkSuccess = false - break - } - firstChunk = false - index = end - } - if (chunkSuccess) { - AndroidShellExecutor.CommandResult(true, "", "", 0) - } else { - AndroidShellExecutor.CommandResult(false, "", "Failed to write base64 chunks") - } - } - - if (!writeResult.success) { - AppLogger.e(TAG, "Failed to write with base64 method: ${writeResult.stderr}") - return ToolResult( - toolName = tool.name, - success = false, - result = FileOperationData( - operation = if (append) "append" else "write", - path = path, - successful = false, - details = "Failed to write to file: ${writeResult.stderr}" - ), - error = "Failed to write to file: ${writeResult.stderr}" - ) - } - - // 验证写入是否成功 - val verifyResult = - AndroidShellExecutor.executeShellCommand( - "test -f '$path' && echo 'exists' || echo 'not exists'" - ) - if (verifyResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = if (append) "append" else "write", - path = path, - successful = false, - details = - "Write command completed but file does not exist. Possible permission issue." - ), - error = - "Write command completed but file does not exist. Possible permission issue." - ) - } - - // 检查文件大小确认内容被写入 - val sizeResult = - AndroidShellExecutor.executeShellCommand( - "stat -c %s '$path' 2>/dev/null || echo '0'" - ) - val size = sizeResult.stdout.trim().toLongOrNull() ?: 0 - if (size == 0L && content.isNotEmpty()) { - // 文件存在但是大小为0,可能写入失败 - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = if (append) "append" else "write", - path = path, - successful = false, - details = - "File was created but appears to be empty. Possible write failure." - ), - error = "File was created but appears to be empty. Possible write failure." - ) - } - - val operation = if (append) "append" else "write" - val details = if (append) "Content appended to $path" else "Content written to $path" - - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = operation, - path = path, - successful = true, - details = details - ), - error = "" - ) - } catch (e: Exception) { - AppLogger.e(TAG, "Error writing to file", e) - - // 提供更具体的错误信息 - val errorMessage = - when { - e is InterruptedException || - e.message?.contains("interrupted", ignoreCase = true) == true -> - "ADB connection interrupted, possibly due to network instability. Please check ADB connection and retry. Error details: ${e.message}" - e is java.net.SocketException || - e.message?.contains("socket", ignoreCase = true) == true -> - "ADB network connection exception, please check if device is still connected and retry. Error details: ${e.message}" - e is java.io.IOException -> "File IO error: ${e.message}. Please check if the file path has write permission." - e.message?.contains("permission", ignoreCase = true) == true -> - "Permission denied, cannot write to file: ${e.message}. Please check if the app has appropriate permissions." - else -> "Error writing to file: ${e.message}" - } - - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = if (append) "append" else "write", - path = path, - successful = false, - details = errorMessage - ), - error = errorMessage - ) - } - } - - /** Delete a file or directory */ - override suspend fun deleteFile(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.deleteFile(tool) - } - - if (isSafEnvironment(environment)) { - return super.deleteFile(tool) - } - - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - - // 如果是Operit内部存储路径,使用super的高权限方法 - if (isOperitInternalPath(path)) { - return super.deleteFile(tool) - } - val recursive = tool.parameters.find { it.name == "recursive" }?.value?.toBoolean() ?: false - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "delete", - path = "", - successful = false, - details = "Path parameter is required" - ), - error = "Path parameter is required" - ) - } - - - return try { - val quotedPath = shQuote(path) - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -e $quotedPath && echo 'exists' || echo 'missing'" - ) - if (existsResult.stdout.trim() != "exists") { - ToolProgressBus.update(tool.name, 1f, "Delete failed") - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "delete", - path = path, - successful = false, - details = "File or directory does not exist: $path" - ), - error = "File or directory does not exist: $path" - ) - } - - val typeResult = - AndroidShellExecutor.executeShellCommand( - "if test -d $quotedPath; then echo 'directory'; elif test -f $quotedPath; then echo 'file'; else echo 'other'; fi" - ) - val isDirectory = typeResult.stdout.trim() == "directory" - - ToolProgressBus.update( - tool.name, - 0.1f, - if (isDirectory) "Deleting directory..." else "Deleting file..." - ) - - val deleteCommand = - if (recursive) "rm -rf $quotedPath" else if (isDirectory) "rmdir $quotedPath" else "rm -f $quotedPath" - val result = AndroidShellExecutor.executeShellCommand(deleteCommand) - - if (result.success && isDirectory && recursive) { - ToolProgressBus.update(tool.name, 0.85f, "Finalizing directory deletion...") - AndroidShellExecutor.executeShellCommand("rmdir $quotedPath") - } - - val verifyDeletedResult = - AndroidShellExecutor.executeShellCommand( - "test -e $quotedPath && echo 'exists' || echo 'missing'" - ) - val deleted = verifyDeletedResult.stdout.trim() != "exists" - - if (result.success && deleted) { - ToolProgressBus.update(tool.name, 1f, "Delete completed") - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "delete", - path = path, - successful = true, - details = "Successfully deleted $path" - ), - error = "" - ) - } else { - val errorMessage = - when { - !result.success && result.stderr.isNotBlank() -> - "Failed to delete: ${result.stderr}" - !deleted -> "Failed to delete: target still exists after delete command" - else -> "Failed to delete: unknown error" - } - ToolProgressBus.update(tool.name, 1f, "Delete failed") - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "delete", - path = path, - successful = false, - details = errorMessage - ), - error = errorMessage - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error deleting file/directory", e) - ToolProgressBus.update(tool.name, 1f, "Delete failed") - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "delete", - path = path, - successful = false, - details = "Error deleting file/directory: ${e.message}" - ), - error = "Error deleting file/directory: ${e.message}" - ) - } - } - - /** Check if a file or directory exists */ - override suspend fun fileExists(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.fileExists(tool) - } - - if (isSafEnvironment(environment)) { - return super.fileExists(tool) - } - - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - - // 如果是Operit内部存储路径,使用super的高权限方法 - if (isOperitInternalPath(path)) { - return super.fileExists(tool) - } - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Path parameter is required" - ) - } - - return try { - // Check if the path exists - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -e '$path' && echo 'exists' || echo 'not exists'" - ) - val exists = existsResult.success && existsResult.stdout.trim() == "exists" - - if (!exists) { - // If it doesn't exist, return a simple FileExistsData with - // exists=false - return ToolResult( - toolName = tool.name, - success = true, - result = FileExistsData(path = path, exists = false), - error = "" - ) - } - - // If it exists, check if it's a directory - val isDirResult = - AndroidShellExecutor.executeShellCommand( - "test -d '$path' && echo 'true' || echo 'false'" - ) - val isDirectory = isDirResult.success && isDirResult.stdout.trim() == "true" - - // Get the size - val sizeResult = - AndroidShellExecutor.executeShellCommand( - "stat -c %s '$path' 2>/dev/null || echo '0'" - ) - val size = sizeResult.stdout.trim().toLongOrNull() ?: 0 - - return ToolResult( - toolName = tool.name, - success = true, - result = - FileExistsData( - path = path, - exists = true, - isDirectory = isDirectory, - size = size - ), - error = "" - ) - } catch (e: Exception) { - AppLogger.e(TAG, "Error checking file existence", e) - return ToolResult( - toolName = tool.name, - success = false, - result = - FileExistsData( - path = path, - exists = false, - isDirectory = false, - size = 0 - ), - error = "Error checking file existence: ${e.message}" - ) - } - } - - /** Move or rename a file or directory */ - override suspend fun moveFile(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.moveFile(tool) - } - val sourcePath = tool.parameters.find { it.name == "source" }?.value ?: "" - val destPath = tool.parameters.find { it.name == "destination" }?.value ?: "" - if (isSafEnvironment(environment)) { - return super.moveFile(tool) - } - PathValidator.validateAndroidPath(sourcePath, tool.name)?.let { return it } - PathValidator.validateAndroidPath(destPath, tool.name)?.let { return it } - - // 如果源文件或目标文件在Operit内部存储,使用super的高权限方法 - if (isOperitInternalPath(sourcePath) || isOperitInternalPath(destPath)) { - return super.moveFile(tool) - } - PathValidator.validateAndroidPath(destPath, tool.name, "destination")?.let { return it } - - if (sourcePath.isBlank() || destPath.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "move", - path = sourcePath, - successful = false, - details = "Source and destination parameters are required" - ), - error = "Source and destination parameters are required" - ) - } - - - return try { - val result = AndroidShellExecutor.executeShellCommand("mv '$sourcePath' '$destPath'") - - if (result.success) { - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "move", - path = sourcePath, - successful = true, - details = "Successfully moved $sourcePath to $destPath" - ), - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "move", - path = sourcePath, - successful = false, - details = "Failed to move file: ${result.stderr}" - ), - error = "Failed to move file: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error moving file", e) - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "move", - path = sourcePath, - successful = false, - details = "Error moving file: ${e.message}" - ), - error = "Error moving file: ${e.message}" - ) - } - } - - /** Copy a file or directory */ - override suspend fun copyFile(tool: AITool): ToolResult { - // 检查是否是 Linux 环境或跨环境操作 - val environment = tool.parameters.find { it.name == "environment" }?.value - val sourceEnvironment = tool.parameters.find { it.name == "source_environment" }?.value - val destEnvironment = tool.parameters.find { it.name == "dest_environment" }?.value - - // 确定源和目标环境 - val srcEnv = sourceEnvironment ?: environment ?: "android" - val dstEnv = destEnvironment ?: environment ?: "android" - - // 如果是 Linux 环境或跨环境操作,委托给父类处理 - if (srcEnv.lowercase() == "linux" || dstEnv.lowercase() == "linux") { - return super.copyFile(tool) - } - - val sourcePath = tool.parameters.find { it.name == "source" }?.value ?: "" - val destPath = tool.parameters.find { it.name == "destination" }?.value ?: "" - val recursive = tool.parameters.find { it.name == "recursive" }?.value?.toBoolean() ?: true - if (sourcePath.startsWith("content://", ignoreCase = true) || destPath.startsWith("content://", ignoreCase = true)) { - return super.copyFile(tool) - } - PathValidator.validateAndroidPath(sourcePath, tool.name, "source")?.let { return it } - PathValidator.validateAndroidPath(destPath, tool.name, "destination")?.let { return it } - - // 如果源文件或目标文件在Operit内部存储,使用super的高权限方法 - if (isOperitInternalPath(sourcePath) || isOperitInternalPath(destPath)) { - return super.copyFile(tool) - } - - if (sourcePath.isBlank() || destPath.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "copy", - path = sourcePath, - successful = false, - details = "Source and destination parameters are required" - ), - error = "Source and destination parameters are required" - ) - } - - return try { - // 首先检查源路径是否存在 - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -e '$sourcePath' && echo 'exists' || echo 'not exists'" - ) - if (existsResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "copy", - path = sourcePath, - successful = false, - details = "Source path does not exist: $sourcePath" - ), - error = "Source path does not exist: $sourcePath" - ) - } - - // 检查是否为目录 - val isDirResult = - AndroidShellExecutor.executeShellCommand( - "test -d '$sourcePath' && echo 'true' || echo 'false'" - ) - val isDirectory = isDirResult.stdout.trim() == "true" - - // 确保目标父目录存在 - val destParentDir = destPath.substringBeforeLast('/') - if (destParentDir.isNotEmpty()) { - AndroidShellExecutor.executeShellCommand("mkdir -p '$destParentDir'") - } - - // 根据是否为目录选择不同的复制命令 - val copyCommand = - if (isDirectory && recursive) { - "cp -r '$sourcePath' '$destPath'" - } else if (!isDirectory) { - "cp '$sourcePath' '$destPath'" - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "copy", - path = sourcePath, - successful = false, - details = - "Cannot copy directory without recursive flag" - ), - error = "Cannot copy directory without recursive flag" - ) - } - - val result = AndroidShellExecutor.executeShellCommand(copyCommand) - - if (result.success) { - // 验证复制是否成功 - val verifyResult = - AndroidShellExecutor.executeShellCommand( - "test -e '$destPath' && echo 'exists' || echo 'not exists'" - ) - if (verifyResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "copy", - path = sourcePath, - successful = false, - details = - "Copy command completed but destination does not exist" - ), - error = "Copy command completed but destination does not exist" - ) - } - - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "copy", - path = sourcePath, - successful = true, - details = - "Successfully copied ${if (isDirectory) "directory" else "file"} $sourcePath to $destPath" - ), - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "copy", - path = sourcePath, - successful = false, - details = "Failed to copy: ${result.stderr}" - ), - error = "Failed to copy: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error copying file/directory", e) - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "copy", - path = sourcePath, - successful = false, - details = "Error copying file/directory: ${e.message}" - ), - error = "Error copying file/directory: ${e.message}" - ) - } - } - - /** Create a directory */ - override suspend fun makeDirectory(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.makeDirectory(tool) - } - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - if (isSafEnvironment(environment)) { - return super.makeDirectory(tool) - } - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - - // 如果是Operit内部存储路径,使用super的高权限方法 - if (isOperitInternalPath(path)) { - return super.makeDirectory(tool) - } - val createParents = - tool.parameters.find { it.name == "create_parents" }?.value?.toBoolean() ?: false - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "mkdir", - path = "", - successful = false, - details = "Path parameter is required" - ), - error = "Path parameter is required" - ) - } - - return try { - // 首先检查目录是否已存在 - val checkDirResult = - AndroidShellExecutor.executeShellCommand( - "test -d '$path' && echo 'exists' || echo 'not exists'" - ) - - if (checkDirResult.success && checkDirResult.stdout.trim() == "exists") { - // 目录已存在,返回成功 - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "mkdir", - path = path, - successful = true, - details = "Directory already exists: $path" - ), - error = "" - ) - } - - val mkdirCommand = if (createParents) "mkdir -p '$path'" else "mkdir '$path'" - val result = AndroidShellExecutor.executeShellCommand(mkdirCommand) - - if (result.success) { - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "mkdir", - path = path, - successful = true, - details = "Successfully created directory $path" - ), - error = "" - ) - } else { - // 创建失败后再次检查是否已存在(可能在执行过程中被创建) - val recheckDirResult = - AndroidShellExecutor.executeShellCommand( - "test -d '$path' && echo 'exists' || echo 'not exists'" - ) - - if (recheckDirResult.success && recheckDirResult.stdout.trim() == "exists") { - // 目录已存在,返回成功 - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "mkdir", - path = path, - successful = true, - details = "Directory already exists: $path" - ), - error = "" - ) - } - - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "mkdir", - path = path, - successful = false, - details = "Failed to create directory: ${result.stderr}" - ), - error = "Failed to create directory: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error creating directory", e) - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "mkdir", - path = path, - successful = false, - details = "Error creating directory: ${e.message}" - ), - error = "Error creating directory: ${e.message}" - ) - } - } - - /** Search for files matching a pattern */ - override suspend fun findFiles(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.findFiles(tool) - } - - if (isSafEnvironment(environment)) { - return super.findFiles(tool) - } - - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - val pattern = tool.parameters.find { it.name == "pattern" }?.value ?: "" - - if (isOperitInternalPath(path)) { - return super.findFiles(tool) - } - - if (path.isBlank() || pattern.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = - FindFilesResultData( - path = path, - pattern = pattern, - files = emptyList() - ), - error = "Path and pattern parameters are required" - ) - } - - return try { - ToolProgressBus.update(tool.name, 0.02f, "Searching (device)...") - // Add options for different search modes - val usePathPattern = - tool.parameters.find { it.name == "use_path_pattern" }?.value?.toBoolean() - ?: false - val caseInsensitive = - tool.parameters.find { it.name == "case_insensitive" }?.value?.toBoolean() - ?: false - - val isFileResult = - AndroidShellExecutor.executeShellCommand( - "test -f ${shQuote(path)} && echo file || echo not_file" - ) - if (isFileResult.success && isFileResult.stdout.trim() == "file") { - val fileName = path.substringAfterLast('/') - val testString = if (usePathPattern) path else fileName - val regex = globToRegex(pattern, caseInsensitive) - val files = if (regex.matches(testString)) listOf(path) else emptyList() - - ToolProgressBus.update(tool.name, 1f, "Search completed, found ${files.size}") - - return ToolResult( - toolName = tool.name, - success = true, - result = FindFilesResultData(path = path, pattern = pattern, files = files), - error = "" - ) - } - - // Add depth control parameter (default to -1 for unlimited depth/fully - // recursive) - val maxDepth = - tool.parameters.find { it.name == "max_depth" }?.value?.toIntOrNull() ?: -1 - - // Determine which search option to use - val searchOption = - if (usePathPattern) { - if (caseInsensitive) "-ipath" else "-path" - } else { - if (caseInsensitive) "-iname" else "-name" - } - - // Properly escape the pattern if quotes are required - val escapedPattern = pattern.replace("'", "'\\''") - val patternForCommand = "'$escapedPattern'" - - // Build the command with depth control if specified - val depthOption = if (maxDepth >= 0) "-maxdepth $maxDepth" else "" - val command = - "find '${if(path.endsWith("/")) path else "$path/"}' $depthOption $searchOption $patternForCommand" - - val files = mutableListOf() - val foundCount = AtomicInteger(0) - val progressFloor = AtomicInteger(2) - val stderrBuilder = StringBuilder() - - val process = AndroidShellExecutor.startShellProcess(command) - try { - val exitCode = coroutineScope { - val stdoutJob = launch { - process.stdout.collect { line -> - val v = line.trim() - if (v.isNotEmpty()) { - files.add(v) - val found = foundCount.incrementAndGet() - val p = (smoothProgress(found, 250f) * 100).toInt().coerceIn(0, 99) - updateProgressFloor(progressFloor, p) - if (found % 20 == 0) { - ToolProgressBus.update( - tool.name, - progressFloor.get() / 100f, - "Searching... found $found" - ) - } - } - } - } - val stderrJob = launch { - process.stderr.collect { line -> - if (line.isNotBlank()) { - stderrBuilder.appendLine(line) - } - } - } - val tickerJob = launch { - while (isActive && process.isAlive) { - delay(500) - val current = progressFloor.get() - if (current < 95) { - progressFloor.compareAndSet(current, current + 1) - ToolProgressBus.update( - tool.name, - progressFloor.get() / 100f, - "Searching... found ${foundCount.get()}" - ) - } - } - } - - val code = process.waitFor() - stdoutJob.cancelAndJoin() - stderrJob.cancelAndJoin() - tickerJob.cancelAndJoin() - code - } - - if (exitCode != 0) { - val err = stderrBuilder.toString().trim() - return ToolResult( - toolName = tool.name, - success = false, - result = FindFilesResultData(path = path, pattern = pattern, files = emptyList()), - error = if (err.isNotBlank()) err else "find command failed with exitCode=$exitCode" - ) - } - } finally { - if (process.isAlive) { - process.destroy() - } - } - - ToolProgressBus.update(tool.name, 1f, "Search completed, found ${files.size}") - - return ToolResult( - toolName = tool.name, - success = true, - result = FindFilesResultData(path = path, pattern = pattern, files = files), - error = "" - ) - } catch (e: Exception) { - AppLogger.e(TAG, "Error searching for files", e) - ToolProgressBus.update(tool.name, 1f, "Search failed") - return ToolResult( - toolName = tool.name, - success = false, - result = - FindFilesResultData( - path = path, - pattern = pattern, - files = emptyList() - ), - error = "Error searching for files: ${e.message}" - ) - } - } - - /** Get file information */ - override suspend fun fileInfo(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.fileInfo(tool) - } - - if (isSafEnvironment(environment)) { - return super.fileInfo(tool) - } - - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - - // 如果是Operit内部存储路径,使用super的高权限方法 - if (isOperitInternalPath(path)) { - return super.fileInfo(tool) - } - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileInfoData( - path = "", - exists = false, - fileType = "", - size = 0, - permissions = "", - owner = "", - group = "", - lastModified = "", - rawStatOutput = "" - ), - error = "Path parameter is required" - ) - } - - return try { - // Check if file exists - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -e '$path' && echo 'exists' || echo 'not exists'" - ) - if (existsResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileInfoData( - path = path, - exists = false, - fileType = "", - size = 0, - permissions = "", - owner = "", - group = "", - lastModified = "", - rawStatOutput = "" - ), - error = "File or directory does not exist: $path" - ) - } - - // Get file details using stat - val statResult = AndroidShellExecutor.executeShellCommand("stat '$path'") - - if (statResult.success) { - // Get file type - val fileTypeResult = - AndroidShellExecutor.executeShellCommand( - "test -d '$path' && echo 'directory' || (test -f '$path' && echo 'file' || echo 'other')" - ) - val fileType = fileTypeResult.stdout.trim() - - // Get file size - val sizeResult = - AndroidShellExecutor.executeShellCommand( - "stat -c %s '$path' 2>/dev/null || echo '0'" - ) - val size = sizeResult.stdout.trim().toLongOrNull() ?: 0 - - // Get file permissions - val permissionsResult = - AndroidShellExecutor.executeShellCommand( - "stat -c %A '$path' 2>/dev/null || echo ''" - ) - val permissions = permissionsResult.stdout.trim() - - // Get owner and group - val ownerResult = - AndroidShellExecutor.executeShellCommand( - "stat -c %U '$path' 2>/dev/null || echo ''" - ) - val owner = ownerResult.stdout.trim() - - val groupResult = - AndroidShellExecutor.executeShellCommand( - "stat -c %G '$path' 2>/dev/null || echo ''" - ) - val group = groupResult.stdout.trim() - - // Get last modified time - val modifiedResult = - AndroidShellExecutor.executeShellCommand( - "stat -c %Y '$path' 2>/dev/null || echo ''" - ) - val lastModifiedEpochSec = modifiedResult.stdout.trim().toLongOrNull() - val lastModified = - if (lastModifiedEpochSec != null && lastModifiedEpochSec > 0) { - SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US) - .format(Date(lastModifiedEpochSec * 1000L)) - } else { - "" - } - - return ToolResult( - toolName = tool.name, - success = true, - result = - FileInfoData( - path = path, - exists = true, - fileType = fileType, - size = size, - permissions = permissions, - owner = owner, - group = group, - lastModified = lastModified, - rawStatOutput = statResult.stdout - ), - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileInfoData( - path = path, - exists = true, - fileType = "", - size = 0, - permissions = "", - owner = "", - group = "", - lastModified = "", - rawStatOutput = "" - ), - error = "Failed to get file information: ${statResult.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error getting file information", e) - return ToolResult( - toolName = tool.name, - success = false, - result = - FileInfoData( - path = path, - exists = false, - fileType = "", - size = 0, - permissions = "", - owner = "", - group = "", - lastModified = "", - rawStatOutput = "" - ), - error = "Error getting file information: ${e.message}" - ) - } - } - - /** Zip files or directories */ - override suspend fun zipFiles(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.zipFiles(tool) - } - val sourcePath = tool.parameters.find { it.name == "source" }?.value ?: "" - val zipPath = tool.parameters.find { it.name == "destination" }?.value ?: "" - val includeRootDirectoryParameter = tool.parameters.find { it.name == "include_root_directory" } - val includeRootDirectory = - if (includeRootDirectoryParameter == null) { - true - } else { - includeRootDirectoryParameter.value.toBooleanStrictOrNull() - ?: return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "include_root_directory must be true or false" - ) - } - PathValidator.validateAndroidPath(sourcePath, tool.name, "source")?.let { return it } - PathValidator.validateAndroidPath(zipPath, tool.name, "destination")?.let { return it } - - if (isOperitInternalPath(sourcePath) || isOperitInternalPath(zipPath)) { - return super.zipFiles(tool) - } - - if (sourcePath.isBlank() || zipPath.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Source and destination parameters are required" - ) - } - - return try { - val archiveSourcePath = - sourcePath.trimEnd('/').let { - if (it.isEmpty() && sourcePath.startsWith("/")) "/" else it - } - // First, check if the source path exists - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -e ${shQuote(archiveSourcePath)} && echo 'exists' || echo 'not exists'" - ) - if (existsResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Source file or directory does not exist: $sourcePath" - ) - } - - // Check if source is a directory - val isDirResult = - AndroidShellExecutor.executeShellCommand( - "test -d ${shQuote(archiveSourcePath)} && echo 'true' || echo 'false'" - ) - val isDirectory = isDirResult.stdout.trim() == "true" - - // Create parent directory for zip file if needed - val zipDir = File(zipPath).parent - if (zipDir != null) { - AndroidShellExecutor.executeShellCommand("mkdir -p ${shQuote(zipDir)}") - } - - // Use Java's ZipOutputStream to create the zip file - // We'll use ADB to copy files to/from the device and process locally - val sourceFile = File(archiveSourcePath) - - // Initialize buffer for file copy - val buffer = ByteArray(1024) - - // Create temporary file for processing - using external files directory for - // better - // permissions - val tempDir = context.getExternalFilesDir(null) ?: context.cacheDir - val tempSourceFile = File(tempDir, "temp_source_${System.currentTimeMillis()}") - val tempZipFile = File(tempDir, "temp_zip_${System.currentTimeMillis()}.zip") - - try { - // Make sure the temp directory exists - tempDir.mkdirs() - - if (isDirectory) { - // For directories, we need to list all files and add them - // to the zip - val listResult = - AndroidShellExecutor.executeShellCommand("find ${shQuote(archiveSourcePath)} -type f") - val fileList = listResult.stdout.trim().split("\n").filter { it.isNotEmpty() } - - // Create ZIP output stream - val fos = FileOutputStream(tempZipFile) - val zos = ZipOutputStream(BufferedOutputStream(fos)) - - try { - for (filePath in fileList) { - // Get the file path relative to the source - // directory - val pathInsideSource = - if (archiveSourcePath == "/") { - filePath.removePrefix("/") - } else { - filePath.removePrefix("$archiveSourcePath/") - } - val relativePath = - if (includeRootDirectory && sourceFile.name.isNotEmpty()) { - "${sourceFile.name}/$pathInsideSource" - } else { - pathInsideSource - } - - // Copy the file from device to temp file - val pullResult = - AndroidShellExecutor.executeShellCommand( - "cat ${shQuote(filePath)} > ${shQuote(tempSourceFile.absolutePath)}" - ) - if (!pullResult.success) { - continue // Skip this file if we - // can't pull it - } - - // Add the file to the ZIP - val fis = FileInputStream(tempSourceFile) - val bis = BufferedInputStream(fis) - - try { - // Add ZIP entry - val entry = ZipEntry(relativePath) - zos.putNextEntry(entry) - - // Write file content to ZIP - var len: Int - while (bis.read(buffer).also { len = it } > 0) { - zos.write(buffer, 0, len) - } - - zos.closeEntry() - } finally { - bis.close() - fis.close() - tempSourceFile.delete() - } - } - } finally { - zos.close() - fos.close() - } - } else { - // For a single file, simpler process - // Copy the file from device to temp file - val pullResult = - AndroidShellExecutor.executeShellCommand( - "cat ${shQuote(archiveSourcePath)} > ${shQuote(tempSourceFile.absolutePath)}" - ) - if (!pullResult.success) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to read source file: ${pullResult.stderr}" - ) - } - - // Create zip file with single entry - val fos = FileOutputStream(tempZipFile) - val zos = ZipOutputStream(BufferedOutputStream(fos)) - - try { - val fis = FileInputStream(tempSourceFile) - val bis = BufferedInputStream(fis) - - try { - // Add ZIP entry - val entry = ZipEntry(sourceFile.name) - zos.putNextEntry(entry) - - // Write file content to ZIP - var len: Int - while (bis.read(buffer).also { len = it } > 0) { - zos.write(buffer, 0, len) - } - - zos.closeEntry() - } finally { - bis.close() - fis.close() - } - } finally { - zos.close() - fos.close() - } - } - - // Log information about the temp ZIP file - AppLogger.d( - TAG, - "Temp ZIP file created at: ${tempZipFile.absolutePath}, size: ${tempZipFile.length()} bytes" - ) - - // Push the ZIP file to the destination - val pushResult = - AndroidShellExecutor.executeShellCommand( - "cat ${shQuote(tempZipFile.absolutePath)} > ${shQuote(zipPath)}" - ) - if (!pushResult.success) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to write ZIP file: ${pushResult.stderr}" - ) - } - - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "zip", - path = sourcePath, - successful = true, - details = "Successfully compressed $sourcePath to $zipPath" - ), - error = "" - ) - } finally { - // Clean up temporary files - tempSourceFile.delete() - tempZipFile.delete() - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error compressing files", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error compressing files: ${e.message}" - ) - } - } - - /** Unzip a zip file */ - override suspend fun unzipFiles(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.unzipFiles(tool) - } - val zipPath = tool.parameters.find { it.name == "source" }?.value ?: "" - val destPath = tool.parameters.find { it.name == "destination" }?.value ?: "" - PathValidator.validateAndroidPath(zipPath, tool.name, "source")?.let { return it } - PathValidator.validateAndroidPath(destPath, tool.name, "destination")?.let { return it } - - if (isOperitInternalPath(zipPath) || isOperitInternalPath(destPath)) { - return super.unzipFiles(tool) - } - - val actualZipPath = zipPath - val actualDestPath = destPath - - if (zipPath.isBlank() || destPath.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Source and destination parameters are required" - ) - } - - return try { - ToolProgressBus.update(tool.name, -1f, "Unzipping...") - // Check if the zip file exists - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -f ${shQuote(zipPath)} && echo 'exists' || echo 'not exists'" - ) - if (existsResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Zip file does not exist: $zipPath" - ) - } - - // Create destination directory if it doesn't exist - AndroidShellExecutor.executeShellCommand("mkdir -p ${shQuote(destPath)};") - - val deviceUnzipCommands = - listOf( - "unzip -o ${shQuote(zipPath)} -d ${shQuote(destPath)}", - "toybox unzip -o ${shQuote(zipPath)} -d ${shQuote(destPath)}", - "busybox unzip -o ${shQuote(zipPath)} -d ${shQuote(destPath)}" - ) - - for (cmd in deviceUnzipCommands) { - try { - ToolProgressBus.update(tool.name, 0.02f, "Unzipping (device)...") - val extractedCount = AtomicInteger(0) - val progressFloor = AtomicInteger(2) - val stderrBuilder = StringBuilder() - - val process = AndroidShellExecutor.startShellProcess("$cmd;") - try { - val exitCode = coroutineScope { - val stdoutJob = launch { - process.stdout.collect { line -> - val t = line.trimStart() - val isProgressLine = - t.startsWith("inflating:") || - t.startsWith("extracting:") || - t.startsWith("creating:") || - t.startsWith(" inflating:") || - t.startsWith(" extracting:") - - if (isProgressLine) { - val extracted = extractedCount.incrementAndGet() - val p = (smoothProgress(extracted, 120f) * 100).toInt().coerceIn(0, 99) - updateProgressFloor(progressFloor, p) - if (extracted % 10 == 0) { - ToolProgressBus.update( - tool.name, - progressFloor.get() / 100f, - "Unzipping... extracted $extracted" - ) - } - } - } - } - val stderrJob = launch { - process.stderr.collect { line -> - if (line.isNotBlank()) { - stderrBuilder.appendLine(line) - } - - val t = line.trimStart() - val isProgressLine = - t.startsWith("inflating:") || - t.startsWith("extracting:") || - t.startsWith("creating:") || - t.startsWith(" inflating:") || - t.startsWith(" extracting:") - - if (isProgressLine) { - val extracted = extractedCount.incrementAndGet() - val p = (smoothProgress(extracted, 120f) * 100).toInt().coerceIn(0, 99) - updateProgressFloor(progressFloor, p) - if (extracted % 10 == 0) { - ToolProgressBus.update( - tool.name, - progressFloor.get() / 100f, - "Unzipping... extracted $extracted" - ) - } - } - } - } - val tickerJob = launch { - while (isActive && process.isAlive) { - delay(500) - val current = progressFloor.get() - if (current < 95) { - progressFloor.compareAndSet(current, current + 1) - ToolProgressBus.update( - tool.name, - progressFloor.get() / 100f, - "Unzipping..." - ) - } - } - } - - val code = process.waitFor() - stdoutJob.cancelAndJoin() - stderrJob.cancelAndJoin() - tickerJob.cancelAndJoin() - code - } - - if (exitCode == 0) { - ToolProgressBus.update(tool.name, 1f, "Unzip completed") - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "unzip", - path = zipPath, - successful = true, - details = "Successfully extracted $zipPath to $destPath" - ), - error = "" - ) - } - } finally { - if (process.isAlive) { - process.destroy() - } - } - } catch (e: Exception) { - AppLogger.w(TAG, "Device-side unzip failed for cmd: $cmd", e) - } - } - - // Create temporary files for processing - using external files directory - // for better - // permissions - val tempDir = context.getExternalFilesDir(null) ?: context.cacheDir - val tempZipFile = File(tempDir, "temp_zip_${System.currentTimeMillis()}.zip") - - try { - // Make sure the temp directory exists - tempDir.mkdirs() - - // Copy the zip file from device to temp file - val pullResult = - AndroidShellExecutor.executeShellCommand( - "cat ${shQuote(zipPath)} > ${shQuote(tempZipFile.absolutePath)}" - ) - if (!pullResult.success) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to read zip file: ${pullResult.stderr}" - ) - } - - // Log information about the temp ZIP file - AppLogger.d( - TAG, - "Temp ZIP file loaded at: ${tempZipFile.absolutePath}, size: ${tempZipFile.length()} bytes" - ) - - val totalEntries = try { - ZipFile(tempZipFile).use { it.size() } - } catch (_: Exception) { - null - } - var processedEntries = 0 - - // Extract files using ZipInputStream - val buffer = ByteArray(64 * 1024) - val zipInputStream = - ZipInputStream(BufferedInputStream(FileInputStream(tempZipFile))) - - try { - var zipEntry: ZipEntry? = zipInputStream.nextEntry - while (zipEntry != null) { - val fileName = zipEntry.name - if (fileName.startsWith("/") || fileName.contains("..") || fileName.contains("\\")) { - zipInputStream.closeEntry() - zipEntry = zipInputStream.nextEntry - continue - } - - val newFile = File(tempDir, fileName) - - val newFileCanonical = newFile.canonicalPath - val tempDirCanonical = tempDir.canonicalPath + File.separator - if (!newFileCanonical.startsWith(tempDirCanonical)) { - zipInputStream.closeEntry() - zipEntry = zipInputStream.nextEntry - continue - } - - // Skip directories, but make sure they exist - if (zipEntry.isDirectory) { - newFile.mkdirs() - val dirPath = "$destPath/$fileName" - AndroidShellExecutor.executeShellCommand("mkdir -p ${shQuote(dirPath)};") - zipInputStream.closeEntry() - zipEntry = zipInputStream.nextEntry - continue - } - - // Create parent directories if needed - val filePath = "$destPath/$fileName" - val parentDirPath = File(filePath).parent - if (parentDirPath != null) { - AndroidShellExecutor.executeShellCommand("mkdir -p ${shQuote(parentDirPath)};") - } - - newFile.parentFile?.mkdirs() - - // Extract file - val fileOutputStream = FileOutputStream(newFile) - - try { - var len: Int - while (zipInputStream.read(buffer).also { len = it } > 0) { - fileOutputStream.write(buffer, 0, len) - } - } finally { - fileOutputStream.close() - } - - // Copy the extracted file to device - val pushResult = - AndroidShellExecutor.executeShellCommand( - "cat ${shQuote(newFile.absolutePath)} > ${shQuote(filePath)}" - ) - if (!pushResult.success) { - AppLogger.w(TAG, "Failed to copy extracted file: $fileName to $filePath") - // Continue with next file - } - - // Clean up temp file - newFile.delete() - - zipInputStream.closeEntry() - processedEntries++ - val progress = - if (totalEntries != null && totalEntries > 0) { - (processedEntries.toFloat() / totalEntries.toFloat()).coerceIn(0f, 1f) - } else { - -1f - } - val msg = - if (totalEntries != null && totalEntries > 0) { - "Unzipping... ($processedEntries/$totalEntries)" - } else { - "Unzipping..." - } - ToolProgressBus.update(tool.name, progress, msg) - zipEntry = zipInputStream.nextEntry - } - } finally { - zipInputStream.close() - } - - ToolProgressBus.update(tool.name, 1f, "Unzip completed") - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "unzip", - path = zipPath, - successful = true, - details = "Successfully extracted $zipPath to $destPath" - ), - error = "" - ) - } finally { - tempZipFile.delete() - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error extracting zip file", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error extracting zip file: ${e.message}" - ) - } finally { - ToolProgressBus.clear() - } - } - - /** 打开文件 使用系统默认应用打开文件 */ - override suspend fun openFile(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.openFile(tool) - } - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - - if (isOperitInternalPath(path)) { - return super.openFile(tool) - } - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "open", - path = "", - successful = false, - details = "Must provide path parameter" - ), - error = "Must provide path parameter" - ) - } - - return try { - // 首先检查文件是否存在 - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -f '$path' && echo 'exists' || echo 'not exists'" - ) - if (existsResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "open", - path = path, - successful = false, - details = "File does not exist: $path" - ), - error = "File does not exist: $path" - ) - } - - // 获取文件MIME类型 - val mimeTypeResult = - AndroidShellExecutor.executeShellCommand("file --mime-type -b '$path'") - val mimeType = - if (mimeTypeResult.success) mimeTypeResult.stdout.trim() - else "application/octet-stream" - - // 使用Android intent打开文件 - val command = "am start -a android.intent.action.VIEW -d 'file://$path' -t '$mimeType'" - val result = AndroidShellExecutor.executeShellCommand(command) - - if (result.success) { - return ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "open", - path = path, - successful = true, - details = "Opened file with system app: $path" - ), - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "open", - path = path, - successful = false, - details = "Failed to open file: ${result.stderr}" - ), - error = "Failed to open file: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error opening file", e) - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "open", - path = path, - successful = false, - details = "Error opening file: ${e.message}" - ), - error = "Error opening file: ${e.message}" - ) - } - } - - /** 分享文件 调用系统分享功能 */ - override suspend fun shareFile(tool: AITool): ToolResult { - val environment = tool.parameters.find { it.name == "environment" }?.value - if (environment == "linux") { - return super.shareFile(tool) - } - val path = tool.parameters.find { it.name == "path" }?.value ?: "" - PathValidator.validateAndroidPath(path, tool.name)?.let { return it } - val title = tool.parameters.find { it.name == "title" }?.value ?: "Share File" - - if (isOperitInternalPath(path)) { - return super.shareFile(tool) - } - - if (path.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "share", - path = "", - successful = false, - details = "Must provide path parameter" - ), - error = "Must provide path parameter" - ) - } - - return try { - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -f ${shQuote(path)} && echo 'exists' || echo 'not exists'" - ) - if (existsResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "share", - path = path, - successful = false, - details = "File does not exist: $path" - ), - error = "File does not exist: $path" - ) - } - - val stagingRoot = (context.getExternalFilesDir(null) ?: context.cacheDir) - val stagingDir = File(stagingRoot, "share_tmp") - if (!stagingDir.exists()) { - stagingDir.mkdirs() - } - - val sourceName = File(path).name.ifBlank { "shared_file" } - val stagedFile = File(stagingDir, "${System.currentTimeMillis()}_$sourceName") - val copyResult = - AndroidShellExecutor.executeShellCommand( - "cat ${shQuote(path)} > ${shQuote(stagedFile.absolutePath)}" - ) - - if (!copyResult.success || !stagedFile.exists()) { - return ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "share", - path = path, - successful = false, - details = "Failed to prepare file for sharing: ${copyResult.stderr}" - ), - error = "Failed to prepare file for sharing: ${copyResult.stderr}" - ) - } - - val extension = stagedFile.extension.lowercase(Locale.US) - val mimeType = - if (extension.isNotEmpty()) { - MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) - ?: "application/octet-stream" - } else { - "application/octet-stream" - } - - val authority = "${context.packageName}.fileprovider" - val contentUri = FileProvider.getUriForFile(context, authority, stagedFile) - val shareIntent = - Intent(Intent.ACTION_SEND).apply { - type = mimeType - putExtra(Intent.EXTRA_STREAM, contentUri) - putExtra(Intent.EXTRA_SUBJECT, title) - clipData = - ClipData.newUri( - context.contentResolver, - stagedFile.name, - contentUri - ) - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - } - val chooserIntent = - Intent.createChooser(shareIntent, title).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - } - context.startActivity(chooserIntent) - - ToolResult( - toolName = tool.name, - success = true, - result = - FileOperationData( - operation = "share", - path = path, - successful = true, - details = "Opened share interface, sharing file: $path" - ), - error = "" - ) - } catch (e: ActivityNotFoundException) { - AppLogger.e(TAG, "No activity found to handle sharing file: $path", e) - ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "share", - path = path, - successful = false, - details = "No application found to share this file type." - ), - error = "No application found to share this file type." - ) - } catch (e: Exception) { - AppLogger.e(TAG, "Error sharing file", e) - ToolResult( - toolName = tool.name, - success = false, - result = - FileOperationData( - operation = "share", - path = path, - successful = false, - details = "Error sharing file: ${e.message}" - ), - error = "Error sharing file: ${e.message}" - ) - } - } - - /** 下载文件 从网络URL下载文件到指定路径 */ - override suspend fun downloadFile(tool: AITool): ToolResult { - return super.downloadFile(tool) - } - - /** Write base64 encoded content to a binary file */ - -// if (path.isBlank()) { -// return ToolResult( -// toolName = tool.name, -// success = false, -// result = -// FileOperationData( -// operation = "write_binary", -// path = "", -// successful = false, -// details = "Path parameter is required" -// ), -// error = "Path parameter is required" -// ) -// } - -// return try { -// // Ensure parent directory exists -// val directory = File(path).parent -// if (directory != null) { -// AndroidShellExecutor.executeShellCommand("mkdir -p '$directory'") -// } - -// // Write content using echo and base64 decode -// val writeResult = -// AndroidShellExecutor.executeShellCommand( -// "echo '$base64Content' | base64 -d > '$path'" -// ) - -// if (!writeResult.success) { -// return ToolResult( -// toolName = tool.name, -// success = false, -// result = -// FileOperationData( -// operation = "write_binary", -// path = path, -// successful = false, -// details = "Failed to write binary file: ${writeResult.stderr}" -// ), -// error = "Failed to write binary file: ${writeResult.stderr}" -// ) -// } - -// // Verify write was successful -// val sizeResult = -// AndroidShellExecutor.executeShellCommand("stat -c %s '$path' 2>/dev/null || echo '0'") -// val size = sizeResult.stdout.trim().toLongOrNull() ?: 0 -// val originalSize = -// android.util.Base64.decode(base64Content, android.util.Base64.NO_WRAP).size - -// if (size.toLong() != originalSize.toLong()) { -// return ToolResult( -// toolName = tool.name, -// success = false, -// result = -// FileOperationData( -// operation = "write_binary", -// path = path, -// successful = false, -// details = "Write completed but file size mismatch. Expected: $originalSize, Got: $size. Possible write failure." -// ), -// error = "Write completed but file size mismatch. Expected: $originalSize, Got: $size. Possible write failure." -// ) -// } - -// return ToolResult( -// toolName = tool.name, -// success = true, -// result = -// FileOperationData( -// operation = "write_binary", -// path = path, -// successful = true, -// details = "Binary content written to $path" -// ), -// error = "" -// ) -// } catch (e: Exception) { -// AppLogger.e(TAG, "Error writing binary file", e) -// return ToolResult( -// toolName = tool.name, -// success = false, -// result = -// FileOperationData( -// operation = "write_binary", -// path = path, -// successful = false, -// details = "Error writing binary file: ${e.message}" -// ), -// error = "Error writing binary file: ${e.message}" -// ) -// } -// } -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerSystemOperationTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerSystemOperationTools.kt deleted file mode 100644 index 5450332bec..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerSystemOperationTools.kt +++ /dev/null @@ -1,527 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.debugger - -import android.content.Context -import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.AppOperationData -import com.ai.assistance.operit.core.tools.NotificationData -import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.SystemSettingData -import com.ai.assistance.operit.core.tools.defaultTool.accessbility.AccessibilitySystemOperationTools -import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor -import com.ai.assistance.operit.data.model.AITool -import com.ai.assistance.operit.data.model.ToolResult - -/** 调试级别的系统操作工具,继承无障碍版本, 并使用shell命令覆盖部分实现 */ -open class DebuggerSystemOperationTools(private val context: Context) : - AccessibilitySystemOperationTools(context) { - - private val TAG = "DebuggerSystemTools" - - override suspend fun modifySystemSetting(tool: AITool): ToolResult { - if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { - return super.modifySystemSetting(tool) - } - - val setting = tool.parameters.find { it.name == "setting" }?.value ?: "" - val value = tool.parameters.find { it.name == "value" }?.value ?: "" - val namespace = tool.parameters.find { it.name == "namespace" }?.value ?: "system" - - if (setting.isBlank() || value.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Must provide setting and value parameters" - ) - } - - val validNamespaces = listOf("system", "secure", "global") - if (!validNamespaces.contains(namespace)) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Namespace must be one of: ${validNamespaces.joinToString(", ")}" - ) - } - - return try { - val command = "settings put $namespace $setting $value" - val result = AndroidShellExecutor.executeShellCommand(command) - - if (result.success) { - val resultData = - SystemSettingData(namespace = namespace, setting = setting, value = value) - - return ToolResult( - toolName = tool.name, - success = true, - result = resultData, - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to set setting: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error modifying system setting", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error modifying system setting: ${e.message}" - ) - } - } - - override suspend fun getSystemSetting(tool: AITool): ToolResult { - if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { - return super.getSystemSetting(tool) - } - - val setting = tool.parameters.find { it.name == "setting" }?.value ?: "" - val namespace = tool.parameters.find { it.name == "namespace" }?.value ?: "system" - - if (setting.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Must provide setting parameter" - ) - } - - val validNamespaces = listOf("system", "secure", "global") - if (!validNamespaces.contains(namespace)) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Namespace must be one of: ${validNamespaces.joinToString(", ")}" - ) - } - - return try { - val command = "settings get $namespace $setting" - val result = AndroidShellExecutor.executeShellCommand(command) - - if (result.success) { - val resultData = - SystemSettingData( - namespace = namespace, - setting = setting, - value = result.stdout.trim() - ) - - return ToolResult( - toolName = tool.name, - success = true, - result = resultData, - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to get setting: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error getting system setting", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error getting system setting: ${e.message}" - ) - } - } - - override suspend fun installApp(tool: AITool): ToolResult { - if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { - return super.installApp(tool) - } - - val apkPath = tool.parameters.find { it.name == "path" }?.value ?: "" - - if (apkPath.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Must provide apk_path parameter" - ) - } - - if (DebuggerFileSystemTools.isOperitInternalPath(apkPath)) { - AppLogger.d( - TAG, - "installApp detected Operit internal path, delegating to AccessibilitySystemOperationTools" - ) - return super.installApp(tool) - } - - val existsResult = - AndroidShellExecutor.executeShellCommand( - "test -f $apkPath && echo 'exists' || echo 'not exists'" - ) - if (existsResult.stdout.trim() != "exists") { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "APK file does not exist: $apkPath" - ) - } - - return try { - val command = "pm install -r $apkPath" - val result = AndroidShellExecutor.executeShellCommand(command) - - if (result.success && result.stdout.contains("Success")) { - val resultData = - AppOperationData( - operationType = "install", - packageName = apkPath, - success = true - ) - - return ToolResult( - toolName = tool.name, - success = true, - result = resultData, - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Installation failed: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error installing app", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error installing app: ${e.message}" - ) - } - } - - override suspend fun uninstallApp(tool: AITool): ToolResult { - if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { - return super.uninstallApp(tool) - } - - val packageName = tool.parameters.find { it.name == "package_name" }?.value ?: "" - val keepData = tool.parameters.find { it.name == "keep_data" }?.value?.toBoolean() ?: false - - if (packageName.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Must provide package_name parameter" - ) - } - - val checkCommand = "pm list packages | grep -c \"$packageName\"" - val checkResult = AndroidShellExecutor.executeShellCommand(checkCommand) - - if (checkResult.stdout.trim() == "0") { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "App not installed: $packageName" - ) - } - - return try { - val command = - if (keepData) { - "pm uninstall -k $packageName" - } else { - "pm uninstall $packageName" - } - - val result = AndroidShellExecutor.executeShellCommand(command) - - if (result.success && result.stdout.contains("Success")) { - val details = if (keepData) "(keep data)" else "" - val resultData = - AppOperationData( - operationType = "uninstall", - packageName = packageName, - success = true, - details = details - ) - - return ToolResult( - toolName = tool.name, - success = true, - result = resultData, - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Uninstallation failed: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error uninstalling app", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error uninstalling app: ${e.message}" - ) - } - } - - override suspend fun startApp(tool: AITool): ToolResult { - if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { - return super.startApp(tool) - } - - val packageName = tool.parameters.find { it.name == "package_name" }?.value ?: "" - val activity = tool.parameters.find { it.name == "activity" }?.value ?: "" - - if (packageName.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Must provide package_name parameter" - ) - } - - return try { - val command: String - if (activity.isBlank()) { - // 使用 am start 命令而不是 monkey,避免修改系统设置(如屏幕旋转) - // 先获取应用的主 Activity,然后使用 -n 参数启动 - val resolveCmd = "cmd package resolve-activity --brief $packageName 2>/dev/null | tail -n 1" - val resolveResult = AndroidShellExecutor.executeShellCommand(resolveCmd) - - if (resolveResult.success && resolveResult.stdout.isNotBlank()) { - val output = resolveResult.stdout.trim() - // resolve-activity 返回格式可能是:package/activity 或只有 activity - // 也可能返回多行,最后一行是组件名 - val lines = output.lines().filter { it.isNotBlank() && !it.startsWith("name=") } - val mainActivity = lines.lastOrNull()?.trim() ?: output.trim() - - // 如果返回的是完整组件名(package/activity),直接使用 - command = if (mainActivity.contains('/')) { - "am start -n $mainActivity" - } else { - // 如果只返回了 Activity 名,拼接包名 - "am start -n $packageName/$mainActivity" - } - AppLogger.d(TAG, "Resolved main Activity: $mainActivity, using command: $command") - } else { - // 如果无法解析 Activity,返回错误 - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Cannot resolve app main Activity. Please provide activity parameter or ensure app is properly installed. Package: $packageName" - ) - } - } else { - command = "am start -n $packageName/$activity" - } - - val result = AndroidShellExecutor.executeShellCommand(command) - - if (result.success) { - val details = if (activity.isNotBlank()) "Activity: $activity" else "" - val resultData = - AppOperationData( - operationType = "start", - packageName = packageName, - success = true, - details = details - ) - - return ToolResult( - toolName = tool.name, - success = true, - result = resultData, - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to start app: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error starting app", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error starting app: ${e.message}" - ) - } - } - - override suspend fun stopApp(tool: AITool): ToolResult { - if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { - return super.stopApp(tool) - } - - val packageName = tool.parameters.find { it.name == "package_name" }?.value ?: "" - - if (packageName.isBlank()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Must provide package_name parameter" - ) - } - - return try { - val command = "am force-stop $packageName" - val result = AndroidShellExecutor.executeShellCommand(command) - - if (result.success) { - val resultData = - AppOperationData( - operationType = "stop", - packageName = packageName, - success = true - ) - - return ToolResult( - toolName = tool.name, - success = true, - result = resultData, - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to stop app: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error stopping app", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error stopping app: ${e.message}" - ) - } - } - - override suspend fun getNotifications(tool: AITool): ToolResult { - if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { - return super.getNotifications(tool) - } - - val limit = tool.parameters.find { it.name == "limit" }?.value?.toIntOrNull() ?: 10 - val includeOngoing = - tool.parameters.find { it.name == "include_ongoing" }?.value?.toBoolean() ?: false - - return try { - val command = - if (includeOngoing) { - "dumpsys notification --noredact | grep -E 'pkg=|text=' | head -${limit * 2}" - } else { - "dumpsys notification --noredact | grep -v 'ongoing' | grep -E 'pkg=|text=' | head -${limit * 2}" - } - - val result = AndroidShellExecutor.executeShellCommand(command) - - if (result.success) { - val lines = result.stdout.split("\n") - val notifications = mutableListOf() - - var currentPackage = "" - var currentText = "" - - for (line in lines) { - when { - line.contains("pkg=") -> { - if (currentPackage.isNotEmpty() && currentText.isNotEmpty()) { - notifications.add( - NotificationData.Notification( - packageName = currentPackage, - text = currentText, - timestamp = System.currentTimeMillis() - ) - ) - currentText = "" - } - - val pkgMatch = Regex("pkg=(\\S+)").find(line) - currentPackage = pkgMatch?.groupValues?.getOrNull(1) ?: "" - } - line.contains("text=") -> { - val textMatch = Regex("text=(.+)").find(line) - currentText = textMatch?.groupValues?.getOrNull(1) ?: "" - } - } - } - - if (currentPackage.isNotEmpty() && currentText.isNotEmpty()) { - notifications.add( - NotificationData.Notification( - packageName = currentPackage, - text = currentText, - timestamp = System.currentTimeMillis() - ) - ) - } - - val resultData = - NotificationData( - notifications = notifications, - timestamp = System.currentTimeMillis() - ) - - return ToolResult( - toolName = tool.name, - success = true, - result = resultData, - error = "" - ) - } else { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to get notifications: ${result.stderr}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error getting notifications", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error getting notifications: ${e.message}" - ) - } - } -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerUITools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerUITools.kt deleted file mode 100644 index 46da0c842f..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/DebuggerUITools.kt +++ /dev/null @@ -1,1359 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.debugger - -import android.annotation.SuppressLint -import android.content.ClipData -import android.content.ClipboardManager -import android.content.Context -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import java.io.File -import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.SimplifiedUINode -import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.UIActionResultData -import com.ai.assistance.operit.core.tools.UIPageResultData -import com.ai.assistance.operit.core.tools.defaultTool.accessbility.AccessibilityUITools -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardUITools -import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor -import com.ai.assistance.operit.core.tools.system.ShellIdentity -import com.ai.assistance.operit.data.model.AITool -import com.ai.assistance.operit.data.model.ToolResult -import java.io.StringReader -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import org.json.JSONObject -import org.xmlpull.v1.XmlPullParser -import org.xmlpull.v1.XmlPullParserFactory -import com.ai.assistance.operit.util.files.OperitPaths -import com.ai.assistance.operit.core.tools.system.uiautomator.UiAutomatorDumpGuard - -/** 调试级别的UI工具,通过Shell命令实现UI操作,继承无障碍版本 */ -open class DebuggerUITools(context: Context) : AccessibilityUITools(context) { - - companion object { - private const val TAG = "DebuggerUITools" - } - - protected open val uiShellIdentity: ShellIdentity? = null - - protected suspend fun executeUiShellCommand(command: String): AndroidShellExecutor.CommandResult { - // 读取页面和按元素点击共用入口;Root 子类也必须保存并恢复调用前的旋转设置。 - if (command.startsWith("uiautomator dump ")) { - return UiAutomatorDumpGuard.execute(command) { protectedCommand -> - AndroidShellExecutor.executeShellCommand(protectedCommand, uiShellIdentity) - } - } - return AndroidShellExecutor.executeShellCommand(command, uiShellIdentity) - } - - protected suspend fun shouldUseAccessibility(tool: AITool): Boolean = - !hasDisplayParam(tool) && PermissionCapabilityResolver.uiSnapshot(context).canUseAccessibility - - /** 是否包含 display 相关参数(有的话强制走 Shell,不走无障碍) */ - private fun hasDisplayParam(tool: AITool): Boolean { - return tool.parameters.any { param -> - param.name.equals("display", ignoreCase = true) - } - } - - private fun getDisplayArg(tool: AITool): String { - val display = tool.parameters.find { it.name.equals("display", ignoreCase = true) }?.value?.trim() - return if (!display.isNullOrEmpty()) "-d $display " else "" - } - - /** 使用Shell命令实现点击操作 */ - override suspend fun tap(tool: AITool): ToolResult { - if (shouldUseAccessibility(tool)) { - AppLogger.d(TAG, "无障碍服务已启用,使用无障碍点击") - return super.tap(tool) - } - - val x = tool.parameters.find { it.name == "x" }?.value?.toIntOrNull() - val y = tool.parameters.find { it.name == "y" }?.value?.toIntOrNull() - - if (x == null || y == null) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = - "Missing or invalid coordinates. Both 'x' and 'y' must be valid integers." - ) - } - withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } - - // 使用Shell命令执行点击 - try { - AppLogger.d(TAG, "Attempting to tap at coordinates: ($x, $y) via shell command") - val command = "input ${getDisplayArg(tool)}tap $x $y" - val result = executeUiShellCommand(command) - - if (result.success) { - AppLogger.d(TAG, "Tap successful at coordinates: ($x, $y)") - withContext(Dispatchers.Main) { - operationOverlay.showTap(x, y) - operationOverlay.hide() - } - return ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "tap", - actionDescription = - "Successfully tapped at coordinates ($x, $y) via shell command", - coordinates = Pair(x, y) - ), - error = "" - ) - } else { - AppLogger.e(TAG, "Tap failed at coordinates: ($x, $y), error: ${result.stderr}") - withContext(Dispatchers.Main) { - operationOverlay.hide() // 隐藏反馈(在主线程上执行) - } - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = - "Failed to tap at coordinates ($x, $y): ${result.stderr ?: "Unknown error"}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error tapping at coordinates ($x, $y)", e) - withContext(Dispatchers.Main) { - operationOverlay.hide() // 隐藏反馈(在主线程上执行) - } - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error tapping at coordinates: ${e.message ?: "Unknown exception"}" - ) - } - } - - override suspend fun longPress(tool: AITool): ToolResult { - if (shouldUseAccessibility(tool)) { - AppLogger.d(TAG, "无障碍服务已启用,使用无障碍长按") - return super.longPress(tool) - } - - val x = tool.parameters.find { it.name == "x" }?.value?.toIntOrNull() - val y = tool.parameters.find { it.name == "y" }?.value?.toIntOrNull() - - if (x == null || y == null) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Missing or invalid coordinates. Both 'x' and 'y' must be valid integers." - ) - } - withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } - - try { - AppLogger.d(TAG, "Attempting to long press at coordinates: ($x, $y) via shell command") - // Use swipe to simulate long press - val command = "input ${getDisplayArg(tool)}swipe $x $y $x $y 800" - val result = executeUiShellCommand(command) - - if (result.success) { - AppLogger.d(TAG, "Long press successful at coordinates: ($x, $y)") - withContext(Dispatchers.Main) { - operationOverlay.showTap(x, y) - operationOverlay.hide() - } - return ToolResult( - toolName = tool.name, - success = true, - result = UIActionResultData( - actionType = "long_press", - actionDescription = "Successfully long pressed at ($x, $y) via shell command", - coordinates = Pair(x, y) - ), - error = "" - ) - } else { - AppLogger.e(TAG, "Long press failed at coordinates: ($x, $y), error: ${result.stderr}") - withContext(Dispatchers.Main) { operationOverlay.hide() } - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to long press at coordinates ($x, $y): ${result.stderr ?: "Unknown error"}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error long pressing at coordinates ($x, $y)", e) - withContext(Dispatchers.Main) { operationOverlay.hide() } - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error long pressing at coordinates: ${e.message ?: "Unknown exception"}" - ) - } - } - - /** 使用Shell命令实现滑动操作 */ - override suspend fun swipe(tool: AITool): ToolResult { - if (shouldUseAccessibility(tool)) { - AppLogger.d(TAG, "无障碍服务已启用,使用无障碍滑动") - return super.swipe(tool) - } - - val startX = tool.parameters.find { it.name == "start_x" }?.value?.toIntOrNull() - val startY = tool.parameters.find { it.name == "start_y" }?.value?.toIntOrNull() - val endX = tool.parameters.find { it.name == "end_x" }?.value?.toIntOrNull() - val endY = tool.parameters.find { it.name == "end_y" }?.value?.toIntOrNull() - val duration = tool.parameters.find { it.name == "duration" }?.value?.toIntOrNull() ?: 300 - - if (startX == null || startY == null || endX == null || endY == null) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = - "Missing or invalid coordinates. 'start_x', 'start_y', 'end_x', and 'end_y' must be valid integers." - ) - } - withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } - - try { - AppLogger.d( - TAG, - "Attempting to swipe from ($startX, $startY) to ($endX, $endY) with duration $duration ms via shell command" - ) - val command = "input ${getDisplayArg(tool)}swipe $startX $startY $endX $endY $duration" - val result = executeUiShellCommand(command) - - if (result.success) { - AppLogger.d(TAG, "Swipe successful from ($startX, $startY) to ($endX, $endY)") - withContext(Dispatchers.Main) { - operationOverlay.showSwipe(startX, startY, endX, endY) - operationOverlay.hide() - } - return ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "swipe", - actionDescription = - "Successfully performed swipe from ($startX, $startY) to ($endX, $endY) via shell command" - ), - error = "" - ) - } else { - AppLogger.e(TAG, "Swipe failed: ${result.stderr}") - withContext(Dispatchers.Main) { - operationOverlay.hide() // 隐藏反馈(在主线程上执行) - } - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to perform swipe: ${result.stderr ?: "Unknown error"}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error performing swipe", e) - withContext(Dispatchers.Main) { - operationOverlay.hide() // 隐藏反馈(在主线程上执行) - } - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error performing swipe: ${e.message ?: "Unknown exception"}" - ) - } - } - - /** 使用Shell命令点击元素 */ - override suspend fun clickElement(tool: AITool): ToolResult { - if (shouldUseAccessibility(tool)) { - AppLogger.d(TAG, "无障碍服务已启用,使用无障碍点击元素") - return super.clickElement(tool) - } - - val resourceId = tool.parameters.find { it.name == "resourceId" }?.value - val className = tool.parameters.find { it.name == "className" }?.value - val contentDesc = tool.parameters.find { it.name == "contentDesc" }?.value - // index kept for future use - tool.parameters.find { it.name == "index" }?.value?.toIntOrNull() ?: 0 - val bounds = tool.parameters.find { it.name == "bounds" }?.value - - if (resourceId == null && className == null && bounds == null && contentDesc == null) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = - "Missing element identifier. Provide at least one of: 'resourceId', 'className', 'contentDesc', or 'bounds'." - ) - } - - // 如果提供了边界坐标,直接点击 - if (bounds != null) { - try { - // 解析边界坐标格式 [left,top][right,bottom] - val boundsPattern = "\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]".toRegex() - val matchResult = boundsPattern.find(bounds) - - if (matchResult == null || matchResult.groupValues.size < 5) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Invalid bounds format. Should be: [left,top][right,bottom]" - ) - } - - // 提取坐标 - val x1 = matchResult.groupValues[1].toInt() - val y1 = matchResult.groupValues[2].toInt() - val x2 = matchResult.groupValues[3].toInt() - val y2 = matchResult.groupValues[4].toInt() - - // 计算中心点 - val centerX = (x1 + x2) / 2 - val centerY = (y1 + y2) / 2 - - // 利用tap方法点击中心点 - val tapTool = - AITool( - name = "tap", - parameters = - listOf( - com.ai.assistance.operit.data.model.ToolParameter( - "x", - centerX.toString() - ), - com.ai.assistance.operit.data.model.ToolParameter( - "y", - centerY.toString() - ) - ) - ) - - return tap(tapTool) - } catch (e: Exception) { - AppLogger.e(TAG, "Error processing bounds", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error processing bounds: ${e.message}" - ) - } - } - - // 使用uiautomator获取和点击元素 - return clickElementWithUiautomator(tool) - } - - /** 使用Shell命令设置输入文本 */ - override suspend fun setInputText(tool: AITool): ToolResult { - if (shouldUseAccessibility(tool)) { - AppLogger.d(TAG, "无障碍服务已启用,使用无障碍设置文本") - return super.setInputText(tool) - } - - val text = tool.parameters.find { it.name == "text" }?.value ?: "" - - try { - // 获取屏幕中心作为文本输入的位置 - val displayMetrics = context.resources.displayMetrics - val centerX = displayMetrics.widthPixels / 2 - val centerY = displayMetrics.heightPixels / 2 - - // 显示文本输入反馈(在主线程上执行) - withContext(Dispatchers.Main) { operationOverlay.showTextInput(centerX, centerY, text) } - - // 使用KEYCODE_CLEAR清除字段,这比模拟CTRL+A和DEL更直接 - AppLogger.d(TAG, "Clearing text field with KEYCODE_CLEAR") - val clearCommand = "input ${getDisplayArg(tool)}keyevent KEYCODE_CLEAR" - executeUiShellCommand(clearCommand) - - // 短暂延迟 - kotlinx.coroutines.delay(300) - - // 如果文本为空,只需清除字段 - if (text.isEmpty()) { - // 成功后主动隐藏overlay - withContext(Dispatchers.Main) { operationOverlay.hide() } - return ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "textInput", - actionDescription = - "Successfully cleared input field via shell command" - ), - error = "" - ) - } - - // 使用原生复制和ADB粘贴来输入文本,这比'input text'更可靠 - AppLogger.d(TAG, "Setting text to clipboard and pasting via ADB: $text") - withContext(Dispatchers.Main) { - val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip = ClipData.newPlainText("operit_input", text) - clipboard.setPrimaryClip(clip) - } - - // 短暂延迟以确保剪贴板操作完成 - kotlinx.coroutines.delay(100) - - // 执行粘贴命令 - val pasteCommand = "input ${getDisplayArg(tool)}keyevent KEYCODE_PASTE" - val pasteResult = executeUiShellCommand(pasteCommand) - - if (pasteResult.success) { - // 成功后主动隐藏overlay - withContext(Dispatchers.Main) { operationOverlay.hide() } - return ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "textInput", - actionDescription = - "Successfully set input text to: $text via clipboard paste" - ), - error = "" - ) - } else { - withContext(Dispatchers.Main) { - operationOverlay.hide() // 隐藏反馈(在主线程上执行) - } - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to paste text from clipboard: ${pasteResult.stderr ?: "Unknown error"}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error setting input text", e) - withContext(Dispatchers.Main) { - operationOverlay.hide() // 隐藏反馈(在主线程上执行) - } - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error setting input text: ${e.message ?: "Unknown exception"}" - ) - } - } - - /** 使用Shell命令实现按键操作 */ - override suspend fun pressKey(tool: AITool): ToolResult { - val keyCode = tool.parameters.find { it.name == "key_code" }?.value - - if (keyCode == null) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Missing 'key_code' parameter." - ) - } - - if (shouldUseAccessibility(tool) && - (accessibilityKeyAction(keyCode) != null || - !PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) - ) { - return super.pressKey(tool) - } - - val command = "input ${getDisplayArg(tool)}keyevent $keyCode" - - return try { - val result = executeUiShellCommand(command) - - if (result.success) { - ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "keyPress", - actionDescription = - "Successfully pressed key: $keyCode via shell command" - ), - error = "" - ) - } else { - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to press key: ${result.stderr ?: "Unknown error"}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error pressing key", e) - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error pressing key: ${e.message ?: "Unknown exception"}" - ) - } - } - - override suspend fun captureScreenshotToFile(tool: AITool): Pair?> { - if (!PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) { - return if (hasDisplayParam(tool)) Pair(null, null) else super.captureScreenshotToFile(tool) - } - return try { - val screenshotDir = OperitPaths.cleanOnExitDir() - - val shortName = System.currentTimeMillis().toString().takeLast(4) - val file = File(screenshotDir, "$shortName.png") - - // 1) Debugger 模式下优先尝试 Shell 模式 (ADB) 截图 - AppLogger.d(TAG, "captureScreenshotToFile: Attempting shell screencap") - val command = "screencap -p ${file.absolutePath}" - val result = executeUiShellCommand(command) - - if (result.success && file.exists()) { - val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } - BitmapFactory.decodeFile(file.absolutePath, options) - val dimensions = if (options.outWidth > 0 && options.outHeight > 0) { - Pair(options.outWidth, options.outHeight) - } else { - null - } - AppLogger.d(TAG, "captureScreenshotToFile: Shell screencap success") - return Pair(file.absolutePath, dimensions) - } - - // 2) 如果 Shell 失败,作为回退尝试无障碍截图 (调用父类) - AppLogger.w(TAG, "captureScreenshotToFile: Shell screencap failed, falling back to accessibility") - if (hasDisplayParam(tool)) Pair(null, null) else super.captureScreenshotToFile(tool) - } catch (e: Exception) { - AppLogger.e(TAG, "captureScreenshotToFile failed in Debugger", e) - Pair(null, null) - } - } - - override suspend fun captureScreenshot(tool: AITool): Pair?> { - return captureScreenshotToFile(tool) - } - - override suspend fun captureScreenshotBitmap(tool: AITool): Pair?> { - val (filePath, dimensions) = captureScreenshot(tool) - if (filePath == null) { - return Pair(null, dimensions) - } - - val bitmap = BitmapFactory.decodeFile(filePath) ?: return Pair(null, dimensions) - val resolvedDimensions = dimensions ?: Pair(bitmap.width, bitmap.height) - return Pair(bitmap, resolvedDimensions) - } - - /** 使用Shell命令获取页面信息 */ - override suspend fun getPageInfo(tool: AITool): ToolResult { - if (shouldUseAccessibility(tool)) { - AppLogger.d(TAG, "无障碍服务已启用,使用无障碍获取页面信息") - val result = super.getPageInfo(tool) - if (result.success || !PermissionCapabilityResolver.shellSnapshot(context).hasPrivilegedShell) return result - } - - val format = tool.parameters.find { it.name == "format" }?.value ?: "xml" - // detail kept for future use - tool.parameters.find { it.name == "detail" }?.value ?: "summary" - - if (format !in listOf("xml", "json")) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Invalid format specified. Must be 'xml' or 'json'." - ) - } - - return try { - // 获取UI数据 - val uiData = getUIDataFromShell(tool) - if (uiData == null) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to retrieve UI data." - ) - } - - // 解析当前窗口信息 - val focusInfo = extractFocusInfoFromShell(uiData.windowInfo) - - // 简化布局信息 - val simplifiedLayout = simplifyLayoutFromXml(uiData.uiXml) - - // 创建结构化数据 - val resultData = - UIPageResultData( - packageName = focusInfo.packageName ?: "Unknown", - activityName = focusInfo.activityName ?: "Unknown", - uiElements = simplifiedLayout - ) - - ToolResult(toolName = tool.name, success = true, result = resultData, error = "") - } catch (e: Exception) { - AppLogger.e(TAG, "Error getting page info", e) - ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error getting page info: ${e.message}" - ) - } - } - - /** UI数据类,保存XML和窗口信息 */ - private data class UIData(val uiXml: String, val windowInfo: String) - - /** 获取UI数据,使用Shell命令,严格遵守工具参数中的 display(如有) */ - private suspend fun getUIDataFromShell(tool: AITool): UIData? { - return try { - // 使用ADB命令获取UI dump - AppLogger.d(TAG, "使用ADB命令获取UI数据") - - val displayId = tool.parameters - .find { it.name.equals("display", ignoreCase = true) } - ?.value - ?.trim() - ?.takeIf { it.isNotEmpty() } - - // 执行UI dump命令,只有在显式提供 display 参数时才使用 --display-id - val dumpResult = if (displayId != null) { - val cmd = "uiautomator dump --display-id $displayId /sdcard/window_dump.xml" - AppLogger.d(TAG, "UI dump using explicit display-id=$displayId") - executeUiShellCommand(cmd) - } else { - executeUiShellCommand("uiautomator dump /sdcard/window_dump.xml") - } - - if (!dumpResult.success) { - AppLogger.e(TAG, "uiautomator dump失败: ${dumpResult.stderr}") - return null - } - AppLogger.d(TAG, "uiautomator dump成功: ${dumpResult.stdout}") - - // 读取dump文件内容 - val readResult = executeUiShellCommand("cat /sdcard/window_dump.xml") - if (!readResult.success) { - AppLogger.e(TAG, "读取UI dump文件失败: ${readResult.stderr}") - return null - } - - // 获取窗口信息 - var windowInfo = getWindowInfoFromShell() - - // 如果窗口信息为空,尝试延迟后重试一次 - if (windowInfo.isEmpty()) { - AppLogger.w(TAG, "首次获取窗口信息失败,延迟500ms后重试") - kotlinx.coroutines.delay(500) - windowInfo = getWindowInfoFromShell() - } - - UIData(readResult.stdout, windowInfo) - } catch (e: Exception) { - AppLogger.e(TAG, "获取UI数据时出错", e) - null - } - } - - /** 获取窗口信息,使用多种命令尝试 */ - private suspend fun getWindowInfoFromShell(): String { - // 尝试多种命令来获取窗口信息 - val commands = - listOf( - // 标准命令,获取当前焦点和焦点应用 - "dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp'", - // 备用命令,只获取当前焦点 - "dumpsys window | grep -E 'mCurrentFocus'", - // 备用命令,只获取焦点应用 - "dumpsys window | grep -E 'mFocusedApp'", - // 最后的备用命令,尝试获取任何窗口信息 - "dumpsys window | grep -E 'Window #|Focus'", - // 极端情况下,尝试获取前台应用包名 - "dumpsys activity recents | grep 'Recent #0' -A2" - ) - - // 依次尝试每个命令,直到有一个成功 - for (command in commands) { - try { - val result = executeUiShellCommand(command) - if (result.success && result.stdout.isNotEmpty()) { - AppLogger.d(TAG, "成功获取窗口信息: ${result.stdout.take(100)}") - return result.stdout - } - // 如果命令执行失败或返回空结果,尝试下一个命令 - AppLogger.w(TAG, "窗口信息命令 '$command' 失败或返回空结果") - } catch (e: Exception) { - AppLogger.e(TAG, "执行窗口信息命令 '$command' 出错", e) - // 继续尝试下一个命令 - } - } - - // 所有命令都失败时,尝试获取topActivity作为最后的手段 - try { - val topActivityCommand = - "dumpsys activity activities | grep -E 'topResumedActivity|topActivity'" - val result = executeUiShellCommand(topActivityCommand) - if (result.success && result.stdout.isNotEmpty()) { - AppLogger.d(TAG, "使用topActivity作为窗口信息替代: ${result.stdout.take(100)}") - return result.stdout - } - } catch (e: Exception) { - AppLogger.e(TAG, "获取topActivity失败", e) - } - - AppLogger.e(TAG, "所有获取窗口信息的尝试均失败") - return "" - } - - /** UI节点数据类,仅在Shell实现中使用 */ - private data class UINodeShell( - val className: String?, - val text: String?, - val contentDesc: String?, - val resourceId: String?, - val bounds: String?, - val isClickable: Boolean, - val children: MutableList = mutableListOf() - ) - - /** 简化布局,从XML中提取UI元素,Shell版本 */ - private fun simplifyLayoutFromXml(xml: String): SimplifiedUINode { - val factory = XmlPullParserFactory.newInstance().apply { isNamespaceAware = false } - val parser = factory.newPullParser().apply { setInput(StringReader(xml)) } - - val nodeStack = mutableListOf() - var rootNode: UINodeShell? = null - - while (parser.eventType != XmlPullParser.END_DOCUMENT) { - when (parser.eventType) { - XmlPullParser.START_TAG -> { - if (parser.name == "node") { - val newNode = createNodeShell(parser) - if (rootNode == null) { - rootNode = newNode - nodeStack.add(newNode) - } else { - nodeStack.lastOrNull()?.children?.add(newNode) - nodeStack.add(newNode) - } - } - } - XmlPullParser.END_TAG -> { - if (parser.name == "node") { - nodeStack.removeLastOrNull() - } - } - } - parser.next() - } - - // 创建默认根节点,如果解析失败 - return rootNode?.toUINodeSimplified() - ?: SimplifiedUINode( - className = null, - text = null, - contentDesc = null, - resourceId = null, - bounds = null, - isClickable = false, - children = emptyList() - ) - } - - // 转换内部UINodeShell为SimplifiedUINode - private fun UINodeShell.toUINodeSimplified(): SimplifiedUINode { - return SimplifiedUINode( - className = className, - text = text, - contentDesc = contentDesc, - resourceId = resourceId, - bounds = bounds, - isClickable = isClickable, - children = children.map { it.toUINodeSimplified() } - ) - } - - private fun createNodeShell(parser: XmlPullParser): UINodeShell { - // 解析关键属性 - val className = parser.getAttributeValue(null, "class")?.substringAfterLast('.') - val text = parser.getAttributeValue(null, "text")?.replace(" ", "\n") - val contentDesc = parser.getAttributeValue(null, "content-desc") - val resourceId = parser.getAttributeValue(null, "resource-id") - val bounds = parser.getAttributeValue(null, "bounds") - val isClickable = parser.getAttributeValue(null, "clickable") == "true" - - return UINodeShell( - className = className, - text = text, - contentDesc = contentDesc, - resourceId = resourceId, - bounds = bounds, - isClickable = isClickable - ) - } - - /** 窗口焦点信息数据类 */ - private data class FocusInfoShell( - var packageName: String? = null, - var activityName: String? = null - ) - - /** 从窗口焦点数据中提取包名和活动名 */ - private fun extractFocusInfoFromShell(windowInfo: String): FocusInfoShell { - val result = FocusInfoShell() - - try { - if (windowInfo.isBlank()) { - AppLogger.w(TAG, "Window info is empty, cannot extract focus information") - // 即使窗口信息为空,也设置默认值,确保不会返回Unknown - result.packageName = "android" - result.activityName = "ForegroundActivity" - return result - } - - AppLogger.d(TAG, "Window info for extraction: ${windowInfo.take(200)}") - - // 尝试不同的提取方法,按照特异性顺序 - if (!extractFromCurrentFocusShell(windowInfo, result) && - !extractFromFocusedAppShell(windowInfo, result) && - !extractFromLauncherInfoShell(windowInfo, result) && - !extractFromTopActivityShell(windowInfo, result) && - !extractUsingGenericPatternsShell(windowInfo, result) - ) { - - AppLogger.w(TAG, "Could not extract focus information using any method") - } - - // 最后的回退:如果我们仍然无法确定任何信息,使用默认值 - if (result.packageName == null) { - if (windowInfo.contains("statusbar") || windowInfo.contains("SystemUI")) { - result.packageName = "com.android.systemui" - result.activityName = "SystemUI" - AppLogger.d(TAG, "Using SystemUI fallback") - } else if (windowInfo.contains("recents")) { - result.packageName = "com.android.systemui" - result.activityName = "Recents" - AppLogger.d(TAG, "Using Recents fallback") - } else { - result.packageName = "android" - result.activityName = "ForegroundActivity" - AppLogger.d(TAG, "Using last-resort fallback values") - } - } - - // 记录提取结果 - AppLogger.d( - TAG, - "Final extraction result - package: ${result.packageName}, activity: ${result.activityName}" - ) - } catch (e: Exception) { - AppLogger.e(TAG, "Error parsing window info", e) - // 确保即使出现异常,我们也有至少一些默认值 - if (result.packageName == null) result.packageName = "android" - if (result.activityName == null) result.activityName = "ForegroundActivity" - } - - return result - } - - /** - * 从mCurrentFocus格式提取 例如:mCurrentFocus=Window{1234567 u0 - * com.example.app/com.example.app.MainActivity} - */ - private fun extractFromCurrentFocusShell(windowInfo: String, result: FocusInfoShell): Boolean { - // 尝试多种mCurrentFocus格式模式 - val currentFocusPatterns = - listOf( - // 标准格式,具有包/活动(同时也支持 mFocusedWindow) - "(?:mCurrentFocus|mFocusedWindow)=.*?\\{.*?\\s+([a-zA-Z0-9_.]+)/([^\\s}]+)".toRegex(), - // 有时会看到的替代格式 - "(?:mCurrentFocus|mFocusedWindow)=.*?\\s+([a-zA-Z0-9_.]+)/([^\\s}]+)\\}".toRegex(), - // 只有包名的格式(活动将单独处理) - "(?:mCurrentFocus|mFocusedWindow)=.*?\\{.*?\\s+([a-zA-Z0-9_.]+)(?:/|\\s)".toRegex() - ) - - for (pattern in currentFocusPatterns) { - val match = pattern.find(windowInfo) - if (match != null) { - if (match.groupValues.size >= 3) { - // 包含包和活动的模式 - result.packageName = match.groupValues[1] - result.activityName = match.groupValues[2] - AppLogger.d(TAG, "Extracted from mCurrentFocus pattern (full): ${pattern.pattern}") - return true - } else if (match.groupValues.size >= 2) { - // 只有包名的模式 - result.packageName = match.groupValues[1] - AppLogger.d(TAG, "Extracted package from mCurrentFocus pattern: ${pattern.pattern}") - // 返回false以允许其他方法提取活动名称 - return false - } - } - } - return false - } - - /** - * 从mFocusedApp格式提取 例如:mFocusedApp=AppWindowToken{token=Token{12345 ActivityRecord{67890 u0 - * com.example.app/.MainActivity t123}}} - */ - private fun extractFromFocusedAppShell(windowInfo: String, result: FocusInfoShell): Boolean { - // mFocusedApp格式的多种模式 - val focusedAppPatterns = - listOf( - // 带有ActivityRecord的标准格式 - "mFocusedApp=.*?ActivityRecord\\{.*?\\s+([a-zA-Z0-9_.]+)/\\.?([^\\s}]+)".toRegex(), - // 处理类似于 mFocusedApp=null 后的真实输出行 - "ActivityRecord\\{.*?\\s+([a-zA-Z0-9_.]+)/\\.?([^\\s}]+)".toRegex(), - // 有时会看到的替代格式 - "mFocusedApp=.*?\\s+([a-zA-Z0-9_.]+)/\\.?([^\\s}]+)\\s".toRegex(), - // 只有包名的格式 - "mFocusedApp=.*?\\s+([a-zA-Z0-9_.]+)(?:/|\\s)".toRegex() - ) - - for (pattern in focusedAppPatterns) { - val match = pattern.find(windowInfo) - if (match != null) { - if (match.groupValues.size >= 3) { - // 包含包和活动的完全匹配 - result.packageName = match.groupValues[1] - result.activityName = match.groupValues[2] - AppLogger.d(TAG, "Extracted from mFocusedApp pattern (full): ${pattern.pattern}") - return true - } else if (match.groupValues.size >= 2) { - // 只有包的部分匹配 - result.packageName = match.groupValues[1] - AppLogger.d(TAG, "Extracted package from mFocusedApp pattern: ${pattern.pattern}") - // 返回false以允许通过其他方法提取活动名称 - return false - } - } - } - return false - } - - /** 为启动器窗口提取信息 例如:mCurrentFocus=Window{1a23bc4 u0 Launcher} */ - private fun extractFromLauncherInfoShell(windowInfo: String, result: FocusInfoShell): Boolean { - // 查找启动器特定模式 - if (windowInfo.contains("mCurrentFocus") && windowInfo.contains("Launcher")) { - val launcherPatterns = - listOf( - "\\{.*?\\s+([a-zA-Z0-9_.]+\\.launcher)/".toRegex(), - "\\{.*?\\s+([a-zA-Z0-9_.]+\\.home)/".toRegex(), - "\\{.*?\\s+Launcher\\}".toRegex() - ) - - for (pattern in launcherPatterns) { - val match = pattern.find(windowInfo) - if (match != null && match.groupValues.size >= 2) { - result.packageName = match.groupValues[1] - result.activityName = "Launcher" - AppLogger.d(TAG, "Extracted launcher info") - return true - } - } - - // 如果我们检测到Launcher但无法提取特定的包, - // 使用默认的启动器包和名称 - result.packageName = "com.android.launcher3" - result.activityName = "Launcher" - AppLogger.d(TAG, "Using default launcher info") - return true - } - return false - } - - /** - * 从topActivity/topResumedActivity输出格式提取 - * 例如:topActivity=ComponentInfo{com.example.app/.MainActivity} - */ - private fun extractFromTopActivityShell(windowInfo: String, result: FocusInfoShell): Boolean { - // topActivity格式的模式 - val topActivityPatterns = - listOf( - "topActivity=ComponentInfo\\{([a-zA-Z0-9_.]+)/\\.?([^}]+)\\}".toRegex(), - "topResumedActivity=ComponentInfo\\{([a-zA-Z0-9_.]+)/\\.?([^}]+)\\}".toRegex(), - "ResumedActivity:\\s+\\{([a-zA-Z0-9_.]+)/\\.?([^\\s}]+)".toRegex() - ) - - for (pattern in topActivityPatterns) { - val match = pattern.find(windowInfo) - if (match != null && match.groupValues.size >= 3) { - result.packageName = match.groupValues[1] - result.activityName = match.groupValues[2] - AppLogger.d(TAG, "Extracted from topActivity pattern: ${pattern.pattern}") - return true - } - } - - // 还要查找Recent tasks格式 - val recentPattern = "Recent #0.*?\\{([a-zA-Z0-9_.]+)/\\.?([^\\s}]+)".toRegex() - val recentMatch = recentPattern.find(windowInfo) - if (recentMatch != null && recentMatch.groupValues.size >= 3) { - result.packageName = recentMatch.groupValues[1] - result.activityName = recentMatch.groupValues[2] - AppLogger.d(TAG, "Extracted from Recent tasks pattern") - return true - } - - return false - } - - /** 作为后备使用更通用的模式提取 */ - private fun extractUsingGenericPatternsShell( - windowInfo: String, - result: FocusInfoShell - ): Boolean { - var foundAny = false - - // 尝试用各种模式提取包名 - if (result.packageName == null) { - // 查找常见的包模式,如com.android.something - val packagePatterns = - listOf( - "\\s([a-zA-Z][a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+){2,})/".toRegex(), // com.example.app/ - "\\s([a-zA-Z][a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+){2,})\\s".toRegex(), // com.example.app (空格后) - "([a-zA-Z][a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+){2,})".toRegex() // 只查找任何包名类似的名称 - ) - - for (pattern in packagePatterns) { - val match = pattern.find(windowInfo) - if (match != null && match.groupValues.size >= 2) { - val potentialPackage = match.groupValues[1] - // 验证这看起来像一个真实的包(避免匹配随机字符串) - if (potentialPackage.split(".").size >= 3 && - !potentialPackage.contains("@") && - !potentialPackage.startsWith("1") && - !potentialPackage.startsWith("0") - ) { - - result.packageName = potentialPackage - foundAny = true - AppLogger.d(TAG, "Found package name using fallback pattern: ${pattern.pattern}") - break - } - } - } - } - - // 如果我们还没有活动名称,尝试提取它 - if (result.activityName == null) { - // 查找活动名称模式 - val activityPatterns = - listOf( - "/\\.?([A-Z][a-zA-Z0-9_]+Activity)".toRegex(), // /.MainActivity or - // /MainActivity - "/([^\\s/}]+)".toRegex(), // 斜杠后的任何段 - "\\.([A-Z][a-zA-Z0-9_]+)".toRegex() // .MainActivity - ) - - for (pattern in activityPatterns) { - val match = pattern.find(windowInfo) - if (match != null && match.groupValues.size >= 2) { - val activityName = match.groupValues[1] - // 验证它看起来像一个活动名称(以大写字母开头) - if (activityName.isNotEmpty() && - activityName[0].isUpperCase() && - !activityName.contains("@") - ) { - - result.activityName = activityName - foundAny = true - AppLogger.d(TAG, "Found activity name using fallback pattern: ${pattern.pattern}") - break - } - } - } - } - - // 特殊情况处理:如果我们有包名但没有活动名称 - if (result.packageName != null && result.activityName == null) { - // 尝试根据包猜测主活动名称 - val packageParts = result.packageName!!.split(".") - if (packageParts.isNotEmpty()) { - val lastPart = packageParts.last().replaceFirstChar { if (it.isLowerCase()) it.titlecase(java.util.Locale.getDefault()) else it.toString() } - result.activityName = "${lastPart}Activity" - AppLogger.d(TAG, "Guessed activity name from package: ${result.activityName}") - foundAny = true - } - } - - // 如果我们找到了包或活动,将其视为部分成功 - return foundAny - } - - - - /** 使用uiautomator点击元素 */ - private suspend fun clickElementWithUiautomator(tool: AITool): ToolResult { - AppLogger.d(TAG, "Using uiautomator to click element") - - val resourceId = tool.parameters.find { it.name == "resourceId" }?.value - val className = tool.parameters.find { it.name == "className" }?.value - val contentDesc = tool.parameters.find { it.name == "contentDesc" }?.value - val index = tool.parameters.find { it.name == "index" }?.value?.toIntOrNull() ?: 0 - val partialMatch = - tool.parameters.find { it.name == "partialMatch" }?.value?.toBoolean() ?: false - - try { - // 先尝试获取UI dump - AppLogger.d(TAG, "Dumping UI hierarchy to find element") - val dumpCommand = "uiautomator dump /sdcard/window_dump.xml" - val result = executeUiShellCommand(dumpCommand) - - if (!result.success) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to dump UI hierarchy: ${result.stderr ?: "Unknown error"}" - ) - } - - // 读取dump文件 - val readCommand = "cat /sdcard/window_dump.xml" - val readResult = executeUiShellCommand(readCommand) - - if (!readResult.success) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to read UI dump: ${readResult.stderr ?: "Unknown error"}" - ) - } - - val xml = readResult.stdout - - // 使用XML Parser查找匹配的元素(取代有问题的正则方式) - val hasSelectors = resourceId != null || className != null || contentDesc != null - if (!hasSelectors) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "No element selector provided." - ) - } - - // 用XmlPullParser逐节点匹配,避免正则跨节点匹配的问题 - data class MatchedNode(val bounds: String?) - val matchingNodes = mutableListOf() - - try { - val factory = XmlPullParserFactory.newInstance().apply { isNamespaceAware = false } - val parser = factory.newPullParser().apply { setInput(StringReader(xml)) } - - while (parser.eventType != XmlPullParser.END_DOCUMENT) { - if (parser.eventType == XmlPullParser.START_TAG && parser.name == "node") { - val actualId = parser.getAttributeValue(null, "resource-id") - val actualClass = parser.getAttributeValue(null, "class") - val actualDesc = parser.getAttributeValue(null, "content-desc") - val actualBounds = parser.getAttributeValue(null, "bounds") - - var matches = true - - if (resourceId != null) { - if (actualId == null) { - matches = false - } else if (partialMatch) { - matches = actualId.contains(resourceId) - } else { - // 支持短ID (expand_search) 和完整ID (tv.danmaku.bili:id/expand_search) - matches = actualId == resourceId || actualId.endsWith(":id/$resourceId") - } - } - - if (matches && className != null) { - if (actualClass == null) { - matches = false - } else if (partialMatch) { - matches = actualClass.contains(className) - } else { - // 支持短类名 (ImageView) 和完整类名 (android.widget.ImageView) - matches = actualClass == className || actualClass.endsWith(".$className") - } - } - - if (matches && contentDesc != null) { - if (actualDesc == null) { - matches = false - } else if (partialMatch) { - matches = actualDesc.contains(contentDesc, ignoreCase = true) - } else { - matches = actualDesc.equals(contentDesc, ignoreCase = true) - } - } - - if (matches) { - matchingNodes.add(MatchedNode(bounds = actualBounds)) - } - } - parser.next() - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error parsing UI XML", e) - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to parse UI hierarchy XML: ${e.message}" - ) - } - - if (matchingNodes.isEmpty()) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "No matching element found." - ) - } - - if (index < 0 || index >= matchingNodes.size) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = - "Index out of range. Found ${matchingNodes.size} elements, but requested index $index." - ) - } - - // 获取指定索引的节点bounds - val nodeBounds = matchingNodes[index].bounds - if (nodeBounds == null) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Target element has no bounds." - ) - } - - // 提取边界坐标 - val boundsPattern = "\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]".toRegex() - val boundsMatch = boundsPattern.find(nodeBounds) - if (boundsMatch == null || boundsMatch.groupValues.size < 5) { - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to extract bounds from the element: $nodeBounds" - ) - } - - // 提取坐标 - val x1 = boundsMatch.groupValues[1].toInt() - val y1 = boundsMatch.groupValues[2].toInt() - val x2 = boundsMatch.groupValues[3].toInt() - val y2 = boundsMatch.groupValues[4].toInt() - - // 计算中心点 - val centerX = (x1 + x2) / 2 - val centerY = (y1 + y2) / 2 - - withContext(Dispatchers.Main) { operationOverlay.hideImmediately() } - - val tapCommand = "input tap $centerX $centerY" - val tapResult = executeUiShellCommand(tapCommand) - - if (tapResult.success) { - val identifierDescription = - when { - resourceId != null -> " with resource ID: $resourceId" - contentDesc != null -> " with content description: $contentDesc" - else -> " with class name: $className" - } - - val matchCount = - if (matchingNodes.size > 1) { - " (index $index of ${matchingNodes.size} matches)" - } else "" - - withContext(Dispatchers.Main) { - operationOverlay.showTap(centerX, centerY) - operationOverlay.hide() - } - return ToolResult( - toolName = tool.name, - success = true, - result = - UIActionResultData( - actionType = "click", - actionDescription = - "Successfully clicked element$identifierDescription$matchCount at coordinates ($centerX, $centerY) via shell command", - coordinates = Pair(centerX, centerY), - elementId = resourceId ?: className ?: contentDesc - ), - error = "" - ) - } else { - withContext(Dispatchers.Main) { - operationOverlay.hide() - } - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Failed to click element: ${tapResult.stderr ?: "Unknown error"}" - ) - } - } catch (e: Exception) { - AppLogger.e(TAG, "Error clicking element with uiautomator", e) - withContext(Dispatchers.Main) { - operationOverlay.hide() - } - return ToolResult( - toolName = tool.name, - success = false, - result = StringResultData(""), - error = "Error clicking element: ${e.message ?: "Unknown exception"}" - ) - } finally { - // 清理临时文件 - try { - Runtime.getRuntime().exec("rm /sdcard/window_dump.xml") - } catch (cleanupEx: Exception) { - AppLogger.e(TAG, "Error cleaning up temp file", cleanupEx) - } - } - } - - /** 从边界字符串提取中心坐标 返回中心点坐标,或null如果格式无效 */ - protected fun extractCenterCoordinates(bounds: String): Pair? { - val boundsPattern = "\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]".toRegex() - val matchResult = boundsPattern.find(bounds) ?: return null - - if (matchResult.groupValues.size < 5) return null - - // 提取坐标 - val x1 = matchResult.groupValues[1].toInt() - val y1 = matchResult.groupValues[2].toInt() - val x2 = matchResult.groupValues[3].toInt() - val y2 = matchResult.groupValues[4].toInt() - - // 计算并返回中心点 - val centerX = (x1 + x2) / 2 - val centerY = (y1 + y2) / 2 - - return Pair(centerX, centerY) - } -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootDeviceInfoToolExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootDeviceInfoToolExecutor.kt deleted file mode 100644 index 7777815844..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootDeviceInfoToolExecutor.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.root - -import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.admin.AdminDeviceInfoToolExecutor - -/** Root级别的设备信息工具,继承管理员版本 */ -open class RootDeviceInfoToolExecutor(context: Context) : AdminDeviceInfoToolExecutor(context) { - // 当前阶段不添加新功能,仅继承管理员实现 -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootFileSystemTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootFileSystemTools.kt deleted file mode 100644 index 197ead4a34..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootFileSystemTools.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.root - -import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.admin.AdminFileSystemTools - -/** Root级别的文件系统工具,继承管理员级别 */ -open class RootFileSystemTools(context: Context) : AdminFileSystemTools(context) { - // 当前阶段不添加新功能,仅继承管理员级别实现 -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootSystemOperationTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootSystemOperationTools.kt deleted file mode 100644 index 7cfb3e35eb..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootSystemOperationTools.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.ai.assistance.operit.core.tools.defaultTool.root - -import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.admin.AdminSystemOperationTools - -/** Root级别的系统操作工具,继承管理员版本 */ -open class RootSystemOperationTools(context: Context) : AdminSystemOperationTools(context) { - // 当前阶段不添加新功能,仅继承管理员实现 -} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootUITools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootUITools.kt index eeaf1a9c1b..f0b52dbd44 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootUITools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootUITools.kt @@ -21,10 +21,7 @@ import kotlinx.coroutines.withContext import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserFactory -/** - * Root-level UI tools that use shell commands (uiautomator, input) for robust UI automation. - * This implementation is modeled after DebuggerUITools but operates without accessibility fallbacks. - */ +/** Root UI 工具复用管理员公共实现,并按 Root 能力执行界面操作。 */ open class RootUITools(context: Context) : AdminUITools(context) { companion object { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardUITools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardUITools.kt index 0b48cc51be..8df2c40517 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardUITools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardUITools.kt @@ -56,7 +56,7 @@ open class StandardUITools(protected val context: Context) : ToolImplementations private const val TAG = "UITools" private const val COMMAND_TIMEOUT_SECONDS = 10L private const val OPERATION_NOT_SUPPORTED = - "This operation is not supported in the standard version. Please use the accessibility or debugger version." + "This operation is not supported in the standard version. Please select administrator or root mode and grant the required authorization." internal val APP_PACKAGES: MutableMap = mutableMapOf( diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidPermissionLevel.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidPermissionLevel.kt index a3a6c1386c..f7038ac82b 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidPermissionLevel.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidPermissionLevel.kt @@ -17,7 +17,6 @@ enum class AndroidPermissionLevel { fun fromString(value: String?): AndroidPermissionLevel { return when(value?.uppercase(Locale.ROOT)) { "STANDARD" -> STANDARD - "ACCESSIBILITY", "DEBUGGER" -> ADMIN "ADMIN" -> ADMIN "ROOT" -> ROOT else -> STANDARD // 默认为最低权限 diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListenerFactory.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListenerFactory.kt index eef7ffa1e5..992aa1a263 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListenerFactory.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListenerFactory.kt @@ -18,7 +18,7 @@ class ActionListenerFactory { val listener = when (backend) { PermissionBackend.STANDARD -> StandardActionListener(appContext) PermissionBackend.ACCESSIBILITY -> AccessibilityActionListener(appContext) - PermissionBackend.SHIZUKU -> DebuggerActionListener(appContext) + PermissionBackend.SHIZUKU -> ShizukuActionListener(appContext) PermissionBackend.ROOT -> RootActionListener(appContext) } listener.initialize() diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/DebuggerActionListener.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ShizukuActionListener.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/action/DebuggerActionListener.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ShizukuActionListener.kt index 195631086a..2d9b482e1d 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/DebuggerActionListener.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ShizukuActionListener.kt @@ -19,9 +19,9 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach /** 基于Shizuku的UI操作监听器 作为管理员模式的 Shizuku 后端 */ -class DebuggerActionListener(private val context: Context) : ActionListener { +class ShizukuActionListener(private val context: Context) : ActionListener { companion object { - private const val TAG = "DebuggerActionListener" + private const val TAG = "ShizukuActionListener" /** 添加状态变更监听器 */ fun addStateChangeListener(listener: () -> Unit) { @@ -96,7 +96,7 @@ class DebuggerActionListener(private val context: Context) : ActionListener { // 启动系统级事件监控 startSystemEventMonitoring() - return@withContext ActionListener.ListeningResult.success(context.getString(R.string.debugger_ui_listener_started)) + return@withContext ActionListener.ListeningResult.success(context.getString(R.string.shizuku_ui_listener_started)) } catch (e: Exception) { AppLogger.e(TAG, "启动调试器UI操作监听失败", e) isListening.set(false) diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutorFactory.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutorFactory.kt index 468e940404..cf010b35e9 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutorFactory.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutorFactory.kt @@ -17,7 +17,7 @@ class ShellExecutorFactory { val appContext = context.applicationContext val executor = when (backend) { PermissionBackend.STANDARD -> StandardShellExecutor(appContext) - PermissionBackend.SHIZUKU -> DebuggerShellExecutor(appContext) + PermissionBackend.SHIZUKU -> ShizukuShellExecutor(appContext) PermissionBackend.ROOT -> RootShellExecutor(appContext) PermissionBackend.ACCESSIBILITY -> error("Accessibility does not provide a shell backend") } diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/DebuggerShellExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShizukuShellExecutor.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/DebuggerShellExecutor.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShizukuShellExecutor.kt index 071de7c8d3..8b70fdc431 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/DebuggerShellExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShizukuShellExecutor.kt @@ -38,9 +38,9 @@ import moe.shizuku.server.IRemoteProcess import moe.shizuku.server.IShizukuService /** 基于Shizuku的Shell命令执行器 作为管理员模式的 Shizuku 后端 */ -class DebuggerShellExecutor(private val context: Context) : ShellExecutor { +class ShizukuShellExecutor(private val context: Context) : ShellExecutor { companion object { - private const val TAG = "DebuggerShellExecutor" + private const val TAG = "ShizukuShellExecutor" private val serviceCache = ConcurrentHashMap() /** 添加状态变更监听器 */ @@ -449,7 +449,7 @@ class DebuggerShellExecutor(private val context: Context) : ShellExecutor { * stdout 与 stderr 必须同时消费,否则任一管道写满都会阻塞远程进程;stdin * 也必须主动关闭,否则需要 EOF 的命令会一直等待输入。 */ -private const val DEBUGGER_SHELL_TAG = "DebuggerShellExecutor" +private const val SHIZUKU_SHELL_TAG = "ShizukuShellExecutor" private const val REMOTE_PROCESS_POLL_INTERVAL_MS = 100L private const val POST_EXIT_OUTPUT_DRAIN_GRACE_MS = 1_000L private const val OUTPUT_TRUNCATION_NOTICE = @@ -553,10 +553,10 @@ private suspend fun executeRemoteProcess( // cancellation is allowed to leave this function. throw e } catch (e: RemoteException) { - AppLogger.e(DEBUGGER_SHELL_TAG, "Remote process operation failed: $command", e) + AppLogger.e(SHIZUKU_SHELL_TAG, "Remote process operation failed: $command", e) ShellExecutor.CommandResult(false, "", "Remote exception: ${e.message}") } catch (e: Exception) { - AppLogger.e(DEBUGGER_SHELL_TAG, "Remote process execution failed: $command", e) + AppLogger.e(SHIZUKU_SHELL_TAG, "Remote process execution failed: $command", e) ShellExecutor.CommandResult(false, "", "Error: ${e.message}") } finally { // Covers failures before the structured reader scope was created. @@ -585,7 +585,7 @@ private fun closeRemoteStdin(process: IRemoteProcess) { process.getOutputStream()?.close() } catch (e: Exception) { // A command may still be usable when the optional stdin descriptor is unavailable. - AppLogger.v(DEBUGGER_SHELL_TAG, "Unable to close remote stdin", e) + AppLogger.v(SHIZUKU_SHELL_TAG, "Unable to close remote stdin", e) } } @@ -594,7 +594,7 @@ private fun destroyRemoteProcess(process: IRemoteProcess?) { try { process.destroy() } catch (e: Exception) { - AppLogger.v(DEBUGGER_SHELL_TAG, "Unable to destroy remote process", e) + AppLogger.v(SHIZUKU_SHELL_TAG, "Unable to destroy remote process", e) } } @@ -603,7 +603,7 @@ private fun closeDescriptor(descriptor: ParcelFileDescriptor?, label: String) { try { descriptor.close() } catch (e: Exception) { - AppLogger.v(DEBUGGER_SHELL_TAG, "Unable to close $label", e) + AppLogger.v(SHIZUKU_SHELL_TAG, "Unable to close $label", e) } } @@ -626,9 +626,9 @@ private fun drainDescriptor( } } catch (e: IOException) { // Closing a descriptor during cancellation or post-exit cleanup is expected. - AppLogger.v(DEBUGGER_SHELL_TAG, "Reading remote $label stopped", e) + AppLogger.v(SHIZUKU_SHELL_TAG, "Reading remote $label stopped", e) } catch (e: Exception) { - AppLogger.w(DEBUGGER_SHELL_TAG, "Reading remote $label failed", e) + AppLogger.w(SHIZUKU_SHELL_TAG, "Reading remote $label failed", e) } } @@ -742,7 +742,7 @@ private class ShizukuShellProcess( completion.complete(-1) throw e } catch (e: Exception) { - AppLogger.e(DEBUGGER_SHELL_TAG, "Interactive Shizuku process failed: $command", e) + AppLogger.e(SHIZUKU_SHELL_TAG, "Interactive Shizuku process failed: $command", e) completion.complete(-1) } finally { if (!processFinished && !destroyed.get()) { @@ -771,11 +771,11 @@ private class ShizukuShellProcess( } } catch (e: IOException) { if (!destroyed.get()) { - AppLogger.v(DEBUGGER_SHELL_TAG, "Reading interactive $label stopped", e) + AppLogger.v(SHIZUKU_SHELL_TAG, "Reading interactive $label stopped", e) } } catch (e: Exception) { if (!destroyed.get()) { - AppLogger.w(DEBUGGER_SHELL_TAG, "Reading interactive $label failed", e) + AppLogger.w(SHIZUKU_SHELL_TAG, "Reading interactive $label failed", e) } } finally { channel.close() diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 9d7c8b5975..e3592c378f 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -7115,8 +7115,8 @@ Cannot decode Bitmap from URI Cannot open input stream for URI - - Debugger UI operation listener started + + Shizuku UI listener started Default Config diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 9f8241bb8b..b0c5c07d89 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -6191,7 +6191,7 @@ No se puede leer el archivo de imagen: %1$s No se puede decodificar Bitmap desde la URI No se puede abrir el flujo de entrada de la URI - Monitor de operaciones de UI del depurador iniciado + Monitor de operaciones de UI de Shizuku iniciado Configuración predeterminada Configuración %1$s Error al importar: %1$s diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index a4e3fec218..97bf331701 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -6049,7 +6049,7 @@ Tidak dapat mendekode Bitmap dari URI Tidak dapat membuka aliran input URI - Pemantauan aksi UI debugger telah dimulai + Pemantauan aksi UI Shizuku telah dimulai Konfigurasi default Konfigurasi %1$s Gagal mengimpor: %1$s diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index cf0436df8b..440069b6dd 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -7805,7 +7805,7 @@ プロフィール AI アシスタントのフローティングウィンドウ AI アシスタントはバックグラウンドで動作しています - デバッガーによる UI 操作の監視を開始しました + Shizuku による UI 操作の監視を開始しました 設定 %1$s 名前のないタグ ワークスペースをバックアップしています... diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index d148076161..23d3678c09 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -6294,7 +6294,7 @@ 이미지 파일을 읽을 수 없습니다: %1$s URI에서 비트맵을 디코딩할 수 없습니다. URI에 대한 입력 스트림을 열 수 없습니다. - 디버거 UI 작업 리스너가 시작되었습니다. + Shizuku UI 작업 리스너가 시작되었습니다. 기본 구성 %1$s 구성 가져오기 실패: %1$s diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index 2375a67cad..4630e488a8 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -6111,7 +6111,7 @@ Tidak dapat membaca fail imej: %1$s Tidak dapat menyahkod Bitmap dari URI Tidak dapat membuka aliran input URI - Pendengar tindakan UI penyahpepijat telah dimulakan + Pendengar tindakan UI Shizuku telah dimulakan Konfigurasi lalai Konfigurasi %1$s Import gagal: %1$s diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 1fac5d599c..0596632631 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -5772,7 +5772,7 @@ Não foi possível ler o arquivo de imagem: %1$s Não é possível decodificar o bitmap do URI Não foi possível abrir o fluxo de entrada para URI - O monitoramento da operação da IU do depurador foi iniciado + O monitoramento da operação da IU do Shizuku foi iniciado Configuração padrão Configurar %1$s Falha na importação: %1$s diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 3f6e86c131..8e95edc428 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -7300,8 +7300,8 @@ Nu se poate de laURIDecodareBitmap Nu se poate deschideURIfluxul de intrare - - DebuggerUIMonitorizarea operațiunilor a fost activată + + Ascultătorul UI Shizuku a pornit Configurația implicită diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1f25a4090e..01532b9422 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7720,8 +7720,8 @@ 无法从URI解码Bitmap 无法打开URI的输入流 - - 调试器UI操作监听已启动 + + Shizuku UI 监听器已启动 默认配置 diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitiesTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitiesTest.kt index c221b3707d..6fb6590b6f 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitiesTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitiesTest.kt @@ -8,21 +8,21 @@ import org.junit.Test import java.util.Locale class PermissionCapabilitiesTest { - @Test fun userModesAreExactlyThreeAndLegacyNamesMapToAdmin() { + @Test fun userModesAreExactlyThreeAndLegacyNamesAreNotRuntimeModes() { assertEquals(listOf("STANDARD", "ADMIN", "ROOT"), AndroidPermissionLevel.values().map { it.name }) - for (name in listOf("ACCESSIBILITY", "DEBUGGER", "accessibility", "debugger", "ADMIN")) { - assertEquals(AndroidPermissionLevel.ADMIN, AndroidPermissionLevel.fromString(name)) + for (name in listOf("ACCESSIBILITY", "DEBUGGER", "accessibility", "debugger")) { + assertEquals(AndroidPermissionLevel.STANDARD, AndroidPermissionLevel.fromString(name)) } assertEquals(AndroidPermissionLevel.STANDARD, AndroidPermissionLevel.fromString(null)) assertEquals(AndroidPermissionLevel.STANDARD, AndroidPermissionLevel.fromString("unknown")) assertEquals(AndroidPermissionLevel.ROOT, AndroidPermissionLevel.fromString("ROOT")) } - @Test fun legacyNamesDoNotDependOnDeviceLocale() { + @Test fun modeNamesDoNotDependOnDeviceLocale() { val previous = Locale.getDefault() try { Locale.setDefault(Locale.forLanguageTag("tr-TR")) - assertEquals(AndroidPermissionLevel.ADMIN, AndroidPermissionLevel.fromString("accessibility")) + assertEquals(AndroidPermissionLevel.ROOT, AndroidPermissionLevel.fromString("root")) assertEquals(AndroidPermissionLevel.ADMIN, AndroidPermissionLevel.fromString("admin")) } finally { Locale.setDefault(previous) diff --git a/docs/TODO/chore/tools-permissions-layout/01-permissions.md b/docs/TODO/chore/tools-permissions-layout/01-permissions.md new file mode 100644 index 0000000000..9e793884e5 --- /dev/null +++ b/docs/TODO/chore/tools-permissions-layout/01-permissions.md @@ -0,0 +1,25 @@ +# 01 权限实现收口 + +## 原实现与目标 + +用户模式已经是 `STANDARD`、`ADMIN`、`ROOT`,但文件、系统、设备和 UI 工具仍经过无障碍、调试、管理员等历史继承层。目标是让工具实现直接对应实际职责,管理员统一使用已授权的无障碍和 Shizuku,Root 保留自身 UI 行为及现有能力选择。 + +## 修改范围 + +- 文件工具:将调试文件实现与管理员路由合并,直接继承标准文件工具,保留只读与写入操作原有路由。 +- UI 工具:将无障碍操作与 Shell 操作收入管理员工具,显式区分内部操作方法;Root 继续继承管理员实现。 +- 系统工具:管理员直接继承标准实现,承接原 Shell 操作。 +- 设备信息及 Root 文件、系统工具:移除没有独立行为的工具壳,通过现有授权能力选择执行后端。 +- Shell 与操作监听器:将 `Debugger` 实现准确命名为 `Shizuku`,同步工厂、日志和提示。 +- 配置:历史值只由现有 DataStore 迁移入口转换为 `ADMIN`,运行时模式解析只识别三档名称。 +- 回归覆盖:维护现有权限能力组合与偏好迁移测试,交由仓库工作流执行。 + +## 验收 + +- [x] 工具实现中不再存在无障碍等级、调试等级及对应继承层 +- [x] 管理员包含原无障碍和 Shell 操作,Root 保留原操作行为 +- [x] 运行时模式只有标准、管理员、Root,旧偏好可迁移 +- [x] 工具名称、参数和结果格式保持现有契约 +- [x] 静态引用与语法检查完成,操作体迁移逐项对比;仓库验证尚未派发 + +[DONE] 权限收口代码及静态核对完成,运行验证以工作流结果为准。 diff --git a/docs/TODO/chore/tools-permissions-layout/index.md b/docs/TODO/chore/tools-permissions-layout/index.md new file mode 100644 index 0000000000..2f225ef9a8 --- /dev/null +++ b/docs/TODO/chore/tools-permissions-layout/index.md @@ -0,0 +1,29 @@ +--- +fork: https://github.com/3316891527/Operit +status: in-progress +--- +# 工具权限收口与目录整理 + +本次工作先将工具权限实现统一为标准、管理员和 Root 三档,再依据逐文件迁移清单整理工具目录。权限收口与目录迁移分别提交,便于核对行为变化与路径变化。 + +## 当前状况 + +用户可选模式已经是 `STANDARD`、`ADMIN`、`ROOT`,工具实现仍保留 Standard、Accessibility、Debugger、Admin、Root 多层继承。`core.tools.packTool` 的解析、加载、运行、安装、界面 DSL 和元数据文件混合放置,工具的其他目录也需要按职责整理。 + +## 执行顺序 + +1. [权限实现收口](01-permissions.md):删除旧工具等级和无行为的中间层,管理员按实际授权使用无障碍、Shizuku,Root 复用管理员能力。 +2. 目录迁移:读取权限收口后的工具源码,先记录逐文件当前路径、目标路径及目标包名,再按清单迁移并同步引用。 + +迁移清单只记录本次实际迁移的文件。目录整理以保持工具调用接口及现有行为为目标。 + +## 验证与交付 + +记录静态引用、路径、配置及差异检查;本地不执行编译、构建或测试。推送工作分支后先派发仓库工作流,再创建以 `dev` 为目标的 PR。工作流受理与实际运行结果分别记录。 + +## 进度 + +- [x] 权限实现统一为三档,旧配置只在迁移入口识别 +- [ ] 形成逐文件目标路径清单 +- [ ] 完成清单中全部迁移及调用方同步 +- [ ] 完成静态核对、提交、工作流派发与 PR From f33b310ea5791946a7f6d07cbfdd6daa22bedd6d Mon Sep 17 00:00:00 2001 From: kong <135376906+3316891527@users.noreply.github.com> Date: Thu, 29 Oct 2026 12:22:58 +0000 Subject: [PATCH 2/7] =?UTF-8?q?refactor(tools):=20=E6=8C=89=E9=80=90?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=B8=85=E5=8D=95=E6=95=B4=E7=90=86=E5=86=85?= =?UTF-8?q?=E7=BD=AE=E5=B7=A5=E5=85=B7=E4=B8=8E=E6=8F=92=E4=BB=B6=E5=8C=85?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oolPkgComposeDslWebViewFocusAndroidTest.kt | 2 +- .../media}/ffmpeg/ffmpeg_probe.js | 0 .../standard => builtin/web}/browser/main.js | 0 .../standard => builtin/web}/browser/probe.js | 0 .../bridge_contract/suspend_await.js | 6 +- app/src/main/AndroidManifest.xml | 8 +- .../operit/api/chat/EnhancedAIService.kt | 4 +- .../core/application/OperitApplication.kt | 6 +- .../operit/core/chat/AIMessageManager.kt | 4 +- .../core/chat/context/ConversationService.kt | 6 +- .../protocol/ConversationMarkupManager.kt | 2 +- .../core/chat/tools/ToolExecutionManager.kt | 8 +- .../operit/core/config/SystemPromptConfig.kt | 2 +- .../operit/core/config/SystemToolPrompts.kt | 2 +- .../extraction/ChatMemoryRebuildManager.kt | 2 +- .../extraction/ConversationMemoryExtractor.kt | 2 +- .../extraction/MemoryAutoSaveScheduler.kt | 2 +- .../performance/PerformanceMonitorManager.kt | 2 +- .../operit/core/tools/ToolPackage.kt | 3 +- .../operit/core/tools/agent/PhoneAgent.kt | 6 +- .../{defaultTool => builtin}/ToolGetter.kt | 34 +- .../a2ui/A2uiToolDefinitions.kt | 2 +- .../a2ui/A2uiToolRuntime.kt | 2 +- .../a2ui/A2uiTools.kt | 4 +- .../calculator}/StandardCalculator.kt | 2 +- .../chat}/StandardChatManagerTool.kt | 2 +- .../device}/StandardDeviceInfoToolExecutor.kt | 4 +- .../filesystem}/AdminFileSystemTools.kt | 14 +- .../filesystem}/LinuxFileSystemTools.kt | 8 +- .../filesystem}/PathValidator.kt | 2 +- .../filesystem}/SafFileSystemTools.kt | 6 +- .../filesystem}/StandardFileSystemTools.kt | 9 +- .../media}/BluetoothSessionManager.kt | 2 +- .../media}/StandardFFmpegTool.kt | 4 +- .../media}/StandardMusicPlaybackTools.kt | 2 +- .../memory}/MemoryQueryToolExecutor.kt | 4 +- .../StandardSoftwareSettingsModifyTools.kt | 4 +- .../settings}/ToolPermissionModeSupport.kt | 2 +- .../shell}/ShellCommandSafety.kt | 2 +- .../shell}/StandardShellToolExecutor.kt | 6 +- .../system}/AdminSystemOperationTools.kt | 7 +- .../system}/StandardIntentToolExecutor.kt | 2 +- .../StandardSendBroadcastToolExecutor.kt | 2 +- .../system}/StandardSystemOperationTools.kt | 7 +- .../StandardTerminalCommandExecutor.kt | 4 +- .../admin => builtin/ui}/AdminUITools.kt | 8 +- .../root => builtin/ui}/RootUITools.kt | 6 +- .../ui}/StandardUITools.kt | 10 +- .../web}/CookiePrivacyManager.kt | 2 +- .../web}/StandardBrowserSessionTools.kt | 90 +- .../web}/StandardHttpTools.kt | 2 +- .../web}/StandardWebVisitTool.kt | 4 +- .../browser/BrowserDownloadSupport.kt | 4 +- .../browser/BrowserNavigationPolicy.kt | 2 +- .../browser/BrowserPageExecutionSupport.kt | 4 +- .../session}/browser/BrowserToolSupport.kt | 6 +- .../session}/browser/BrowserWebViewSupport.kt | 6 +- .../session}/browser/WebSessionBrowserHost.kt | 4 +- .../browser/WebSessionBrowserHostState.kt | 4 +- .../browser/WebSessionHistoryStore.kt | 2 +- .../WebSessionPermissionRequestActivity.kt | 2 +- .../session}/browser/WebSessionWebViewHost.kt | 2 +- .../UserscriptCapabilityRegistry.kt | 2 +- .../session}/userscript/UserscriptMatcher.kt | 2 +- .../userscript/UserscriptMetadataParser.kt | 2 +- .../session}/userscript/UserscriptModels.kt | 2 +- .../install/UserscriptImportCoordinator.kt | 2 +- .../install/UserscriptImportPickerActivity.kt | 2 +- .../runtime/UserscriptBootstrapScript.kt | 2 +- .../runtime/UserscriptCookieService.kt | 2 +- .../runtime/UserscriptStorageNotifier.kt | 2 +- .../runtime/UserscriptTabStateStore.kt | 2 +- .../runtime/UserscriptWebRequestEngine.kt | 2 +- .../runtime/WebSessionUserscriptManager.kt | 28 +- .../userscript/storage/UserscriptEntities.kt | 2 +- .../userscript/storage/UserscriptJsonStore.kt | 2 +- .../storage/UserscriptRepository.kt | 30 +- .../ui/WebSessionUserscriptUiStateStore.kt | 12 +- .../workflow}/StandardWorkflowTools.kt | 2 +- .../core/tools/climode/CliToolModeSupport.kt | 2 +- .../javascript/ComposeDslActionRetention.kt | 4 +- .../operit/core/tools/javascript/JsEngine.kt | 14 +- .../javascript/JsNativeInterfaceDelegates.kt | 4 +- .../core/tools/javascript/JsToolManager.kt | 2 +- .../tools/javascript/JsToolPkgRegistration.kt | 8 +- .../operit/core/tools/mcp/MCPToolExecutor.kt | 4 +- .../packTool/PackageDebugRefreshReceiver.kt | 3 +- .../packTool/ToolPkgDebugInstallReceiver.kt | 3 +- .../{ => install}/PackageFileImportSupport.kt | 3 +- .../{ => install}/PackageSourceDeletion.kt | 2 +- .../{ => install}/PackageTemplateFactory.kt | 2 +- .../packTool/{ => loader}/ToolPkgLoadOrder.kt | 5 +- .../packTool/{ => loader}/ToolPkgLoader.kt | 8 +- .../{ => metadata}/BuiltInPackageDefaults.kt | 3 +- .../{ => metadata}/ToolPkgApiVersion.kt | 2 +- .../ToolPkgCommonPluginConstants.kt | 2 +- .../ToolPkgManifestRequirement.kt | 2 +- .../{ => metadata}/ToolPkgMarketOrigin.kt | 2 +- .../{ => metadata}/ToolPkgTemplateModels.kt | 2 +- .../minify/ToolPkgArtifactMinifier.kt | 6 +- .../ToolPkgMainRegistrationScriptParser.kt | 23 +- .../packTool/{ => parser}/ToolPkgParser.kt | 14 +- .../{ => runtime}/PackageActivationResult.kt | 2 +- .../packTool/{ => runtime}/PackageManager.kt | 22 +- .../PackageManagerToolPkgFacade.kt | 9 +- .../{ => runtime}/ToolPkgHookModels.kt | 2 +- .../packTool/{ => runtime}/ToolPkgManager.kt | 6 +- .../{ => runtime}/ToolPkgRuntimeMonitor.kt | 2 +- .../{ => uidsl}/ToolPkgComposeDslParser.kt | 2 +- .../AndroidPermissionLevel.kt | 2 +- .../permissions/PermissionCapabilities.kt | 4 +- .../PermissionCapabilityResolver.kt | 4 +- .../PermissionCapabilitySession.kt | 2 +- .../AccessibilityProviderInstaller.kt | 2 +- .../authorization}/RootAuthorizer.kt | 4 +- .../authorization}/ShizukuAuthorizer.kt | 2 +- .../authorization}/ShizukuInstaller.kt | 2 +- .../core/tools/{ => runtime}/AIToolHandler.kt | 5 +- .../core/tools/{ => runtime}/AIToolHook.kt | 2 +- .../{ => runtime}/ToolExecutionLimits.kt | 2 +- .../tools/{ => runtime}/ToolProgressBus.kt | 2 +- .../tools/{ => runtime}/ToolRegistration.kt | 9 +- .../action/AccessibilityActionListener.kt | 2 +- .../tools/system/action/ActionListener.kt | 2 +- .../system/action/ActionListenerFactory.kt | 2 +- .../core/tools/system/action/ActionManager.kt | 2 +- .../tools/system/action/RootActionListener.kt | 2 +- .../system/action/ShizukuActionListener.kt | 4 +- .../system/action/StandardActionListener.kt | 2 +- .../MediaProjectionCaptureManager.kt | 2 +- .../{ => capture}/MediaProjectionHolder.kt | 2 +- .../{ => capture}/ScreenCaptureActivity.kt | 2 +- .../{ => capture}/ScreenCaptureService.kt | 2 +- .../{ => shell}/AndroidShellExecutor.kt | 3 +- .../tools/system/shell/RootShellExecutor.kt | 4 +- .../core/tools/system/shell/ShellExecutor.kt | 4 +- .../system/shell/ShellExecutorFactory.kt | 2 +- .../system/shell/ShizukuShellExecutor.kt | 6 +- .../system/shell/StandardShellExecutor.kt | 4 +- .../system/shower/OperitShowerShellRunner.kt | 4 +- .../{ => terminal}/OperitTerminalManager.kt | 2 +- .../tools/system/{ => terminal}/Terminal.kt | 2 +- .../uiautomator/UiAutomatorDumpGuard.kt | 2 +- .../operit/core/workflow/WorkflowExecutor.kt | 2 +- .../operit/data/mcp/MCPLocalServer.kt | 2 +- .../operit/data/mcp/MCPRepository.kt | 2 +- .../operit/data/mcp/plugins/MCPBridge.kt | 4 +- .../operit/data/mcp/plugins/MCPDeployer.kt | 4 +- .../data/mcp/plugins/MCPSharedSession.kt | 2 +- .../operit/data/mcp/plugins/MCPStarter.kt | 2 +- .../AndroidPermissionModeMigration.kt | 2 +- .../AndroidPermissionPreferences.kt | 2 +- .../CharacterCardToolAccessResolver.kt | 2 +- .../data/repository/UIHierarchyManager.kt | 2 +- .../data/storage/PackageSkillInventory.kt | 4 +- .../ToolPkgDesktopWidgetConfigActivity.kt | 2 +- .../ToolPkgDesktopWidgetDslRenderer.kt | 10 +- .../appwidget/ToolPkgDesktopWidgetHost.kt | 4 +- .../ExternalChatRequestExecutor.kt | 6 +- .../AppLifecycleHookPluginRegistry.kt | 24 +- .../toolpkg/ToolPkgAiProviderRegistry.kt | 4 +- .../toolpkg/ToolPkgChatInputHookBridge.kt | 6 +- .../toolpkg/ToolPkgChatMessageHookBridge.kt | 6 +- .../ToolPkgChatMessageMenuItemBridge.kt | 8 +- .../toolpkg/ToolPkgChatRuntimeHookBridge.kt | 6 +- .../toolpkg/ToolPkgChatViewHookBridge.kt | 6 +- .../toolpkg/ToolPkgCommonBridgePlugin.kt | 16 +- .../toolpkg/ToolPkgHookBridgeSupport.kt | 6 +- .../plugins/toolpkg/ToolPkgLifecyclePlugin.kt | 6 +- .../toolpkg/ToolPkgPromptHookBridge.kt | 18 +- .../toolpkg/ToolPkgSummaryHookBridge.kt | 6 +- .../toolpkg/ToolPkgToolLifecycleBridge.kt | 12 +- .../toolpkg/ai/ToolPkgJsAiProviderService.kt | 8 +- .../operit/services/ChatServiceCore.kt | 2 +- .../services/TermuxCommandResultService.kt | 2 +- .../services/core/AttachmentDelegate.kt | 4 +- .../core/MessageCoordinationDelegate.kt | 2 +- .../core/MessageProcessingDelegate.kt | 4 +- .../composedsl/ToolPkgComposeDslActions.kt | 2 +- .../ToolPkgComposeDslDebugSnapshotStore.kt | 4 +- .../ToolPkgComposeDslGeneratedRenderers.kt | 4 +- .../composedsl/ToolPkgComposeDslScreen.kt | 10 +- .../composedsl/ToolPkgComposeDslWebView.kt | 4 +- .../markdown/XmlRenderPluginRegistry.kt | 8 +- .../browser/WebSessionBookmarkSheet.kt | 2 +- .../browser/WebSessionBrowserScreen.kt | 16 +- .../browser/WebSessionDownloadSheet.kt | 8 +- .../browser/WebSessionHistorySheet.kt | 4 +- .../websession/browser/WebSessionMenuSheet.kt | 2 +- .../browser/WebSessionMinimizedIndicator.kt | 2 +- .../websession/browser/WebSessionTabSheet.kt | 2 +- .../browser/WebSessionUserscriptSheet.kt | 12 +- .../workflow/screens/WorkflowDetailScreen.kt | 2 +- .../workflow/screens/WorkflowListScreen.kt | 2 +- .../workflow/viewmodel/WorkflowViewModel.kt | 4 +- .../chat/components/AttachmentSelector.kt | 4 +- .../chat/components/SharedFileTargetDialog.kt | 6 +- .../input/agent/AgentChatInputSection.kt | 2 +- .../input/classic/ClassicChatInputSection.kt | 2 +- .../export/htmlpackager/HtmlPackagerScreen.kt | 2 +- .../conversation/chat/screens/AIChatScreen.kt | 2 +- .../chat/viewmodel/ChatViewModel.kt | 4 +- .../chat/webview/LocalWebServer.kt | 2 +- .../chat/webview/WorkspaceFileSelector.kt | 4 +- .../chat/webview/workspace/FileManager.kt | 2 +- .../workspace/WorkspaceBackupManager.kt | 4 +- .../webview/workspace/WorkspaceManager.kt | 2 +- .../WorkspaceReadOnlyDocumentPreview.kt | 2 +- .../chat/webview/workspace/WorkspaceSetup.kt | 4 +- .../browser/WorkspaceBrowserOperations.kt | 2 +- .../workspace/links/WorkspaceFileLinkHost.kt | 2 +- .../process/WorkspaceRuleFileReader.kt | 2 +- .../memory/viewmodel/MemoryViewModel.kt | 2 +- .../workbench/MemoryDocumentImporter.kt | 2 +- .../dialogs/MCPPackageDetailsDialog.kt | 2 +- .../dialogs/PackageAddActionDialog.kt | 2 +- .../packages/dialogs/PackageDetailsDialog.kt | 4 +- .../dialogs/PackageTemplateIdentityDialog.kt | 4 +- .../packages/dialogs/ScriptExecutionDialog.kt | 2 +- .../market/ArtifactLocalInstallSupport.kt | 2 +- .../market/GitHubForgePublishService.kt | 2 +- .../market/MarketEntryInstallController.kt | 4 +- .../packages/market/MarketInstallMarker.kt | 2 +- .../packages/screens/PackageManagerDialogs.kt | 2 +- .../packages/screens/PackageManagerScreen.kt | 12 +- .../packages/screens/PackageSearch.kt | 2 +- .../packages/screens/PluginTabContent.kt | 2 +- .../screens/QuickPluginCreatorSetupSupport.kt | 4 +- .../viewmodel/ArtifactMarketViewModel.kt | 4 +- .../viewmodel/UnifiedMarketBrowseViewModel.kt | 4 +- .../viewmodel/UnifiedMarketDetailViewModel.kt | 4 +- .../resources/hub/ResourceHubViewModel.kt | 2 +- .../components/CharacterCardDialog.kt | 4 +- .../settings/display/DisplayBehaviorState.kt | 2 +- .../toolpermissions/ToolPermissionPage.kt | 2 +- .../ConfigurationResourceStorageScreen.kt | 2 +- .../ConfigurationResourceStorageViewModel.kt | 2 +- .../management/storage/DataStorageScreen.kt | 2 +- .../demo/components/PermissionLevelCard.kt | 4 +- .../support/demo/screens/ShizukuDemoScreen.kt | 8 +- .../support/demo/state/DemoStateManager.kt | 10 +- .../demo/viewmodel/ShizukuDemoViewModel.kt | 4 +- .../uidebugger/UIDebuggerViewModel.kt | 2 +- .../screen/FloatingScreenOcrScreen.kt | 2 +- .../assistance/operit/ui/main/MainActivity.kt | 2 +- .../ai/assistance/operit/ui/main/OperitApp.kt | 4 +- .../ui/main/components/DrawerContent.kt | 6 +- .../ui/main/navigation/AppRouteCatalog.kt | 6 +- ...onversationMarkupManagerResultLimitTest.kt | 2 +- .../a2ui/A2uiToolsTest.kt | 2 +- .../ToolPermissionModeSupportTest.kt | 2 +- .../shell}/ShellCommandSafetyTest.kt | 2 +- .../browser/BrowserNavigationPolicyTest.kt | 2 +- .../ComposeDslActionRetentionTest.kt | 4 +- .../PackageFileImportSupportTest.kt | 2 +- .../PackageSourceDeletionTest.kt | 2 +- .../PackageTemplateFactoryTest.kt | 2 +- .../ToolPkgApiDeclarationTest.kt | 2 +- .../ToolPkgMarketOriginCodecTest.kt | 2 +- .../ToolPkgManifestSelectionTest.kt | 2 +- .../PackageActivationResultTest.kt | 2 +- .../{ => runtime}/ToolPkgManagerTest.kt | 2 +- .../permissions/PermissionCapabilitiesTest.kt | 4 +- .../PermissionCapabilitySessionTest.kt | 2 +- .../PermissionOperationRouterTest.kt | 2 +- .../uiautomator/UiAutomatorDumpGuardTest.kt | 2 +- docs/TODO/chore/README.md | 2 + .../01-permissions.md | 2 +- .../tools-permissions-layout/02-layout.md | 303 +++++ .../chore/tools-permissions-layout/files.json | 1060 +++++++++++++++++ .../chore/tools-permissions-layout/index.md | 15 +- .../tools-permissions-layout/verification.md | 27 + .../architecture/DEFAULT_TOOLS_ARCH.md | 20 +- .../04_modules/android.md | 2 +- .../04_modules/ffmpeg.md | 2 +- .../04_modules/files.md | 8 +- .../04_modules/memory.md | 4 +- .../04_modules/network.md | 8 +- .../04_modules/okhttp.md | 4 +- .../04_modules/system.md | 14 +- .../04_modules/tasker.md | 4 +- .../04_modules/tool-types.md | 2 +- .../04_modules/ui.md | 7 +- .../05_hooks/render_and_toggle.md | 2 +- .../05_hooks/tool_lifecycle.md | 2 +- .../09_compatibility/api_versions.md | 4 +- .../toolpkg_developer_documentation/index.md | 4 +- tools/adb/JS_ADB_README.md | 16 +- tools/adb/JS_ADB_README_zh.md | 20 +- .../verify_layout_completion.py | 2 +- tools/string/count_ui_strings.py | 2 +- 291 files changed, 2172 insertions(+), 588 deletions(-) rename app/src/androidTest/js/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/media}/ffmpeg/ffmpeg_probe.js (100%) rename app/src/androidTest/js/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/web}/browser/main.js (100%) rename app/src/androidTest/js/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/web}/browser/probe.js (100%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool => builtin}/ToolGetter.kt (76%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool => builtin}/a2ui/A2uiToolDefinitions.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool => builtin}/a2ui/A2uiToolRuntime.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool => builtin}/a2ui/A2uiTools.kt (97%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/calculator}/StandardCalculator.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/chat}/StandardChatManagerTool.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/device}/StandardDeviceInfoToolExecutor.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/admin => builtin/filesystem}/AdminFileSystemTools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/filesystem}/LinuxFileSystemTools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool => builtin/filesystem}/PathValidator.kt (97%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/filesystem}/SafFileSystemTools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/filesystem}/StandardFileSystemTools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/media}/BluetoothSessionManager.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/media}/StandardFFmpegTool.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/media}/StandardMusicPlaybackTools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/memory}/MemoryQueryToolExecutor.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/settings}/StandardSoftwareSettingsModifyTools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/settings}/ToolPermissionModeSupport.kt (93%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/shell}/ShellCommandSafety.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/shell}/StandardShellToolExecutor.kt (94%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/admin => builtin/system}/AdminSystemOperationTools.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/system}/StandardIntentToolExecutor.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/system}/StandardSendBroadcastToolExecutor.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/system}/StandardSystemOperationTools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/terminal}/StandardTerminalCommandExecutor.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/admin => builtin/ui}/AdminUITools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/root => builtin/ui}/RootUITools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/ui}/StandardUITools.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/web}/CookiePrivacyManager.kt (92%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/web}/StandardBrowserSessionTools.kt (90%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/web}/StandardHttpTools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/web}/StandardWebVisitTool.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/BrowserDownloadSupport.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/BrowserNavigationPolicy.kt (96%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/BrowserPageExecutionSupport.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/BrowserToolSupport.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/BrowserWebViewSupport.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/WebSessionBrowserHost.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/WebSessionBrowserHostState.kt (95%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/WebSessionHistoryStore.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/WebSessionPermissionRequestActivity.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/WebSessionWebViewHost.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/UserscriptCapabilityRegistry.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/UserscriptMatcher.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/UserscriptMetadataParser.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/UserscriptModels.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/install/UserscriptImportCoordinator.kt (96%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/install/UserscriptImportPickerActivity.kt (97%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/runtime/UserscriptBootstrapScript.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/runtime/UserscriptCookieService.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/runtime/UserscriptStorageNotifier.kt (88%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/runtime/UserscriptTabStateStore.kt (91%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/runtime/UserscriptWebRequestEngine.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/runtime/WebSessionUserscriptManager.kt (97%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/storage/UserscriptEntities.kt (95%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/storage/UserscriptJsonStore.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/storage/UserscriptRepository.kt (94%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/userscript/ui/WebSessionUserscriptUiStateStore.kt (73%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/workflow}/StandardWorkflowTools.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => install}/PackageFileImportSupport.kt (96%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => install}/PackageSourceDeletion.kt (90%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => install}/PackageTemplateFactory.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => loader}/ToolPkgLoadOrder.kt (96%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => loader}/ToolPkgLoader.kt (89%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => metadata}/BuiltInPackageDefaults.kt (85%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => metadata}/ToolPkgApiVersion.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => metadata}/ToolPkgCommonPluginConstants.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => metadata}/ToolPkgManifestRequirement.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => metadata}/ToolPkgMarketOrigin.kt (97%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => metadata}/ToolPkgTemplateModels.kt (94%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => parser}/ToolPkgMainRegistrationScriptParser.kt (93%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => parser}/ToolPkgParser.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => runtime}/PackageActivationResult.kt (94%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => runtime}/PackageManager.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => runtime}/PackageManagerToolPkgFacade.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => runtime}/ToolPkgHookModels.kt (95%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => runtime}/ToolPkgManager.kt (97%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => runtime}/ToolPkgRuntimeMonitor.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/packTool/{ => uidsl}/ToolPkgComposeDslParser.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{system => permissions}/AndroidPermissionLevel.kt (93%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{system => permissions/authorization}/AccessibilityProviderInstaller.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{system => permissions/authorization}/RootAuthorizer.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{system => permissions/authorization}/ShizukuAuthorizer.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{system => permissions/authorization}/ShizukuInstaller.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{ => runtime}/AIToolHandler.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{ => runtime}/AIToolHook.kt (96%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{ => runtime}/ToolExecutionLimits.kt (86%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{ => runtime}/ToolProgressBus.kt (97%) rename app/src/main/java/com/ai/assistance/operit/core/tools/{ => runtime}/ToolRegistration.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/system/{ => capture}/MediaProjectionCaptureManager.kt (99%) rename app/src/main/java/com/ai/assistance/operit/core/tools/system/{ => capture}/MediaProjectionHolder.kt (92%) rename app/src/main/java/com/ai/assistance/operit/core/tools/system/{ => capture}/ScreenCaptureActivity.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/system/{ => capture}/ScreenCaptureService.kt (98%) rename app/src/main/java/com/ai/assistance/operit/core/tools/system/{ => shell}/AndroidShellExecutor.kt (95%) rename app/src/main/java/com/ai/assistance/operit/core/tools/system/{ => terminal}/OperitTerminalManager.kt (96%) rename app/src/main/java/com/ai/assistance/operit/core/tools/system/{ => terminal}/Terminal.kt (99%) rename app/src/test/java/com/ai/assistance/operit/core/tools/{defaultTool => builtin}/a2ui/A2uiToolsTest.kt (99%) rename app/src/test/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/settings}/ToolPermissionModeSupportTest.kt (95%) rename app/src/test/java/com/ai/assistance/operit/core/tools/{defaultTool/standard => builtin/shell}/ShellCommandSafetyTest.kt (98%) rename app/src/test/java/com/ai/assistance/operit/core/tools/{defaultTool/websession => builtin/web/session}/browser/BrowserNavigationPolicyTest.kt (98%) rename app/src/test/java/com/ai/assistance/operit/core/tools/packTool/{ => install}/PackageFileImportSupportTest.kt (93%) rename app/src/test/java/com/ai/assistance/operit/core/tools/packTool/{ => install}/PackageSourceDeletionTest.kt (97%) rename app/src/test/java/com/ai/assistance/operit/core/tools/packTool/{ => install}/PackageTemplateFactoryTest.kt (98%) rename app/src/test/java/com/ai/assistance/operit/core/tools/packTool/{ => metadata}/ToolPkgApiDeclarationTest.kt (94%) rename app/src/test/java/com/ai/assistance/operit/core/tools/packTool/{ => metadata}/ToolPkgMarketOriginCodecTest.kt (97%) rename app/src/test/java/com/ai/assistance/operit/core/tools/packTool/{ => parser}/ToolPkgManifestSelectionTest.kt (96%) rename app/src/test/java/com/ai/assistance/operit/core/tools/packTool/{ => runtime}/PackageActivationResultTest.kt (97%) rename app/src/test/java/com/ai/assistance/operit/core/tools/packTool/{ => runtime}/ToolPkgManagerTest.kt (98%) create mode 100644 docs/TODO/chore/tools-permissions-layout/02-layout.md create mode 100644 docs/TODO/chore/tools-permissions-layout/files.json create mode 100644 docs/TODO/chore/tools-permissions-layout/verification.md diff --git a/app/src/androidTest/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslWebViewFocusAndroidTest.kt b/app/src/androidTest/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslWebViewFocusAndroidTest.kt index ab0285d976..0536322c49 100644 --- a/app/src/androidTest/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslWebViewFocusAndroidTest.kt +++ b/app/src/androidTest/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslWebViewFocusAndroidTest.kt @@ -29,7 +29,7 @@ import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslNode +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslNode import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Rule diff --git a/app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/ffmpeg/ffmpeg_probe.js b/app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/media/ffmpeg/ffmpeg_probe.js similarity index 100% rename from app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/ffmpeg/ffmpeg_probe.js rename to app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/media/ffmpeg/ffmpeg_probe.js diff --git a/app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/main.js b/app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/main.js similarity index 100% rename from app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/main.js rename to app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/main.js diff --git a/app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/probe.js b/app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/probe.js similarity index 100% rename from app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/probe.js rename to app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/probe.js diff --git a/app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_contract/suspend_await.js b/app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_contract/suspend_await.js index 2a936bdbcf..5b4c5c20af 100644 --- a/app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_contract/suspend_await.js +++ b/app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_contract/suspend_await.js @@ -7,7 +7,7 @@ const { runSuite, } = require('./common'); -const AndroidShellExecutor = Java.com.ai.assistance.operit.core.tools.system.AndroidShellExecutor; +const AndroidShellExecutor = Java.com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor; const StandardActionListener = Java.com.ai.assistance.operit.core.tools.system.action.StandardActionListener; const StreamBuildersKt = Java.type('com.ai.assistance.operit.util.stream.StreamBuildersKt'); @@ -28,7 +28,7 @@ function assertCommandResultProxy(result, label) { assert(result && typeof result === 'object', (label || 'result') + ' should be an object'); assertEq( String(result.className), - 'com.ai.assistance.operit.core.tools.system.AndroidShellExecutor$CommandResult', + 'com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor$CommandResult', (label || 'result') + ' className mismatch' ); assertEq(typeof result.success, 'boolean', (label || 'result') + ' success should be boolean'); @@ -51,7 +51,7 @@ exports.run = async function run() { test('Java.callSuspend awaits companion suspend method and returns proxy result', async () => { const result = await withTimeout( Java.callSuspend( - 'com.ai.assistance.operit.core.tools.system.AndroidShellExecutor', + 'com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor', 'executeShellCommand', 'echo bridge-contract-suspend-top-level' ), diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6bcd5c683f..7e37adc31c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -120,7 +120,7 @@ tools:node="remove" /> @@ -327,7 +327,7 @@ android:foregroundServiceType="dataSync" /> diff --git a/app/src/main/java/com/ai/assistance/operit/api/chat/EnhancedAIService.kt b/app/src/main/java/com/ai/assistance/operit/api/chat/EnhancedAIService.kt index b54aac3afb..13e5687102 100644 --- a/app/src/main/java/com/ai/assistance/operit/api/chat/EnhancedAIService.kt +++ b/app/src/main/java/com/ai/assistance/operit/api/chat/EnhancedAIService.kt @@ -37,11 +37,11 @@ import com.ai.assistance.operit.core.chat.hooks.mergeAdjacentTurns import com.ai.assistance.operit.core.chat.hooks.toPromptTurns import com.ai.assistance.operit.core.chat.hooks.toRoleContentPairs import com.ai.assistance.operit.core.application.ActivityLifecycleManager -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.core.tools.climode.CliToolModeSupport import com.ai.assistance.operit.core.tools.climode.ToolExposureMode -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilitySession import com.ai.assistance.operit.data.model.FunctionType import com.ai.assistance.operit.data.model.InputProcessingState diff --git a/app/src/main/java/com/ai/assistance/operit/core/application/OperitApplication.kt b/app/src/main/java/com/ai/assistance/operit/core/application/OperitApplication.kt index 72fd4c08d2..e123e36db3 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/application/OperitApplication.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/application/OperitApplication.kt @@ -28,9 +28,9 @@ import com.ai.assistance.operit.plugins.lifecycle.AppLifecycleEvent import com.ai.assistance.operit.plugins.lifecycle.AppLifecycleHookParams import com.ai.assistance.operit.plugins.lifecycle.AppLifecycleHookPluginRegistry import com.ai.assistance.operit.core.config.SystemPromptConfig -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor -import com.ai.assistance.operit.core.tools.system.Terminal +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor +import com.ai.assistance.operit.core.tools.system.terminal.Terminal import com.ai.assistance.operit.core.workflow.WorkflowSchedulerInitializer import com.ai.assistance.operit.data.backup.RoomDatabaseBackupPreferences import com.ai.assistance.operit.data.backup.RoomDatabaseBackupScheduler diff --git a/app/src/main/java/com/ai/assistance/operit/core/chat/AIMessageManager.kt b/app/src/main/java/com/ai/assistance/operit/core/chat/AIMessageManager.kt index d14c9c3012..cc52ba0c22 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/chat/AIMessageManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/chat/AIMessageManager.kt @@ -25,9 +25,9 @@ import com.ai.assistance.operit.core.chat.hooks.PromptTurnKind import com.ai.assistance.operit.core.chat.plugins.MessageProcessingController import com.ai.assistance.operit.core.chat.plugins.MessageProcessingHookParams import com.ai.assistance.operit.core.chat.plugins.MessageProcessingPluginRegistry -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.MemoryQueryResultData -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.AttachmentInfo import com.ai.assistance.operit.data.model.ChatMessage diff --git a/app/src/main/java/com/ai/assistance/operit/core/chat/context/ConversationService.kt b/app/src/main/java/com/ai/assistance/operit/core/chat/context/ConversationService.kt index 95d01e01f2..f6a6dccf7e 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/chat/context/ConversationService.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/chat/context/ConversationService.kt @@ -20,8 +20,8 @@ import com.ai.assistance.operit.core.chat.hooks.toPromptTurns import com.ai.assistance.operit.core.config.SystemPromptConfig import com.ai.assistance.operit.core.tools.climode.ToolExposureMode import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ConversationSummaryConfig import com.ai.assistance.operit.data.model.FunctionType @@ -47,7 +47,7 @@ import com.ai.assistance.operit.util.stream.TextStreamEventType import com.ai.assistance.operit.util.stream.TextStreamRevisionTracker import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch -import com.ai.assistance.operit.core.tools.ToolProgressBus +import com.ai.assistance.operit.core.tools.runtime.ToolProgressBus import com.ai.assistance.operit.util.streamnative.NativeXmlSplitter import com.github.difflib.DiffUtils import com.github.difflib.UnifiedDiffUtils diff --git a/app/src/main/java/com/ai/assistance/operit/core/chat/protocol/ConversationMarkupManager.kt b/app/src/main/java/com/ai/assistance/operit/core/chat/protocol/ConversationMarkupManager.kt index d67bce04fb..a65707cbc0 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/chat/protocol/ConversationMarkupManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/chat/protocol/ConversationMarkupManager.kt @@ -3,7 +3,7 @@ package com.ai.assistance.operit.core.chat.protocol import android.content.Context import com.ai.assistance.operit.R import com.ai.assistance.operit.core.chat.media.MediaLinkParser -import com.ai.assistance.operit.core.tools.ToolExecutionLimits +import com.ai.assistance.operit.core.tools.runtime.ToolExecutionLimits import com.ai.assistance.operit.core.chat.protocol.ChatMarkupRegex import com.ai.assistance.operit.util.media.ImagePoolManager import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/chat/tools/ToolExecutionManager.kt b/app/src/main/java/com/ai/assistance/operit/core/chat/tools/ToolExecutionManager.kt index 30414ad50e..51aa2eaa1e 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/chat/tools/ToolExecutionManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/chat/tools/ToolExecutionManager.kt @@ -5,16 +5,16 @@ import com.ai.assistance.operit.ui.common.a2ui.CardFences import android.content.Context import com.ai.assistance.operit.R import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.AIToolHookDecision +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHookDecision import com.ai.assistance.operit.core.chat.protocol.toolFailurePayload import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutor +import com.ai.assistance.operit.core.tools.runtime.ToolExecutor import com.ai.assistance.operit.core.tools.climode.CliToolModeSupport import com.ai.assistance.operit.core.tools.climode.ToolExposureMode import com.ai.assistance.operit.data.model.ToolInvocation import com.ai.assistance.operit.data.model.ToolResult -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilitySession import com.ai.assistance.operit.util.stream.StreamCollector diff --git a/app/src/main/java/com/ai/assistance/operit/core/config/SystemPromptConfig.kt b/app/src/main/java/com/ai/assistance/operit/core/config/SystemPromptConfig.kt index 431fe5f31b..b312156562 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/config/SystemPromptConfig.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/config/SystemPromptConfig.kt @@ -6,7 +6,7 @@ import com.ai.assistance.operit.core.chat.hooks.PromptHookContext import com.ai.assistance.operit.core.chat.hooks.PromptHookRegistry import com.ai.assistance.operit.core.tools.climode.CliToolModeSupport import com.ai.assistance.operit.core.tools.climode.ToolExposureMode -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.preferences.ApiPreferences import com.ai.assistance.operit.data.skill.SkillRepository import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.WorkspaceRuleFileReader diff --git a/app/src/main/java/com/ai/assistance/operit/core/config/SystemToolPrompts.kt b/app/src/main/java/com/ai/assistance/operit/core/config/SystemToolPrompts.kt index 4315712ae1..edeb081ae1 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/config/SystemToolPrompts.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/config/SystemToolPrompts.kt @@ -5,7 +5,7 @@ import com.ai.assistance.operit.core.chat.hooks.PromptHookRegistry import com.ai.assistance.operit.data.model.SystemToolPromptCategory import com.ai.assistance.operit.data.model.ToolPrompt import com.ai.assistance.operit.data.model.ToolParameterSchema -import com.ai.assistance.operit.core.tools.defaultTool.a2ui.A2uiToolDefinitions +import com.ai.assistance.operit.core.tools.builtin.a2ui.A2uiToolDefinitions /** * 系统工具提示词管理器 diff --git a/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/ChatMemoryRebuildManager.kt b/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/ChatMemoryRebuildManager.kt index aaa3b94dae..11d84d4dca 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/ChatMemoryRebuildManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/ChatMemoryRebuildManager.kt @@ -4,7 +4,7 @@ import android.content.Context import com.ai.assistance.operit.R import com.ai.assistance.operit.data.memory.resolveChatMemorySpaceId import com.ai.assistance.operit.api.chat.EnhancedAIService -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.model.ChatHistory import com.ai.assistance.operit.data.model.FunctionType import com.ai.assistance.operit.data.preferences.CharacterCardManager diff --git a/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/ConversationMemoryExtractor.kt b/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/ConversationMemoryExtractor.kt index d3d217f165..0e615451a3 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/ConversationMemoryExtractor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/ConversationMemoryExtractor.kt @@ -6,7 +6,7 @@ import com.ai.assistance.operit.core.chat.protocol.ChatMarkupRegex import com.ai.assistance.operit.core.chat.protocol.ThinkingMarkup import com.ai.assistance.operit.R import com.ai.assistance.operit.api.chat.AIService -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.model.Memory import com.ai.assistance.operit.data.preferences.ApiPreferences import com.ai.assistance.operit.data.preferences.MemorySearchSettingsPreferences diff --git a/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/MemoryAutoSaveScheduler.kt b/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/MemoryAutoSaveScheduler.kt index 85d42a41a7..6006e40ba9 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/MemoryAutoSaveScheduler.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/memory/extraction/MemoryAutoSaveScheduler.kt @@ -2,7 +2,7 @@ package com.ai.assistance.operit.core.memory.extraction import android.content.Context import com.ai.assistance.operit.api.chat.EnhancedAIService -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.db.AppDatabase import com.ai.assistance.operit.data.model.FunctionType import com.ai.assistance.operit.data.model.MemoryAutoSaveCandidate diff --git a/app/src/main/java/com/ai/assistance/operit/core/performance/PerformanceMonitorManager.kt b/app/src/main/java/com/ai/assistance/operit/core/performance/PerformanceMonitorManager.kt index 702c260e73..5a3c703622 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/performance/PerformanceMonitorManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/performance/PerformanceMonitorManager.kt @@ -8,7 +8,7 @@ import android.os.Process import android.os.SystemClock import android.system.Os import android.system.OsConstants -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.terminal.TerminalManager import com.ai.assistance.operit.util.logging.AppLogger import java.io.File diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/ToolPackage.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/ToolPackage.kt index 362a87c8d5..69916a97b1 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/ToolPackage.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/ToolPackage.kt @@ -3,7 +3,7 @@ package com.ai.assistance.operit.core.tools import android.content.Context import android.os.Build import com.ai.assistance.operit.core.tools.javascript.JsToolManager - import com.ai.assistance.operit.core.tools.packTool.PackageManager + import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.data.model.ToolValidationResult @@ -32,6 +32,7 @@ import kotlinx.serialization.json.JsonPrimitive import kotlinx.coroutines.runBlocking import kotlinx.coroutines.flow.last import java.util.Locale +import com.ai.assistance.operit.core.tools.runtime.ToolExecutor /** * Represents a package of tools that can be imported by the AI diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/agent/PhoneAgent.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/agent/PhoneAgent.kt index d91d03440b..111f45cd7f 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/agent/PhoneAgent.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/agent/PhoneAgent.kt @@ -13,11 +13,11 @@ import androidx.core.content.FileProvider import com.ai.assistance.operit.R import com.ai.assistance.operit.api.chat.AIService import com.ai.assistance.operit.core.chat.hooks.toPromptTurns -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.AppListData -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardUITools +import com.ai.assistance.operit.core.tools.builtin.ui.StandardUITools import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/ToolGetter.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ToolGetter.kt similarity index 76% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/ToolGetter.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ToolGetter.kt index 91ea22b74b..3e428564ec 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/ToolGetter.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ToolGetter.kt @@ -1,11 +1,35 @@ -package com.ai.assistance.operit.core.tools.defaultTool +package com.ai.assistance.operit.core.tools.builtin import android.content.Context -import com.ai.assistance.operit.core.tools.defaultTool.admin.* -import com.ai.assistance.operit.core.tools.defaultTool.root.* -import com.ai.assistance.operit.core.tools.defaultTool.standard.* -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel + + + +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.data.preferences.androidPermissionPreferences +import com.ai.assistance.operit.core.tools.builtin.calculator.StandardCalculator +import com.ai.assistance.operit.core.tools.builtin.chat.StandardChatManagerTool +import com.ai.assistance.operit.core.tools.builtin.device.StandardDeviceInfoToolExecutor +import com.ai.assistance.operit.core.tools.builtin.filesystem.AdminFileSystemTools +import com.ai.assistance.operit.core.tools.builtin.filesystem.StandardFileSystemTools +import com.ai.assistance.operit.core.tools.builtin.media.StandardFFmpegConvertToolExecutor +import com.ai.assistance.operit.core.tools.builtin.media.StandardFFmpegInfoToolExecutor +import com.ai.assistance.operit.core.tools.builtin.media.StandardFFmpegToolExecutor +import com.ai.assistance.operit.core.tools.builtin.media.StandardMusicPlaybackTools +import com.ai.assistance.operit.core.tools.builtin.memory.MemoryQueryToolExecutor +import com.ai.assistance.operit.core.tools.builtin.settings.StandardSoftwareSettingsModifyTools +import com.ai.assistance.operit.core.tools.builtin.shell.StandardShellToolExecutor +import com.ai.assistance.operit.core.tools.builtin.system.AdminSystemOperationTools +import com.ai.assistance.operit.core.tools.builtin.system.StandardIntentToolExecutor +import com.ai.assistance.operit.core.tools.builtin.system.StandardSendBroadcastToolExecutor +import com.ai.assistance.operit.core.tools.builtin.system.StandardSystemOperationTools +import com.ai.assistance.operit.core.tools.builtin.terminal.StandardTerminalCommandExecutor +import com.ai.assistance.operit.core.tools.builtin.ui.AdminUITools +import com.ai.assistance.operit.core.tools.builtin.ui.RootUITools +import com.ai.assistance.operit.core.tools.builtin.ui.StandardUITools +import com.ai.assistance.operit.core.tools.builtin.web.StandardBrowserSessionTools +import com.ai.assistance.operit.core.tools.builtin.web.StandardHttpTools +import com.ai.assistance.operit.core.tools.builtin.web.StandardWebVisitTool +import com.ai.assistance.operit.core.tools.builtin.workflow.StandardWorkflowTools /** 工具获取器 - 根据三档用户模式获取工具,管理员工具在操作时按实际授权选择后端 */ object ToolGetter { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolDefinitions.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolDefinitions.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolDefinitions.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolDefinitions.kt index d283c69673..edbd97302a 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolDefinitions.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolDefinitions.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.a2ui +package com.ai.assistance.operit.core.tools.builtin.a2ui import com.ai.assistance.operit.data.model.SystemToolPromptCategory import com.ai.assistance.operit.data.model.ToolParameterSchema diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolRuntime.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolRuntime.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolRuntime.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolRuntime.kt index 84495736e1..6c64e67e41 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolRuntime.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolRuntime.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.a2ui +package com.ai.assistance.operit.core.tools.builtin.a2ui import com.ai.assistance.operit.core.chat.tools.ToolExecutionManager.ToolRuntimeContext import com.ai.assistance.operit.ui.common.a2ui.CardDelivery diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiTools.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiTools.kt index 0078867906..16478c4916 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiTools.kt @@ -1,8 +1,8 @@ -package com.ai.assistance.operit.core.tools.defaultTool.a2ui +package com.ai.assistance.operit.core.tools.builtin.a2ui import android.content.Context import com.ai.assistance.operit.core.chat.tools.ToolExecutionManager -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardCalculator.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/calculator/StandardCalculator.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardCalculator.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/calculator/StandardCalculator.kt index ec75b62e78..7bec4ed615 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardCalculator.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/calculator/StandardCalculator.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.calculator import com.ai.assistance.operit.core.tools.CalculationResultData import com.ai.assistance.operit.core.tools.DateResultData diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardChatManagerTool.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/chat/StandardChatManagerTool.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardChatManagerTool.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/chat/StandardChatManagerTool.kt index 833313a5e9..2d733388d1 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardChatManagerTool.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/chat/StandardChatManagerTool.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.chat import android.content.ComponentName import android.content.Context diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardDeviceInfoToolExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/device/StandardDeviceInfoToolExecutor.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardDeviceInfoToolExecutor.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/device/StandardDeviceInfoToolExecutor.kt index d12b500507..324edf4612 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardDeviceInfoToolExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/device/StandardDeviceInfoToolExecutor.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.device import android.content.Context import android.content.Intent @@ -10,7 +10,7 @@ import android.os.StatFs import android.provider.Settings import com.ai.assistance.operit.core.tools.DeviceInfoResultData import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutor +import com.ai.assistance.operit.core.tools.runtime.ToolExecutor import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminFileSystemTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/AdminFileSystemTools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminFileSystemTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/AdminFileSystemTools.kt index 2d043eb36a..0c03afbffa 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminFileSystemTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/AdminFileSystemTools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.admin +package com.ai.assistance.operit.core.tools.builtin.filesystem import android.content.ActivityNotFoundException import android.content.ClipData @@ -7,7 +7,7 @@ import android.content.Intent import android.webkit.MimeTypeMap import androidx.core.content.FileProvider import com.ai.assistance.operit.BuildConfig -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.DirectoryListingData import com.ai.assistance.operit.core.tools.FileContentData import com.ai.assistance.operit.core.tools.FileExistsData @@ -16,13 +16,13 @@ import com.ai.assistance.operit.core.tools.FileOperationData import com.ai.assistance.operit.core.tools.FilePartContentData import com.ai.assistance.operit.core.tools.FindFilesResultData import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutionLimits -import com.ai.assistance.operit.core.tools.ToolProgressBus -import com.ai.assistance.operit.core.tools.defaultTool.PathValidator -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardFileSystemTools +import com.ai.assistance.operit.core.tools.runtime.ToolExecutionLimits +import com.ai.assistance.operit.core.tools.runtime.ToolProgressBus +import com.ai.assistance.operit.core.tools.builtin.filesystem.PathValidator +import com.ai.assistance.operit.core.tools.builtin.filesystem.StandardFileSystemTools import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver import com.ai.assistance.operit.core.tools.permissions.PermissionOperationRouter -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor +import com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/LinuxFileSystemTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/LinuxFileSystemTools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/LinuxFileSystemTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/LinuxFileSystemTools.kt index 1a940dd0c1..0d72b5e90b 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/LinuxFileSystemTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/LinuxFileSystemTools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.filesystem import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger @@ -12,13 +12,13 @@ import com.ai.assistance.operit.core.tools.FilePartContentData import com.ai.assistance.operit.core.tools.FindFilesResultData import com.ai.assistance.operit.core.tools.GrepResultData import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolProgressBus -import com.ai.assistance.operit.core.tools.ToolExecutionLimits +import com.ai.assistance.operit.core.tools.runtime.ToolProgressBus +import com.ai.assistance.operit.core.tools.runtime.ToolExecutionLimits import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.util.files.FileUtils -import com.ai.assistance.operit.core.tools.defaultTool.PathValidator +import com.ai.assistance.operit.core.tools.builtin.filesystem.PathValidator import kotlinx.coroutines.* import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Semaphore diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/PathValidator.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/PathValidator.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/PathValidator.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/PathValidator.kt index 1055033993..450b182625 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/PathValidator.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/PathValidator.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool +package com.ai.assistance.operit.core.tools.builtin.filesystem import com.ai.assistance.operit.core.tools.FileOperationData import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/SafFileSystemTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/SafFileSystemTools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/SafFileSystemTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/SafFileSystemTools.kt index 4d74aa97a8..ec3d5c5c5e 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/SafFileSystemTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/SafFileSystemTools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.filesystem import android.content.Context import android.database.Cursor @@ -16,8 +16,8 @@ import com.ai.assistance.operit.core.tools.FilePartContentData import com.ai.assistance.operit.core.tools.FindFilesResultData import com.ai.assistance.operit.core.tools.GrepResultData import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutionLimits -import com.ai.assistance.operit.core.tools.ToolProgressBus +import com.ai.assistance.operit.core.tools.runtime.ToolExecutionLimits +import com.ai.assistance.operit.core.tools.runtime.ToolProgressBus import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.data.preferences.ApiPreferences diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/StandardFileSystemTools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/StandardFileSystemTools.kt index 59f36e65c8..15f117263b 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/StandardFileSystemTools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.filesystem import android.content.Context import com.ai.assistance.operit.R @@ -16,10 +16,10 @@ import com.ai.assistance.operit.core.tools.FileInfoData import com.ai.assistance.operit.core.tools.FileOperationData import com.ai.assistance.operit.core.tools.FilePartContentData import com.ai.assistance.operit.core.tools.FindFilesResultData -import com.ai.assistance.operit.core.tools.ToolProgressBus +import com.ai.assistance.operit.core.tools.runtime.ToolProgressBus import com.ai.assistance.operit.core.tools.GrepResultData import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutionLimits +import com.ai.assistance.operit.core.tools.runtime.ToolExecutionLimits import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.FunctionType import com.ai.assistance.operit.data.model.ModelParameter @@ -70,11 +70,12 @@ import com.ai.assistance.operit.data.preferences.ModelConfigManager import com.ai.assistance.operit.terminal.TerminalManager import com.ai.assistance.operit.terminal.provider.filesystem.FileSystemProvider import com.ai.assistance.operit.terminal.utils.SSHFileConnectionManager -import com.ai.assistance.operit.core.tools.defaultTool.PathValidator +import com.ai.assistance.operit.core.tools.builtin.filesystem.PathValidator import com.ai.assistance.operit.util.android.LocaleUtils import com.ai.assistance.operit.util.ripgrep.NativeRipgrep import org.json.JSONObject import java.util.concurrent.atomic.AtomicInteger +import com.ai.assistance.operit.core.tools.builtin.web.StandardWebVisitTool /** * Collection of file system operation tools for the AI assistant These tools use Java File APIs for diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/BluetoothSessionManager.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/BluetoothSessionManager.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/BluetoothSessionManager.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/BluetoothSessionManager.kt index faf52c5b17..d8e57e11f5 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/BluetoothSessionManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/BluetoothSessionManager.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.media import android.annotation.SuppressLint import android.bluetooth.BluetoothAdapter diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFFmpegTool.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardFFmpegTool.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFFmpegTool.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardFFmpegTool.kt index 1eff9787c6..a7e8b7d9fb 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFFmpegTool.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardFFmpegTool.kt @@ -1,9 +1,9 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.media import android.content.Context import com.ai.assistance.operit.core.tools.FFmpegResultData import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutor +import com.ai.assistance.operit.core.tools.runtime.ToolExecutor import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.data.model.ToolValidationResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardMusicPlaybackTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardMusicPlaybackTools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardMusicPlaybackTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardMusicPlaybackTools.kt index 94e9c14345..afef6c25fc 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardMusicPlaybackTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardMusicPlaybackTools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.media import android.content.Context import android.net.Uri diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/MemoryQueryToolExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/memory/MemoryQueryToolExecutor.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/MemoryQueryToolExecutor.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/memory/MemoryQueryToolExecutor.kt index d815301332..485ccd28f6 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/MemoryQueryToolExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/memory/MemoryQueryToolExecutor.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.memory import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger @@ -7,7 +7,7 @@ import com.ai.assistance.operit.core.tools.MemoryQueryResultData import com.ai.assistance.operit.core.tools.MemoryLinkResultData import com.ai.assistance.operit.core.tools.MemoryLinkQueryResultData import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutor +import com.ai.assistance.operit.core.tools.runtime.ToolExecutor import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.CharacterCardMemoryProfileBindingMode import com.ai.assistance.operit.data.model.Memory diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSoftwareSettingsModifyTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/settings/StandardSoftwareSettingsModifyTools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSoftwareSettingsModifyTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/settings/StandardSoftwareSettingsModifyTools.kt index aa6cbf0d33..1361d4a399 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSoftwareSettingsModifyTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/settings/StandardSoftwareSettingsModifyTools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.settings import com.ai.assistance.operit.data.model.ModelConfigDefaults @@ -49,7 +49,7 @@ import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.core.tools.ToolPermissionModeResultData import com.ai.assistance.operit.core.tools.javascript.JsEngine import com.ai.assistance.operit.core.tools.javascript.JsExecutionTraceRecorder -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ApiProviderType import com.ai.assistance.operit.data.model.CharacterCard diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ToolPermissionModeSupport.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/settings/ToolPermissionModeSupport.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ToolPermissionModeSupport.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/settings/ToolPermissionModeSupport.kt index a4f9ceae01..b8f66c5183 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ToolPermissionModeSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/settings/ToolPermissionModeSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.settings import com.ai.assistance.operit.core.tools.ToolPermissionModeResultData import com.ai.assistance.operit.ui.permissions.PermissionLevel diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ShellCommandSafety.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/shell/ShellCommandSafety.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ShellCommandSafety.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/shell/ShellCommandSafety.kt index b8baf82689..3cb5081408 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ShellCommandSafety.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/shell/ShellCommandSafety.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.shell /** * Lightweight shell command safety validator. diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardShellToolExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/shell/StandardShellToolExecutor.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardShellToolExecutor.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/shell/StandardShellToolExecutor.kt index 2b6152ab4c..86941a73fa 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardShellToolExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/shell/StandardShellToolExecutor.kt @@ -1,11 +1,11 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.shell import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.core.tools.ADBResultData import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor -import com.ai.assistance.operit.core.tools.system.ShizukuAuthorizer +import com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor +import com.ai.assistance.operit.core.tools.permissions.authorization.ShizukuAuthorizer import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.data.model.ToolValidationResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminSystemOperationTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/AdminSystemOperationTools.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminSystemOperationTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/AdminSystemOperationTools.kt index 101d5a2fe1..2697ad5b7b 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminSystemOperationTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/AdminSystemOperationTools.kt @@ -1,16 +1,17 @@ -package com.ai.assistance.operit.core.tools.defaultTool.admin +package com.ai.assistance.operit.core.tools.builtin.system import android.content.Context import com.ai.assistance.operit.core.tools.AppOperationData import com.ai.assistance.operit.core.tools.NotificationData import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.core.tools.SystemSettingData -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardSystemOperationTools +import com.ai.assistance.operit.core.tools.builtin.system.StandardSystemOperationTools import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor +import com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.util.logging.AppLogger +import com.ai.assistance.operit.core.tools.builtin.filesystem.AdminFileSystemTools /** 管理员系统工具按现有授权能力执行 Shell 或标准系统操作。 */ open class AdminSystemOperationTools(private val context: Context) : StandardSystemOperationTools(context) { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardIntentToolExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardIntentToolExecutor.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardIntentToolExecutor.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardIntentToolExecutor.kt index 7769c1c058..82113cabdc 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardIntentToolExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardIntentToolExecutor.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.system import android.content.Context import android.content.Intent diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSendBroadcastToolExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSendBroadcastToolExecutor.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSendBroadcastToolExecutor.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSendBroadcastToolExecutor.kt index 12a6f42c46..f4811413fb 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSendBroadcastToolExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSendBroadcastToolExecutor.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.system import android.content.Context import android.content.Intent diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSystemOperationTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSystemOperationTools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSystemOperationTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSystemOperationTools.kt index c451619304..109aac3044 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSystemOperationTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSystemOperationTools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.system import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -30,8 +30,8 @@ import com.ai.assistance.operit.core.tools.LocationData import com.ai.assistance.operit.core.tools.NotificationData import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.core.tools.SystemSettingData -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionPermissionRequestCoordinator -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionPermissionRequestCoordinator +import com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import java.util.Locale @@ -53,6 +53,7 @@ import com.ai.assistance.operit.services.notification.OperitNotificationStore import com.ai.assistance.operit.R import com.ai.assistance.operit.util.files.AndroidUserPathUtils import com.ai.assistance.operit.util.files.OperitPaths +import com.ai.assistance.operit.core.tools.builtin.media.BluetoothSessionManager /** 提供系统级操作的工具类 包括系统设置修改、应用安装和卸载等 这些操作需要用户明确授权 */ open class StandardSystemOperationTools(private val context: Context) { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardTerminalCommandExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/terminal/StandardTerminalCommandExecutor.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardTerminalCommandExecutor.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/terminal/StandardTerminalCommandExecutor.kt index 620c41aee4..c295ca9100 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardTerminalCommandExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/terminal/StandardTerminalCommandExecutor.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.terminal import android.content.Context import com.ai.assistance.operit.R @@ -6,7 +6,7 @@ import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.core.tools.* import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult -import com.ai.assistance.operit.core.tools.system.Terminal +import com.ai.assistance.operit.core.tools.system.terminal.Terminal import com.ai.assistance.operit.terminal.provider.type.HiddenExecResult import com.ai.assistance.operit.terminal.view.domain.ansi.TerminalChar import kotlinx.coroutines.* diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminUITools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/AdminUITools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminUITools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/AdminUITools.kt index e51a064513..48ee3bda6d 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminUITools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/AdminUITools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.admin +package com.ai.assistance.operit.core.tools.builtin.ui import android.annotation.SuppressLint import android.content.ClipData @@ -10,10 +10,10 @@ import com.ai.assistance.operit.core.tools.SimplifiedUINode import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.core.tools.UIActionResultData import com.ai.assistance.operit.core.tools.UIPageResultData -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardUITools +import com.ai.assistance.operit.core.tools.builtin.ui.StandardUITools import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor -import com.ai.assistance.operit.core.tools.system.ShellIdentity +import com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor +import com.ai.assistance.operit.core.tools.system.shell.ShellIdentity import com.ai.assistance.operit.core.tools.system.uiautomator.UiAutomatorDumpGuard import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootUITools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/RootUITools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootUITools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/RootUITools.kt index f0b52dbd44..b25d28e443 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootUITools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/RootUITools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.root +package com.ai.assistance.operit.core.tools.builtin.ui import android.content.ClipData import android.content.ClipboardManager @@ -8,9 +8,9 @@ import com.ai.assistance.operit.core.tools.SimplifiedUINode import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.core.tools.UIActionResultData import com.ai.assistance.operit.core.tools.UIPageResultData -import com.ai.assistance.operit.core.tools.defaultTool.admin.AdminUITools +import com.ai.assistance.operit.core.tools.builtin.ui.AdminUITools import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver -import com.ai.assistance.operit.core.tools.system.ShellIdentity +import com.ai.assistance.operit.core.tools.system.shell.ShellIdentity import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardUITools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/StandardUITools.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardUITools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/StandardUITools.kt index 8df2c40517..405d969f82 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardUITools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/StandardUITools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.ui import android.content.Context import android.graphics.Bitmap @@ -12,10 +12,10 @@ import com.ai.assistance.operit.core.tools.SimplifiedUINode import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.core.tools.UIPageResultData import com.ai.assistance.operit.core.tools.AppListData -import com.ai.assistance.operit.core.tools.defaultTool.ToolGetter -import com.ai.assistance.operit.core.tools.system.MediaProjectionCaptureManager -import com.ai.assistance.operit.core.tools.system.MediaProjectionHolder -import com.ai.assistance.operit.core.tools.system.ScreenCaptureActivity +import com.ai.assistance.operit.core.tools.builtin.ToolGetter +import com.ai.assistance.operit.core.tools.system.capture.MediaProjectionCaptureManager +import com.ai.assistance.operit.core.tools.system.capture.MediaProjectionHolder +import com.ai.assistance.operit.core.tools.system.capture.ScreenCaptureActivity import kotlinx.coroutines.delay import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.FunctionType diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/CookiePrivacyManager.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/CookiePrivacyManager.kt similarity index 92% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/CookiePrivacyManager.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/CookiePrivacyManager.kt index 34ec15bc3c..350c0e9e82 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/CookiePrivacyManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/CookiePrivacyManager.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.web import android.webkit.CookieManager import kotlin.coroutines.resume diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardBrowserSessionTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardBrowserSessionTools.kt similarity index 90% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardBrowserSessionTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardBrowserSessionTools.kt index 7ebd2565d6..3f7b495d4d 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardBrowserSessionTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardBrowserSessionTools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.web import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -41,11 +41,11 @@ import android.webkit.WebViewClient import com.ai.assistance.operit.R import com.ai.assistance.operit.core.application.ActivityLifecycleManager import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutor -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.* -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptInstallSourceType -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime.WebSessionUserscriptManager -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.storage.UserscriptRepository +import com.ai.assistance.operit.core.tools.runtime.ToolExecutor + +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptInstallSourceType +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime.WebSessionUserscriptManager +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.storage.UserscriptRepository import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.util.logging.AppLogger @@ -69,6 +69,84 @@ import kotlinx.coroutines.runBlocking import androidx.core.content.ContextCompat import org.json.JSONArray import org.json.JSONObject +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.BrowserConsoleEntry +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.BrowserNavigationPolicy +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.BrowserNetworkRequestEntry +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.BrowserPageRegistry +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.BrowserSnapshot +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.PendingAsyncJsCall +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.PendingDialog +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.PendingExternalOpenRequest +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebDownloadEvent +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionBrowserHost +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionHistoryStore +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.activateSessionOnMain +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.applyViewportOverride +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.boolParam +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.browserRefResolverScript +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.buildBrowserResponse +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.buildClickCode +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.buildPageRegistry +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.buildSettledBrowserResponse +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.buildWaitForCode +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.captureActionMarkers +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.captureSnapshotModel +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.captureSnapshotText +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.closeSession +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.createSessionTabOnMain +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.currentTabIndex +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.ensureDesktopModeInitialized +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.ensureOverlayPermission +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.ensureSessionAttachedOnMain +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.error +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.evaluateJavascriptAsync +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.evaluatePageFunction +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.extractAsyncJsValue +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.fillFormFields +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.formatBrowserFileLink +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.getSession +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.handleUserscriptDownloadOnMain +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.initializeBrowserDownloadSupport +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.intParam +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.latestBrowserDownloadEventAfter +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.latestSnapshot +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.locatorExpressionForRef +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.navigateSessionOnMain +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.notifySessionStateChanged +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.ok +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.openUserscriptSheetOnMain +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.openUserscriptTabOnMain +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.orderedSessionIds +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.pageError +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.param +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.parseFormFields +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.parseHeaders +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.parseStringArrayParam +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.pressKeyOnPage +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.quoteJsCode +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.refreshNavigationStateAsync +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.refreshSessionUiOnMain +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.renderAllConsoleMessages +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.renderJsArrayCode +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.renderManagedDownloads +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.renderModalState +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.renderNetworkRequestLog +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.renderOpenTabs +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.renderPageState +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.requireSnapshotNode +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.resolveElementRect +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.resolvePendingDialogOnMain +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.resolvePreferredSessionId +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.runPlaywrightLikeCode +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.selectOptionsByRef +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.sessionById +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.sessionIdAtIndex +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.settleBrowserAction +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.takeScreenshot +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.typeIntoElementByRef +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.waitForDocumentReady +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.waitForTextState +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.writeBrowserTextOutput class StandardBrowserSessionTools(internal val context: Context) : ToolExecutor { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardHttpTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardHttpTools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardHttpTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardHttpTools.kt index d07f88e73e..f575a87f7e 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardHttpTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardHttpTools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.web import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWebVisitTool.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardWebVisitTool.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWebVisitTool.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardWebVisitTool.kt index 74bb0ddf71..cdcdc90720 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWebVisitTool.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardWebVisitTool.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.web import android.content.Context import android.graphics.Color as AndroidColor @@ -67,7 +67,7 @@ import androidx.savedstate.SavedStateRegistryOwner import androidx.savedstate.setViewTreeSavedStateRegistryOwner import com.ai.assistance.operit.R import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutor +import com.ai.assistance.operit.core.tools.runtime.ToolExecutor import com.ai.assistance.operit.core.tools.VisitWebResultData import com.ai.assistance.operit.data.preferences.DisplayPreferencesManager import com.ai.assistance.operit.data.model.AITool diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserDownloadSupport.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserDownloadSupport.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserDownloadSupport.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserDownloadSupport.kt index 869c159637..db3f45711c 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserDownloadSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserDownloadSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -10,7 +10,7 @@ import android.os.Environment import android.webkit.MimeTypeMap import androidx.core.content.FileProvider import com.ai.assistance.operit.core.application.ActivityLifecycleManager -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardBrowserSessionTools +import com.ai.assistance.operit.core.tools.builtin.web.StandardBrowserSessionTools import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.util.network.HttpMultiPartDownloader import java.io.File diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserNavigationPolicy.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserNavigationPolicy.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserNavigationPolicy.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserNavigationPolicy.kt index e15df71a2c..4c5e2499fd 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserNavigationPolicy.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserNavigationPolicy.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser /** 自动开窗按文档限流;外部请求的抑制跨重定向保留,用户主动操作仍可重试。 */ internal class BrowserNavigationPolicy { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserPageExecutionSupport.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserPageExecutionSupport.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserPageExecutionSupport.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserPageExecutionSupport.kt index 8274eee0f2..9e73576753 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserPageExecutionSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserPageExecutionSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -20,7 +20,7 @@ import android.webkit.URLUtil import android.webkit.WebView import com.ai.assistance.operit.R import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardBrowserSessionTools +import com.ai.assistance.operit.core.tools.builtin.web.StandardBrowserSessionTools import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.util.logging.AppLogger diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserToolSupport.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserToolSupport.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserToolSupport.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserToolSupport.kt index 122b01882b..08f703a83a 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserToolSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserToolSupport.kt @@ -1,10 +1,10 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser import android.webkit.JsPromptResult import android.webkit.JsResult import android.webkit.WebResourceRequest import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardBrowserSessionTools +import com.ai.assistance.operit.core.tools.builtin.web.StandardBrowserSessionTools import java.util.Locale import java.util.concurrent.CountDownLatch import org.json.JSONArray @@ -193,7 +193,7 @@ internal fun StandardBrowserSessionTools.recordNetworkRequest( val headers = request.requestHeaders?.mapKeys { it.key ?: "" } ?: emptyMap() val acceptHeader = headers.entries.firstOrNull { it.key.equals("Accept", ignoreCase = true) }?.value val entry = - com.ai.assistance.operit.core.tools.defaultTool.websession.browser.BrowserNetworkRequestEntry( + com.ai.assistance.operit.core.tools.builtin.web.session.browser.BrowserNetworkRequestEntry( method = request.method.orEmpty().ifBlank { "GET" }, url = url, isMainFrame = request.isForMainFrame, diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserWebViewSupport.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserWebViewSupport.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserWebViewSupport.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserWebViewSupport.kt index 063b3090ce..4bec95d159 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserWebViewSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserWebViewSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -31,8 +31,8 @@ import androidx.webkit.WebSettingsCompat import androidx.webkit.WebViewFeature import com.ai.assistance.operit.R import com.ai.assistance.operit.core.application.ActivityLifecycleManager -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardBrowserSessionTools -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptInstallSourceType +import com.ai.assistance.operit.core.tools.builtin.web.StandardBrowserSessionTools +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptInstallSourceType import com.ai.assistance.operit.util.logging.AppLogger import java.util.LinkedHashSet import java.util.Locale diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionBrowserHost.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionBrowserHost.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionBrowserHost.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionBrowserHost.kt index 12c97a6282..c5e3b3cc25 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionBrowserHost.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionBrowserHost.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -38,7 +38,7 @@ import androidx.savedstate.SavedStateRegistryController import androidx.savedstate.SavedStateRegistryOwner import androidx.savedstate.setViewTreeSavedStateRegistryOwner import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.ui.WebSessionUserscriptUiStateStore +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.ui.WebSessionUserscriptUiStateStore import com.ai.assistance.operit.ui.features.automation.websession.browser.WebSessionBrowserScreen import com.ai.assistance.operit.ui.features.automation.websession.browser.WebSessionFloatingTheme import com.ai.assistance.operit.ui.features.automation.websession.browser.WebSessionMinimizedIndicator diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionBrowserHostState.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionBrowserHostState.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionBrowserHostState.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionBrowserHostState.kt index 0ce2e9ae88..05fcfb6047 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionBrowserHostState.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionBrowserHostState.kt @@ -1,7 +1,7 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser import androidx.compose.runtime.Immutable -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptPageMenuCommand +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptPageMenuCommand import kotlinx.serialization.Serializable internal enum class WebSessionBrowserSheetRoute { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionHistoryStore.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionHistoryStore.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionHistoryStore.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionHistoryStore.kt index 1597351317..79fde8654d 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionHistoryStore.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionHistoryStore.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser import android.content.Context import android.net.Uri diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionPermissionRequestActivity.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionPermissionRequestActivity.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionPermissionRequestActivity.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionPermissionRequestActivity.kt index c1308c13f0..483876924b 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionPermissionRequestActivity.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionPermissionRequestActivity.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser import android.content.Context import android.content.Intent diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionWebViewHost.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionWebViewHost.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionWebViewHost.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionWebViewHost.kt index a5531f81b0..ecce49dedc 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionWebViewHost.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionWebViewHost.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser import android.view.Gravity import android.view.View diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptCapabilityRegistry.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptCapabilityRegistry.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptCapabilityRegistry.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptCapabilityRegistry.kt index 655dcae7e4..bebc0abffa 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptCapabilityRegistry.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptCapabilityRegistry.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript import androidx.webkit.WebViewFeature diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptMatcher.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptMatcher.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptMatcher.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptMatcher.kt index fc442881be..54c6659359 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptMatcher.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptMatcher.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript import android.net.Uri import java.util.Locale diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptMetadataParser.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptMetadataParser.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptMetadataParser.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptMetadataParser.kt index 2b4ef86a3b..79c353577b 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptMetadataParser.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptMetadataParser.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript internal object UserscriptMetadataParser { private val metadataBlockRegex = diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptModels.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptModels.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptModels.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptModels.kt index fdb8db6c50..b2fda1d2fb 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptModels.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptModels.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript import kotlinx.serialization.Serializable diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/install/UserscriptImportCoordinator.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/install/UserscriptImportCoordinator.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/install/UserscriptImportCoordinator.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/install/UserscriptImportCoordinator.kt index 7a673471a6..2c9eed8b40 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/install/UserscriptImportCoordinator.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/install/UserscriptImportCoordinator.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.install +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.install import android.content.Context import android.content.Intent diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/install/UserscriptImportPickerActivity.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/install/UserscriptImportPickerActivity.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/install/UserscriptImportPickerActivity.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/install/UserscriptImportPickerActivity.kt index 7172e9eb53..7199befe5e 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/install/UserscriptImportPickerActivity.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/install/UserscriptImportPickerActivity.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.install +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.install import android.content.Intent import android.database.Cursor diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptBootstrapScript.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptBootstrapScript.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptBootstrapScript.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptBootstrapScript.kt index 88aee41e72..03564cbf3d 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptBootstrapScript.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptBootstrapScript.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime internal object UserscriptBootstrapScript { const val BRIDGE_NAME = "OperitUserscriptBridge" diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptCookieService.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptCookieService.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptCookieService.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptCookieService.kt index 3f73d1103e..af4060108b 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptCookieService.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptCookieService.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime import android.webkit.CookieManager import java.net.HttpCookie diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptStorageNotifier.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptStorageNotifier.kt similarity index 88% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptStorageNotifier.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptStorageNotifier.kt index f5691d4c06..4b82855a52 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptStorageNotifier.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptStorageNotifier.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime import org.json.JSONObject diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptTabStateStore.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptTabStateStore.kt similarity index 91% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptTabStateStore.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptTabStateStore.kt index 57bd81a114..1aacefd0e0 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptTabStateStore.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptTabStateStore.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime import java.util.concurrent.ConcurrentHashMap diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptWebRequestEngine.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptWebRequestEngine.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptWebRequestEngine.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptWebRequestEngine.kt index f7c6af1706..3538e21c8a 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptWebRequestEngine.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptWebRequestEngine.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime import java.util.Locale import java.util.UUID diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/WebSessionUserscriptManager.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/WebSessionUserscriptManager.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/WebSessionUserscriptManager.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/WebSessionUserscriptManager.kt index bcb5557e2f..0dee751499 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/WebSessionUserscriptManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/WebSessionUserscriptManager.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime import android.Manifest import android.app.NotificationChannel @@ -22,19 +22,19 @@ import androidx.webkit.WebMessageCompat import androidx.webkit.WebViewCompat import androidx.webkit.WebViewFeature import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.ParsedUserscriptMetadata -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptCapabilityRegistry -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptInstallPreview -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptInstallSourceType -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptListItem -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptMatcher -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptPageMenuCommand -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptPageRuntimeState -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptPageRuntimeStatus -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptSupportState -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.install.UserscriptImportCoordinator -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.storage.UserscriptRepository -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.ui.WebSessionUserscriptUiStateStore +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.ParsedUserscriptMetadata +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptCapabilityRegistry +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptInstallPreview +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptInstallSourceType +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptListItem +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptMatcher +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptPageMenuCommand +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptPageRuntimeState +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptPageRuntimeStatus +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptSupportState +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.install.UserscriptImportCoordinator +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.storage.UserscriptRepository +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.ui.WebSessionUserscriptUiStateStore import com.ai.assistance.operit.util.logging.AppLogger import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptEntities.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptEntities.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptEntities.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptEntities.kt index 97c2ac59bb..789e9c0e03 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptEntities.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptEntities.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.storage +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.storage import kotlinx.serialization.Serializable diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptJsonStore.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptJsonStore.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptJsonStore.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptJsonStore.kt index 6c80a7ff20..9daa1c530f 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptJsonStore.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptJsonStore.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.storage +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.storage import android.content.Context import com.ai.assistance.operit.util.files.OperitPaths diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptRepository.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptRepository.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptRepository.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptRepository.kt index 497f808b8f..206216451b 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptRepository.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptRepository.kt @@ -1,22 +1,22 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.storage +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.storage import android.content.Context import android.util.Base64 import android.webkit.MimeTypeMap -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.ParsedUserscriptMetadata -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptCapabilityRegistry -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptBootstrapPayload -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptExecutionPayload -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptInstallPreview -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptInstallSourceType -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptListItem -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptLogItem -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptMatcher -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptMetadataParser -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptRequireEntry -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptResourceEntry -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptResourcePayload -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptRunAt +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.ParsedUserscriptMetadata +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptCapabilityRegistry +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptBootstrapPayload +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptExecutionPayload +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptInstallPreview +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptInstallSourceType +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptListItem +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptLogItem +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptMatcher +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptMetadataParser +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptRequireEntry +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptResourceEntry +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptResourcePayload +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptRunAt import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.util.files.OperitPaths import java.io.File diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/ui/WebSessionUserscriptUiStateStore.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/ui/WebSessionUserscriptUiStateStore.kt similarity index 73% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/ui/WebSessionUserscriptUiStateStore.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/ui/WebSessionUserscriptUiStateStore.kt index b9a43c28c2..4511076bd5 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/ui/WebSessionUserscriptUiStateStore.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/ui/WebSessionUserscriptUiStateStore.kt @@ -1,10 +1,10 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.ui +package com.ai.assistance.operit.core.tools.builtin.web.session.userscript.ui -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptInstallPreview -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptListItem -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptLogItem -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptPageRuntimeStatus -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptSupportState +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptInstallPreview +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptListItem +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptLogItem +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptPageRuntimeStatus +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptSupportState import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWorkflowTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/workflow/StandardWorkflowTools.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWorkflowTools.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/builtin/workflow/StandardWorkflowTools.kt index 0dfeee29ae..dc9d803eed 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWorkflowTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/builtin/workflow/StandardWorkflowTools.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.workflow import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/climode/CliToolModeSupport.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/climode/CliToolModeSupport.kt index cf19e26f74..c74247bf28 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/climode/CliToolModeSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/climode/CliToolModeSupport.kt @@ -5,7 +5,7 @@ import com.ai.assistance.operit.core.config.SystemToolPrompts import com.ai.assistance.operit.core.tools.PackageTool import com.ai.assistance.operit.core.tools.PackageToolParameter import com.ai.assistance.operit.core.tools.ToolPackage -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.mcp.MCPLocalServer import com.ai.assistance.operit.data.model.ApiProviderType import com.ai.assistance.operit.data.model.SystemToolPromptCategory diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/ComposeDslActionRetention.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/ComposeDslActionRetention.kt index 9ae7b82aa3..3dc0ba5606 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/ComposeDslActionRetention.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/ComposeDslActionRetention.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.core.tools.javascript -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslNode -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslRenderResult +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslNode +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslRenderResult import java.util.ArrayDeque internal fun collectComposeDslActionIds(result: ToolPkgComposeDslRenderResult): Set { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsEngine.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsEngine.kt index bcf471aaed..15e3d6e49b 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsEngine.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsEngine.kt @@ -11,13 +11,13 @@ import androidx.core.content.ContextCompat import com.ai.assistance.operit.core.application.ActivityLifecycleManager import com.ai.assistance.operit.core.chat.logMessageTiming import com.ai.assistance.operit.core.chat.messageTimingNow -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_MESSAGE_PROCESSING -import com.ai.assistance.operit.core.tools.packTool.ToolPkgApiCompatibility -import com.ai.assistance.operit.core.tools.packTool.ToolPkgApiVersion -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslRenderResult -import com.ai.assistance.operit.core.tools.packTool.ToolPkgRuntimeMonitor +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_MESSAGE_PROCESSING +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgApiCompatibility +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgApiVersion +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslRenderResult +import com.ai.assistance.operit.core.tools.packTool.runtime.ToolPkgRuntimeMonitor import com.ai.assistance.operit.ui.main.navigation.AppRouteDiscoveryGateway import com.ai.assistance.operit.ui.main.navigation.AppRouterGateway import com.ai.assistance.operit.ui.main.navigation.RouteEntrySource diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsNativeInterfaceDelegates.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsNativeInterfaceDelegates.kt index 914ccdce21..ee26f5acb7 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsNativeInterfaceDelegates.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsNativeInterfaceDelegates.kt @@ -10,13 +10,13 @@ import android.text.StaticLayout import android.text.TextPaint import android.text.TextUtils import android.util.Base64 -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.BinaryResultData import com.ai.assistance.operit.core.tools.BooleanResultData import com.ai.assistance.operit.core.tools.IntResultData import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.core.tools.ToolResultData -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolManager.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolManager.kt index 4289ddf355..572e9d4eeb 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolManager.kt @@ -3,7 +3,7 @@ package com.ai.assistance.operit.core.tools.javascript import android.content.Context import com.ai.assistance.operit.core.tools.ScriptExecutionTraceData import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.util.logging.AppLogger diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolPkgRegistration.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolPkgRegistration.kt index 0a4bef5661..1fa84abed9 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolPkgRegistration.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolPkgRegistration.kt @@ -1,9 +1,9 @@ package com.ai.assistance.operit.core.tools.javascript -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_REGISTRATION_CHAT_MESSAGE_MENU_ITEM -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_REGISTRATION_CHAT_RUNTIME_HOOK -import com.ai.assistance.operit.core.tools.packTool.ToolPkgMarketOrigin -import com.ai.assistance.operit.core.tools.packTool.ToolPkgMarketOriginCodec +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_MESSAGE_MENU_ITEM +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_RUNTIME_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOrigin +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOriginCodec import org.json.JSONObject import org.json.JSONTokener diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/mcp/MCPToolExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/mcp/MCPToolExecutor.kt index 6e333a8382..8c184abbd9 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/mcp/MCPToolExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/mcp/MCPToolExecutor.kt @@ -3,8 +3,8 @@ package com.ai.assistance.operit.core.tools.mcp import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutionLimits -import com.ai.assistance.operit.core.tools.ToolExecutor +import com.ai.assistance.operit.core.tools.runtime.ToolExecutionLimits +import com.ai.assistance.operit.core.tools.runtime.ToolExecutor import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.data.model.ToolValidationResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageDebugRefreshReceiver.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageDebugRefreshReceiver.kt index 5aa8805b88..89b03e0c43 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageDebugRefreshReceiver.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageDebugRefreshReceiver.kt @@ -3,11 +3,12 @@ package com.ai.assistance.operit.core.tools.packTool import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.util.logging.AppLogger import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager class PackageDebugRefreshReceiver : BroadcastReceiver() { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgDebugInstallReceiver.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgDebugInstallReceiver.kt index be7f7f0b13..c883957b2e 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgDebugInstallReceiver.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgDebugInstallReceiver.kt @@ -3,11 +3,12 @@ package com.ai.assistance.operit.core.tools.packTool import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.util.logging.AppLogger import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager class ToolPkgDebugInstallReceiver : BroadcastReceiver() { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageFileImportSupport.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageFileImportSupport.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageFileImportSupport.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageFileImportSupport.kt index fc440ed9ec..84f15045a1 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageFileImportSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageFileImportSupport.kt @@ -1,10 +1,11 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.install import android.content.Context import android.net.Uri import android.provider.OpenableColumns import com.ai.assistance.operit.util.logging.AppLogger import java.io.File +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager /** 从分享或文件选择器导入外部包时的文件名判断与拷贝。 */ object PackageFileImportSupport { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageSourceDeletion.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageSourceDeletion.kt similarity index 90% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageSourceDeletion.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageSourceDeletion.kt index b1e11d80ad..d711137c71 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageSourceDeletion.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageSourceDeletion.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.install import java.io.File diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageTemplateFactory.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageTemplateFactory.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageTemplateFactory.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageTemplateFactory.kt index b1b2e8e0b5..85e472d31e 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageTemplateFactory.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageTemplateFactory.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.install import java.io.File import java.util.zip.ZipEntry diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgLoadOrder.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/loader/ToolPkgLoadOrder.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgLoadOrder.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/loader/ToolPkgLoadOrder.kt index f25baf0941..23764fd08a 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgLoadOrder.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/loader/ToolPkgLoadOrder.kt @@ -1,6 +1,9 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.loader import com.ai.assistance.operit.core.tools.ToolPackage +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgManifestRequirement +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgSubpackageRuntime internal data class ToolPkgLoadOrderResult( val orderedContainers: List, diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgLoader.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/loader/ToolPkgLoader.kt similarity index 89% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgLoader.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/loader/ToolPkgLoader.kt index 8b1ddfcdc1..f9476608f0 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgLoader.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/loader/ToolPkgLoader.kt @@ -1,10 +1,16 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.loader import android.content.Context import com.ai.assistance.operit.core.tools.ToolPackage import com.ai.assistance.operit.core.tools.javascript.JsEngine import java.io.File import java.util.zip.ZipFile +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgArchiveParser +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgLoadResult +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgMainRegistrationParseResult +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgMainRegistrationScriptParser +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgManifestPreview +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgSourceType internal object ToolPkgLoader { fun loadToolPkgFromExternalFile( diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/BuiltInPackageDefaults.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/BuiltInPackageDefaults.kt similarity index 85% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/BuiltInPackageDefaults.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/BuiltInPackageDefaults.kt index 9401211ee7..37f5459271 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/BuiltInPackageDefaults.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/BuiltInPackageDefaults.kt @@ -1,6 +1,7 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.metadata import com.ai.assistance.operit.core.tools.ToolPackage +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgLoadResult /** 个人发行版的首次默认值;已保存的启停状态仍由包管理器持有。 */ internal object BuiltInPackageDefaults { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiVersion.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiVersion.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiVersion.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiVersion.kt index e595f07e96..9105937ac0 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiVersion.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiVersion.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.metadata import com.ai.assistance.operit.BuildConfig diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgCommonPluginConstants.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgCommonPluginConstants.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgCommonPluginConstants.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgCommonPluginConstants.kt index 96081f5312..05c5f24d87 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgCommonPluginConstants.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgCommonPluginConstants.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.metadata internal const val TOOLPKG_RUNTIME_COMPOSE_DSL = "compose_dsl" diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManifestRequirement.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgManifestRequirement.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManifestRequirement.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgManifestRequirement.kt index d9be8a8dbc..8054e01238 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManifestRequirement.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgManifestRequirement.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.metadata import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMarketOrigin.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgMarketOrigin.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMarketOrigin.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgMarketOrigin.kt index 11714c1c82..eb6aeb2de6 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMarketOrigin.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgMarketOrigin.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.metadata import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgTemplateModels.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgTemplateModels.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgTemplateModels.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgTemplateModels.kt index ff780d8f33..0a5b0bdc46 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgTemplateModels.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgTemplateModels.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.metadata import com.ai.assistance.operit.core.tools.LocalizedText import kotlinx.serialization.SerialName diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgArtifactMinifier.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgArtifactMinifier.kt index 9cbf15264c..5724182885 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgArtifactMinifier.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgArtifactMinifier.kt @@ -1,9 +1,9 @@ package com.ai.assistance.operit.core.tools.packTool.minify import android.content.Context -import com.ai.assistance.operit.core.tools.packTool.ToolPkgArchiveParser -import com.ai.assistance.operit.core.tools.packTool.ToolPkgMarketOrigin -import com.ai.assistance.operit.core.tools.packTool.ToolPkgMarketOriginCodec +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgArchiveParser +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOrigin +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOriginCodec import com.ai.assistance.operit.ui.features.extensions.packages.market.PUBLISH_LOGO_MAX_BYTES import com.ai.assistance.operit.ui.features.extensions.packages.market.ToolPkgLogoAsset import java.io.ByteArrayOutputStream diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMainRegistrationScriptParser.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgMainRegistrationScriptParser.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMainRegistrationScriptParser.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgMainRegistrationScriptParser.kt index 37c1cb765e..c842002f6f 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMainRegistrationScriptParser.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgMainRegistrationScriptParser.kt @@ -1,10 +1,31 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.parser import com.ai.assistance.operit.core.tools.LocalizedText import com.ai.assistance.operit.core.tools.javascript.JsEngine import com.ai.assistance.operit.util.logging.AppLogger import org.json.JSONArray import org.json.JSONObject +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_AI_PROVIDER +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_INPUT_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_MESSAGE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_MESSAGE_MENU_ITEM +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_RUNTIME_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_VIEW_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_INPUT_MENU_TOGGLE_PLUGIN +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_MESSAGE_PROCESSING_PLUGIN +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_ESTIMATE_FINALIZE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_ESTIMATE_HISTORY_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_FINALIZE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_HISTORY_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_INPUT_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_SUMMARY_GENERATE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_SYSTEM_PROMPT_COMPOSE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_TOOL_LIFECYCLE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_TOOL_PROMPT_COMPOSE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_XML_RENDER_PLUGIN +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_RUNTIME_COMPOSE_DSL +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOriginCodec +import com.ai.assistance.operit.core.tools.packTool.metadata.buildToolPkgRouteId internal object ToolPkgMainRegistrationScriptParser { private const val TAG = "ToolPkgMainRegParser" diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgParser.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgParser.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt index 02063e7312..fd31dfa42c 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgParser.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.parser import android.content.Context import android.provider.DocumentsContract @@ -16,6 +16,18 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonPrimitive import org.hjson.JsonValue +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_NAV_SURFACE_MAIN_SIDEBAR_PLUGINS +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_NAV_SURFACE_PACKAGE_DETAILS +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_RUNTIME_COMPOSE_DSL +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgApiCompatibility +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgManifestRequirement +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgManifestWorkflowTemplate +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgManifestWorkspaceTemplate +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOrigin +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgPackageVersion +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgWorkflowTemplateRuntime +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgWorkspaceTemplateRuntime +import com.ai.assistance.operit.core.tools.packTool.metadata.buildToolPkgRouteId private val TOOLPKG_DIRECTORY_RESOURCE_MIME_TYPES = setOf( diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageActivationResult.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageActivationResult.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageActivationResult.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageActivationResult.kt index ba3b3fab49..ff717f1ed7 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageActivationResult.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageActivationResult.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.runtime import com.ai.assistance.operit.core.tools.PackageActivationErrorCode import com.ai.assistance.operit.core.tools.PackageActivationErrorData diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManager.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageManager.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManager.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageManager.kt index 5df5c519d5..b4c1e9710a 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageManager.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.runtime import android.content.Context import com.ai.assistance.operit.core.tools.PackageActivationErrorCode @@ -10,7 +10,7 @@ import com.ai.assistance.operit.data.storage.LocalModelUsageHandle import com.ai.assistance.operit.core.chat.logMessageTiming import com.ai.assistance.operit.core.chat.messageTimingNow import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.core.tools.PackageToolExecutor import com.ai.assistance.operit.core.tools.PackageTool @@ -27,7 +27,7 @@ import com.ai.assistance.operit.core.tools.skill.SkillManager import com.ai.assistance.operit.data.security.PluginDenylistRepository import com.ai.assistance.operit.data.preferences.SkillVisibilityPreferences import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.data.preferences.DisplayPreferencesManager import com.ai.assistance.operit.data.preferences.ApiPreferences @@ -56,6 +56,22 @@ import kotlinx.coroutines.launch import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.hjson.JsonValue +import com.ai.assistance.operit.core.tools.packTool.install.deleteInstalledPackageSources +import com.ai.assistance.operit.core.tools.packTool.loader.ToolPkgLoadOrderResolver +import com.ai.assistance.operit.core.tools.packTool.loader.ToolPkgLoader +import com.ai.assistance.operit.core.tools.packTool.metadata.BuiltInPackageDefaults +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_RUNTIME_COMPOSE_DSL +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgApiCompatibility +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgManifestRequirement +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOrigin +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOriginCodec +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgArchiveParser +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgLoadResult +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgManifestPreview +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgResourceRuntime +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgSourceType +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgSubpackageRuntime /** * Manages the loading, registration, and handling of tool packages diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManagerToolPkgFacade.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageManagerToolPkgFacade.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManagerToolPkgFacade.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageManagerToolPkgFacade.kt index 706d4a3a8d..0904e88a00 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManagerToolPkgFacade.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageManagerToolPkgFacade.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.runtime import android.content.Context import com.ai.assistance.operit.core.chat.logMessageTiming @@ -13,6 +13,13 @@ import java.util.UUID import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_MESSAGE_PROCESSING +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_NAVIGATION_ENTRY_ACTION +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_NAV_SURFACE_PACKAGE_DETAILS +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_RUNTIME_COMPOSE_DSL +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgArchiveParser +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgSourceType internal class PackageManagerToolPkgFacade( private val packageManager: PackageManager diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgHookModels.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgHookModels.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgHookModels.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgHookModels.kt index f7c63d64d6..5ff9b68fe2 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgHookModels.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgHookModels.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.runtime /** * Mirror of ToolPkg xml_render hook result shape used by JS toolpkg. diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManager.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgManager.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManager.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgManager.kt index 3fc53279e8..29365c68dd 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgManager.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.runtime import android.content.Context import com.ai.assistance.operit.core.tools.ToolPackage @@ -8,6 +8,10 @@ import com.ai.assistance.operit.util.logging.AppLogger import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.atomic.AtomicBoolean +import com.ai.assistance.operit.core.tools.packTool.loader.ToolPkgLoadOrderResolver +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgLoadResult +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgSubpackageRuntime /** * 一个 ToolPkg 容器当前活跃执行引擎的运行信息。 diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgRuntimeMonitor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgRuntimeMonitor.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgRuntimeMonitor.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgRuntimeMonitor.kt index 76f6118e17..2ef9a43251 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgRuntimeMonitor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgRuntimeMonitor.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.runtime import android.os.SystemClock import java.util.ArrayDeque diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgComposeDslParser.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/uidsl/ToolPkgComposeDslParser.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgComposeDslParser.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/packTool/uidsl/ToolPkgComposeDslParser.kt index 1527a90ca5..5ca9a6a062 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgComposeDslParser.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/uidsl/ToolPkgComposeDslParser.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.uidsl import org.json.JSONArray import org.json.JSONObject diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidPermissionLevel.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/AndroidPermissionLevel.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidPermissionLevel.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/permissions/AndroidPermissionLevel.kt index f7038ac82b..62c9d9d6df 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidPermissionLevel.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/AndroidPermissionLevel.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.permissions import java.util.Locale diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilities.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilities.kt index 17d4d629a5..ef2220e4d8 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilities.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilities.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.core.tools.permissions -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel -import com.ai.assistance.operit.core.tools.system.ShellIdentity +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.system.shell.ShellIdentity /** 执行后端与用户模式分开,新增授权来源不需要新增用户模式。 */ enum class PermissionBackend { STANDARD, ACCESSIBILITY, SHIZUKU, ROOT } diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilityResolver.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilityResolver.kt index b2e1d41d5a..84564ffef5 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilityResolver.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilityResolver.kt @@ -1,8 +1,8 @@ package com.ai.assistance.operit.core.tools.permissions import android.content.Context -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel -import com.ai.assistance.operit.core.tools.system.ShizukuAuthorizer +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.authorization.ShizukuAuthorizer import com.ai.assistance.operit.core.tools.system.shell.ShellExecutorFactory import com.ai.assistance.operit.data.preferences.androidPermissionPreferences import com.ai.assistance.operit.data.repository.UIHierarchyManager diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitySession.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitySession.kt index c30438146b..90dbf55ee4 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitySession.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitySession.kt @@ -1,6 +1,6 @@ package com.ai.assistance.operit.core.tools.permissions -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import kotlinx.coroutines.sync.Mutex /** 保存一次工具执行会话内的授权能力快照,避免每个工具重复探测系统授权。 */ diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/AccessibilityProviderInstaller.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/AccessibilityProviderInstaller.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/AccessibilityProviderInstaller.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/AccessibilityProviderInstaller.kt index 57cdaadcf1..721092cf63 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/AccessibilityProviderInstaller.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/AccessibilityProviderInstaller.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.permissions.authorization import android.content.Context import android.content.pm.PackageInfo diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/RootAuthorizer.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/RootAuthorizer.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/RootAuthorizer.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/RootAuthorizer.kt index beb6aeb1be..76d4652b8c 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/RootAuthorizer.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/RootAuthorizer.kt @@ -1,10 +1,10 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.permissions.authorization import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.R import com.ai.assistance.operit.core.tools.system.shell.RootShellExecutor -import com.ai.assistance.operit.core.tools.system.ShellIdentity +import com.ai.assistance.operit.core.tools.system.shell.ShellIdentity import com.ai.assistance.operit.data.preferences.RootCommandExecutionMode import com.ai.assistance.operit.data.preferences.androidPermissionPreferences import com.topjohnwu.superuser.Shell diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/ShizukuAuthorizer.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/ShizukuAuthorizer.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/ShizukuAuthorizer.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/ShizukuAuthorizer.kt index 32f0b3af95..44e45a352f 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/ShizukuAuthorizer.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/ShizukuAuthorizer.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.permissions.authorization import android.content.Context import android.content.pm.PackageManager diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/ShizukuInstaller.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/ShizukuInstaller.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/ShizukuInstaller.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/ShizukuInstaller.kt index d795a7f4be..ab52501bf9 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/ShizukuInstaller.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/ShizukuInstaller.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.permissions.authorization import android.content.Context import android.content.Intent diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/AIToolHandler.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/runtime/AIToolHandler.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/AIToolHandler.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/runtime/AIToolHandler.kt index cdeee5cf6e..f5b4b471df 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/AIToolHandler.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/runtime/AIToolHandler.kt @@ -1,9 +1,9 @@ -package com.ai.assistance.operit.core.tools +package com.ai.assistance.operit.core.tools.runtime import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.core.tools.mcp.MCPManager -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilitySession import com.ai.assistance.operit.data.model.AITool @@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.runBlocking +import com.ai.assistance.operit.core.tools.StringResultData /** * Handles the extraction and execution of AI tools from responses Supports real-time streaming diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/AIToolHook.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/runtime/AIToolHook.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/core/tools/AIToolHook.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/runtime/AIToolHook.kt index ef399df51c..b16a8646ce 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/AIToolHook.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/runtime/AIToolHook.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools +package com.ai.assistance.operit.core.tools.runtime import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/ToolExecutionLimits.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolExecutionLimits.kt similarity index 86% rename from app/src/main/java/com/ai/assistance/operit/core/tools/ToolExecutionLimits.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolExecutionLimits.kt index 2fc2512a6c..95a300e25a 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/ToolExecutionLimits.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolExecutionLimits.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools +package com.ai.assistance.operit.core.tools.runtime object ToolExecutionLimits { const val MAX_FILE_READ_BYTES = 32_000 diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/ToolProgressBus.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolProgressBus.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/core/tools/ToolProgressBus.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolProgressBus.kt index 2a8384d0a1..ea9fbe4064 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/ToolProgressBus.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolProgressBus.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools +package com.ai.assistance.operit.core.tools.runtime import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt index 40f88ef94a..c483893265 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools +package com.ai.assistance.operit.core.tools.runtime import android.content.Context import com.ai.assistance.operit.R @@ -7,7 +7,7 @@ import com.ai.assistance.operit.core.performance.PerformanceMonitorManager import com.ai.assistance.operit.core.chat.tools.ToolExecutionManager import com.ai.assistance.operit.core.tools.climode.CliToolModeSupport import com.ai.assistance.operit.core.tools.climode.ToolExposureMode -import com.ai.assistance.operit.core.tools.defaultTool.ToolGetter +import com.ai.assistance.operit.core.tools.builtin.ToolGetter import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.data.model.ToolResult @@ -24,6 +24,9 @@ import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking import org.json.JSONArray import org.json.JSONObject +import com.ai.assistance.operit.core.tools.PerformanceMetricsResultData +import com.ai.assistance.operit.core.tools.SleepResultData +import com.ai.assistance.operit.core.tools.StringResultData /** * This file contains all tool registrations centralized for easier maintenance and integration It @@ -36,7 +39,7 @@ import org.json.JSONObject * @param context Application context for tools that need it */ fun registerAllTools(handler: AIToolHandler, context: Context) { - com.ai.assistance.operit.core.tools.defaultTool.a2ui.A2uiTools.register(handler, context) + com.ai.assistance.operit.core.tools.builtin.a2ui.A2uiTools.register(handler, context) // Helper function to wrap UI tool execution with visibility changes diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/AccessibilityActionListener.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/AccessibilityActionListener.kt index c2ebae0a34..1185f5d8ab 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/AccessibilityActionListener.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/AccessibilityActionListener.kt @@ -5,7 +5,7 @@ import android.content.Intent import android.provider.Settings import com.ai.assistance.operit.util.logging.AppLogger import android.view.accessibility.AccessibilityEvent -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.data.repository.UIHierarchyManager import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListener.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListener.kt index ac655ddff6..9e4dee3f71 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListener.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListener.kt @@ -1,6 +1,6 @@ package com.ai.assistance.operit.core.tools.system.action -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel /** 通用UI操作监听接口 定义了不同权限级别UI操作监听的统一接口 */ interface ActionListener { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListenerFactory.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListenerFactory.kt index 992aa1a263..38fe6826d3 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListenerFactory.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionListenerFactory.kt @@ -3,7 +3,7 @@ package com.ai.assistance.operit.core.tools.system.action import android.content.Context import com.ai.assistance.operit.core.tools.permissions.PermissionBackend import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.data.preferences.androidPermissionPreferences /** 监听器实例按后端缓存,授权状态不随实例一起缓存。 */ diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionManager.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionManager.kt index c6a9cb813c..24eff693e9 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ActionManager.kt @@ -3,7 +3,7 @@ package com.ai.assistance.operit.core.tools.system.action import android.content.Context import com.ai.assistance.operit.R import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/RootActionListener.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/RootActionListener.kt index 274dd8d8ba..2af99a38f1 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/RootActionListener.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/RootActionListener.kt @@ -4,7 +4,7 @@ import android.content.Context import com.ai.assistance.operit.R import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.core.tools.permissions.PermissionBackend -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.core.tools.system.shell.ShellExecutorFactory import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ShizukuActionListener.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ShizukuActionListener.kt index 2d9b482e1d..3376fb5749 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ShizukuActionListener.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/ShizukuActionListener.kt @@ -4,8 +4,8 @@ import android.content.Context import com.ai.assistance.operit.R import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.core.tools.permissions.PermissionBackend -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel -import com.ai.assistance.operit.core.tools.system.ShizukuAuthorizer +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.authorization.ShizukuAuthorizer import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/StandardActionListener.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/StandardActionListener.kt index 7f04fa22a0..34e3450a80 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/StandardActionListener.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/action/StandardActionListener.kt @@ -4,7 +4,7 @@ import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.R import android.view.accessibility.AccessibilityEvent -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.util.concurrent.atomic.AtomicBoolean diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/MediaProjectionCaptureManager.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/MediaProjectionCaptureManager.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/MediaProjectionCaptureManager.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/MediaProjectionCaptureManager.kt index 80a61d03a4..4146d89982 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/MediaProjectionCaptureManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/MediaProjectionCaptureManager.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.system.capture import android.content.Context import android.graphics.Bitmap diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/MediaProjectionHolder.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/MediaProjectionHolder.kt similarity index 92% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/MediaProjectionHolder.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/MediaProjectionHolder.kt index 85aadd9a9d..c45f22a55a 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/MediaProjectionHolder.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/MediaProjectionHolder.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.system.capture import android.content.Context import android.media.projection.MediaProjection diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/ScreenCaptureActivity.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/ScreenCaptureActivity.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/ScreenCaptureActivity.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/ScreenCaptureActivity.kt index 4b5a7b51c6..4bc63abcec 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/ScreenCaptureActivity.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/ScreenCaptureActivity.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.system.capture import android.app.Activity import android.content.Context diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/ScreenCaptureService.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/ScreenCaptureService.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/ScreenCaptureService.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/ScreenCaptureService.kt index 90d3cb1d1b..2d198fddf1 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/ScreenCaptureService.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/ScreenCaptureService.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.system.capture import android.app.Notification import android.app.NotificationChannel diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidShellExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/AndroidShellExecutor.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidShellExecutor.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/AndroidShellExecutor.kt index da63e584ba..3a6e828723 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidShellExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/AndroidShellExecutor.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.system.shell import android.content.Context import com.ai.assistance.operit.core.tools.permissions.PermissionBackend @@ -7,6 +7,7 @@ import com.ai.assistance.operit.core.tools.system.shell.ShellExecutor import com.ai.assistance.operit.core.tools.system.shell.ShellExecutorFactory import com.ai.assistance.operit.core.tools.system.shell.ShellProcess import com.ai.assistance.operit.data.preferences.androidPermissionPreferences +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel /** 根据模式和当前授权选择 Shell 后端;命令提交后不自动重放。 */ class AndroidShellExecutor { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/RootShellExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/RootShellExecutor.kt index 100ad2ca73..094ddd993c 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/RootShellExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/RootShellExecutor.kt @@ -3,8 +3,8 @@ package com.ai.assistance.operit.core.tools.system.shell import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel -import com.ai.assistance.operit.core.tools.system.ShellIdentity +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.system.shell.ShellIdentity import com.ai.assistance.operit.data.preferences.AndroidPermissionPreferences import com.ai.assistance.operit.data.preferences.RootCommandExecutionMode import com.ai.assistance.operit.data.preferences.androidPermissionPreferences diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutor.kt index c18b790eb4..aab3d45962 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutor.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.core.tools.system.shell -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel -import com.ai.assistance.operit.core.tools.system.ShellIdentity +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.system.shell.ShellIdentity /** 通用Shell命令执行接口 定义了不同权限级别Shell操作的统一接口 */ interface ShellExecutor { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutorFactory.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutorFactory.kt index cf010b35e9..a6764c90ca 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutorFactory.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShellExecutorFactory.kt @@ -3,7 +3,7 @@ package com.ai.assistance.operit.core.tools.system.shell import android.content.Context import com.ai.assistance.operit.core.tools.permissions.PermissionBackend import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.data.preferences.androidPermissionPreferences /** 实例按后端缓存,模式到后端的选择在每次操作前重新计算。 */ diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShizukuShellExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShizukuShellExecutor.kt index 8b70fdc431..4b9f0309b4 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShizukuShellExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/ShizukuShellExecutor.kt @@ -4,9 +4,9 @@ import android.content.Context import android.os.ParcelFileDescriptor import android.os.RemoteException import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel -import com.ai.assistance.operit.core.tools.system.ShizukuAuthorizer -import com.ai.assistance.operit.core.tools.system.ShellIdentity +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.authorization.ShizukuAuthorizer +import com.ai.assistance.operit.core.tools.system.shell.ShellIdentity import java.io.BufferedReader import java.io.IOException import java.io.InputStream diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/StandardShellExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/StandardShellExecutor.kt index 9c1d745ac3..0e96af7072 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/StandardShellExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/StandardShellExecutor.kt @@ -2,8 +2,8 @@ package com.ai.assistance.operit.core.tools.system.shell import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel -import com.ai.assistance.operit.core.tools.system.ShellIdentity +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.system.shell.ShellIdentity import java.io.BufferedReader import java.io.InputStreamReader import java.util.concurrent.TimeUnit diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shower/OperitShowerShellRunner.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shower/OperitShowerShellRunner.kt index bf459f7fe3..13914bffe9 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/shower/OperitShowerShellRunner.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/shower/OperitShowerShellRunner.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.core.tools.system.shower -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor -import com.ai.assistance.operit.core.tools.system.ShellIdentity as AppShellIdentity +import com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor +import com.ai.assistance.operit.core.tools.system.shell.ShellIdentity as AppShellIdentity import com.ai.assistance.showerclient.ShellCommandResult import com.ai.assistance.showerclient.ShellIdentity import com.ai.assistance.showerclient.ShellRunner diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/OperitTerminalManager.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/terminal/OperitTerminalManager.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/OperitTerminalManager.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/system/terminal/OperitTerminalManager.kt index a60a98ff55..cacddd8b20 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/OperitTerminalManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/terminal/OperitTerminalManager.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.system.terminal import android.content.Context import android.content.pm.PackageManager diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/Terminal.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/terminal/Terminal.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/core/tools/system/Terminal.kt rename to app/src/main/java/com/ai/assistance/operit/core/tools/system/terminal/Terminal.kt index 514d893f8e..2c2f188352 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/Terminal.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/terminal/Terminal.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.system +package com.ai.assistance.operit.core.tools.system.terminal import android.content.Context import android.os.Build diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/system/uiautomator/UiAutomatorDumpGuard.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/system/uiautomator/UiAutomatorDumpGuard.kt index 06996dc8dd..26a74595c9 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/system/uiautomator/UiAutomatorDumpGuard.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/system/uiautomator/UiAutomatorDumpGuard.kt @@ -1,6 +1,6 @@ package com.ai.assistance.operit.core.tools.system.uiautomator -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor +import com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock diff --git a/app/src/main/java/com/ai/assistance/operit/core/workflow/WorkflowExecutor.kt b/app/src/main/java/com/ai/assistance/operit/core/workflow/WorkflowExecutor.kt index 099e5cbe5d..0cebdbc0da 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/workflow/WorkflowExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/workflow/WorkflowExecutor.kt @@ -4,7 +4,7 @@ import android.content.Context import com.ai.assistance.operit.R import com.ai.assistance.operit.core.config.SystemToolPrompts import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ConditionNode import com.ai.assistance.operit.data.model.ConditionOperator diff --git a/app/src/main/java/com/ai/assistance/operit/data/mcp/MCPLocalServer.kt b/app/src/main/java/com/ai/assistance/operit/data/mcp/MCPLocalServer.kt index 1f6e2d9200..fa92b3d0d7 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/mcp/MCPLocalServer.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/mcp/MCPLocalServer.kt @@ -4,7 +4,7 @@ import android.content.Context import android.content.SharedPreferences import com.ai.assistance.operit.R import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.mcp.MCPManager import com.ai.assistance.operit.core.tools.DirectoryListingData import com.ai.assistance.operit.core.tools.FileExistsData diff --git a/app/src/main/java/com/ai/assistance/operit/data/mcp/MCPRepository.kt b/app/src/main/java/com/ai/assistance/operit/data/mcp/MCPRepository.kt index 2328d579cb..724b3ed82e 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/mcp/MCPRepository.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/mcp/MCPRepository.kt @@ -7,7 +7,7 @@ import android.os.Environment import com.ai.assistance.operit.R import com.ai.assistance.operit.api.chat.EnhancedAIService import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.mcp.MCPManager import com.ai.assistance.operit.core.tools.mcp.MCPPackage import com.ai.assistance.operit.core.tools.mcp.McpRuntimeDescriptor diff --git a/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPBridge.kt b/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPBridge.kt index 1a727896ac..75ae440d85 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPBridge.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPBridge.kt @@ -5,8 +5,8 @@ import com.ai.assistance.operit.R import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.util.files.OperitPaths import com.ai.assistance.operit.util.network.PortProcessKiller -import com.ai.assistance.operit.core.tools.system.Terminal -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.system.terminal.Terminal +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import java.io.BufferedReader diff --git a/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPDeployer.kt b/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPDeployer.kt index 7736efcf9f..f086a1ff73 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPDeployer.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPDeployer.kt @@ -4,8 +4,8 @@ import android.content.Context import com.ai.assistance.operit.R import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.data.mcp.MCPLocalServer -import com.ai.assistance.operit.core.tools.system.Terminal -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.system.terminal.Terminal +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.google.gson.JsonParser diff --git a/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPSharedSession.kt b/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPSharedSession.kt index 2e898ab785..374db74eeb 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPSharedSession.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPSharedSession.kt @@ -2,7 +2,7 @@ package com.ai.assistance.operit.data.mcp.plugins import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.system.Terminal +import com.ai.assistance.operit.core.tools.system.terminal.Terminal import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock diff --git a/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPStarter.kt b/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPStarter.kt index 1193a6fdb7..85af0c0131 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPStarter.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/mcp/plugins/MCPStarter.kt @@ -7,7 +7,7 @@ import com.ai.assistance.operit.core.tools.mcp.MCPManager import com.ai.assistance.operit.core.tools.mcp.McpRuntimeDescriptor import com.ai.assistance.operit.data.mcp.MCPLocalServer import com.ai.assistance.operit.data.mcp.MCPRepository -import com.ai.assistance.operit.core.tools.system.Terminal +import com.ai.assistance.operit.core.tools.system.terminal.Terminal import com.ai.assistance.operit.data.mcp.createMcpConfigGson import com.google.gson.JsonParser import kotlinx.coroutines.CancellationException diff --git a/app/src/main/java/com/ai/assistance/operit/data/preferences/AndroidPermissionModeMigration.kt b/app/src/main/java/com/ai/assistance/operit/data/preferences/AndroidPermissionModeMigration.kt index 39889ce6e2..45ee0ace14 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/preferences/AndroidPermissionModeMigration.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/preferences/AndroidPermissionModeMigration.kt @@ -4,7 +4,7 @@ import androidx.datastore.core.DataMigration import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.stringPreferencesKey -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import java.util.Locale /** 只更新旧模式名称,保留 Root 设置以及其他偏好。 */ diff --git a/app/src/main/java/com/ai/assistance/operit/data/preferences/AndroidPermissionPreferences.kt b/app/src/main/java/com/ai/assistance/operit/data/preferences/AndroidPermissionPreferences.kt index 2c84d32dd0..a53e1d7528 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/preferences/AndroidPermissionPreferences.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/preferences/AndroidPermissionPreferences.kt @@ -7,7 +7,7 @@ import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first diff --git a/app/src/main/java/com/ai/assistance/operit/data/preferences/CharacterCardToolAccessResolver.kt b/app/src/main/java/com/ai/assistance/operit/data/preferences/CharacterCardToolAccessResolver.kt index f12764d79a..e210be3de0 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/preferences/CharacterCardToolAccessResolver.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/preferences/CharacterCardToolAccessResolver.kt @@ -2,7 +2,7 @@ package com.ai.assistance.operit.data.preferences import android.content.Context import com.ai.assistance.operit.core.config.SystemToolPrompts -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.CharacterCardToolAccessConfig import com.ai.assistance.operit.data.skill.SkillRepository import kotlinx.coroutines.flow.first diff --git a/app/src/main/java/com/ai/assistance/operit/data/repository/UIHierarchyManager.kt b/app/src/main/java/com/ai/assistance/operit/data/repository/UIHierarchyManager.kt index 84f19b0d1d..5d2b062942 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/repository/UIHierarchyManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/repository/UIHierarchyManager.kt @@ -15,7 +15,7 @@ import android.os.RemoteException import com.ai.assistance.operit.util.logging.AppLogger import androidx.core.content.FileProvider import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.system.AccessibilityProviderInstaller +import com.ai.assistance.operit.core.tools.permissions.authorization.AccessibilityProviderInstaller import com.ai.assistance.operit.provider.IAccessibilityProvider import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow diff --git a/app/src/main/java/com/ai/assistance/operit/data/storage/PackageSkillInventory.kt b/app/src/main/java/com/ai/assistance/operit/data/storage/PackageSkillInventory.kt index ce6ddcd92a..52012eccb7 100644 --- a/app/src/main/java/com/ai/assistance/operit/data/storage/PackageSkillInventory.kt +++ b/app/src/main/java/com/ai/assistance/operit/data/storage/PackageSkillInventory.kt @@ -1,8 +1,8 @@ package com.ai.assistance.operit.data.storage import android.content.Context -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.core.tools.skill.SkillManager import com.ai.assistance.operit.data.mcp.MCPRepository import com.ai.assistance.operit.util.files.OperitPaths diff --git a/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetConfigActivity.kt b/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetConfigActivity.kt index f169e19bd2..f2376fc7c1 100644 --- a/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetConfigActivity.kt +++ b/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetConfigActivity.kt @@ -35,7 +35,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.foundation.layout.WindowInsets import androidx.lifecycle.lifecycleScope import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.ui.theme.OperitTheme import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay diff --git a/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetDslRenderer.kt b/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetDslRenderer.kt index 5d4ef5d0a6..44be4b5ae2 100644 --- a/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetDslRenderer.kt +++ b/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetDslRenderer.kt @@ -23,11 +23,11 @@ import androidx.glance.text.FontWeight import androidx.glance.text.Text import androidx.glance.text.TextStyle import androidx.glance.unit.ColorProvider -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslNode -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslParser -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslRenderResult +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslNode +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslParser +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslRenderResult import com.ai.assistance.operit.ui.common.composedsl.normalizeToken import com.ai.assistance.operit.util.logging.AppLogger diff --git a/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetHost.kt b/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetHost.kt index 48b2873b4a..41a4e75dc4 100644 --- a/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetHost.kt +++ b/app/src/main/java/com/ai/assistance/operit/integrations/appwidget/ToolPkgDesktopWidgetHost.kt @@ -3,8 +3,8 @@ package com.ai.assistance.operit.integrations.appwidget import android.appwidget.AppWidgetManager import android.content.Context import android.content.Intent -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.ui.main.MainActivity import kotlinx.coroutines.runBlocking import androidx.glance.appwidget.updateAll diff --git a/app/src/main/java/com/ai/assistance/operit/integrations/externalchat/ExternalChatRequestExecutor.kt b/app/src/main/java/com/ai/assistance/operit/integrations/externalchat/ExternalChatRequestExecutor.kt index 8af97b087f..e01a84f680 100644 --- a/app/src/main/java/com/ai/assistance/operit/integrations/externalchat/ExternalChatRequestExecutor.kt +++ b/app/src/main/java/com/ai/assistance/operit/integrations/externalchat/ExternalChatRequestExecutor.kt @@ -3,9 +3,9 @@ package com.ai.assistance.operit.integrations.externalchat import android.content.Context import com.ai.assistance.operit.core.tools.ChatListResultData import com.ai.assistance.operit.core.tools.MessageSendResultData -import com.ai.assistance.operit.core.tools.defaultTool.standard.MessageSendStreamSession -import com.ai.assistance.operit.core.tools.defaultTool.standard.MessageSendStreamStartResult -import com.ai.assistance.operit.core.tools.defaultTool.standard.StandardChatManagerTool +import com.ai.assistance.operit.core.tools.builtin.chat.MessageSendStreamSession +import com.ai.assistance.operit.core.tools.builtin.chat.MessageSendStreamStartResult +import com.ai.assistance.operit.core.tools.builtin.chat.StandardChatManagerTool import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.data.model.ToolParameter diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/lifecycle/AppLifecycleHookPluginRegistry.kt b/app/src/main/java/com/ai/assistance/operit/plugins/lifecycle/AppLifecycleHookPluginRegistry.kt index 943b75f5cc..7a3280114e 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/lifecycle/AppLifecycleHookPluginRegistry.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/lifecycle/AppLifecycleHookPluginRegistry.kt @@ -7,18 +7,18 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_ACTIVITY_ON_CREATE -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_ACTIVITY_ON_DESTROY -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_ACTIVITY_ON_PAUSE -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_ACTIVITY_ON_RESUME -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_ACTIVITY_ON_START -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_ACTIVITY_ON_STOP -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_APPLICATION_ON_BACKGROUND -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_APPLICATION_ON_CREATE -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_APPLICATION_ON_FOREGROUND -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_APPLICATION_ON_LOW_MEMORY -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_APPLICATION_ON_TERMINATE -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_APPLICATION_ON_TRIM_MEMORY +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_ACTIVITY_ON_CREATE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_ACTIVITY_ON_DESTROY +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_ACTIVITY_ON_PAUSE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_ACTIVITY_ON_RESUME +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_ACTIVITY_ON_START +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_ACTIVITY_ON_STOP +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_APPLICATION_ON_BACKGROUND +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_APPLICATION_ON_CREATE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_APPLICATION_ON_FOREGROUND +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_APPLICATION_ON_LOW_MEMORY +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_APPLICATION_ON_TERMINATE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_APPLICATION_ON_TRIM_MEMORY enum class AppLifecycleEvent(val wireName: String) { APPLICATION_CREATE(TOOLPKG_EVENT_APPLICATION_ON_CREATE), diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgAiProviderRegistry.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgAiProviderRegistry.kt index 1638787c43..1568770623 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgAiProviderRegistry.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgAiProviderRegistry.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.plugins.toolpkg -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime import java.util.concurrent.atomic.AtomicBoolean internal object ToolPkgAiProviderRegistry { diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatInputHookBridge.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatInputHookBridge.kt index 3a91f93f67..392b794240 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatInputHookBridge.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatInputHookBridge.kt @@ -1,8 +1,8 @@ package com.ai.assistance.operit.plugins.toolpkg -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_CHAT_INPUT -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_CHAT_INPUT +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputEvents import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputHook diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatMessageHookBridge.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatMessageHookBridge.kt index e5b8fb10a5..4eddad97da 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatMessageHookBridge.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatMessageHookBridge.kt @@ -1,8 +1,8 @@ package com.ai.assistance.operit.plugins.toolpkg -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_CHAT_MESSAGE -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_CHAT_MESSAGE +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.util.logging.AppLogger import java.util.concurrent.atomic.AtomicBoolean diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatMessageMenuItemBridge.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatMessageMenuItemBridge.kt index 0c27077234..e4016d42e3 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatMessageMenuItemBridge.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatMessageMenuItemBridge.kt @@ -1,10 +1,10 @@ package com.ai.assistance.operit.plugins.toolpkg import android.content.Context -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_CHAT_MESSAGE_MENU_ITEM -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_RUNTIME_COMPOSE_DSL -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_CHAT_MESSAGE_MENU_ITEM +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_RUNTIME_COMPOSE_DSL +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.plugins.chatmessage.ChatMessageMenuDialogRequest import com.ai.assistance.operit.plugins.chatmessage.ChatMessageMenuItemClickResult diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatRuntimeHookBridge.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatRuntimeHookBridge.kt index 43e68e0922..3a32d3d749 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatRuntimeHookBridge.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatRuntimeHookBridge.kt @@ -4,9 +4,9 @@ import com.ai.assistance.operit.core.chat.hooks.ChatRuntimeHook import com.ai.assistance.operit.core.chat.hooks.ChatRuntimeHookContext import com.ai.assistance.operit.core.chat.hooks.ChatRuntimeHookEvent import com.ai.assistance.operit.core.chat.hooks.ChatRuntimeHookRegistry -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_CHAT_RUNTIME -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_CHAT_RUNTIME +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime import com.ai.assistance.operit.data.model.InputProcessingState import com.ai.assistance.operit.util.logging.AppLogger import java.util.concurrent.atomic.AtomicBoolean diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatViewHookBridge.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatViewHookBridge.kt index f9a3928960..8bfee67891 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatViewHookBridge.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatViewHookBridge.kt @@ -1,8 +1,8 @@ package com.ai.assistance.operit.plugins.toolpkg -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_CHAT_VIEW -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_CHAT_VIEW +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime import com.ai.assistance.operit.plugins.chatview.ChatViewEvent import com.ai.assistance.operit.plugins.chatview.ChatViewHookParams import com.ai.assistance.operit.plugins.chatview.ChatViewHookPlugin diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgCommonBridgePlugin.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgCommonBridgePlugin.kt index 0be989b6df..5d09760b47 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgCommonBridgePlugin.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgCommonBridgePlugin.kt @@ -11,12 +11,12 @@ import com.ai.assistance.operit.core.chat.plugins.MessageProcessingHookParams import com.ai.assistance.operit.core.chat.plugins.MessageProcessingPlugin import com.ai.assistance.operit.core.chat.plugins.MessageProcessingPluginRegistry import com.ai.assistance.operit.core.chat.hooks.PromptTurn -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_INPUT_MENU_TOGGLE -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_MESSAGE_PROCESSING -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_XML_RENDER +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_INPUT_MENU_TOGGLE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_MESSAGE_PROCESSING +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_XML_RENDER import com.ai.assistance.operit.plugins.OperitPlugin import com.ai.assistance.operit.ui.common.markdown.XmlRenderPlugin import com.ai.assistance.operit.ui.common.markdown.XmlRenderPluginRegistry @@ -27,8 +27,8 @@ import com.ai.assistance.operit.ui.features.conversation.chat.components.style.i import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuTogglePluginRegistry import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.util.stream.Stream -import com.ai.assistance.operit.core.tools.packTool.ToolPkgXmlRenderHookComposeDslResult -import com.ai.assistance.operit.core.tools.packTool.ToolPkgXmlRenderHookObjectResult +import com.ai.assistance.operit.core.tools.packTool.runtime.ToolPkgXmlRenderHookComposeDslResult +import com.ai.assistance.operit.core.tools.packTool.runtime.ToolPkgXmlRenderHookObjectResult import com.ai.assistance.operit.core.tools.javascript.extractJsExecutionErrorMessage import com.ai.assistance.operit.util.stream.stream import java.util.UUID diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgHookBridgeSupport.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgHookBridgeSupport.kt index dc4229bb37..0e934d4a5d 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgHookBridgeSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgHookBridgeSupport.kt @@ -1,12 +1,12 @@ package com.ai.assistance.operit.plugins.toolpkg import com.ai.assistance.operit.core.application.OperitApplication -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.LocalizedText import com.ai.assistance.operit.core.tools.javascript.JsJavaBridgeDelegates import com.ai.assistance.operit.core.tools.javascript.extractJsExecutionErrorMessage -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime import org.json.JSONArray import org.json.JSONObject import org.json.JSONTokener diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgLifecyclePlugin.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgLifecyclePlugin.kt index b281c13c19..fe5ea4831a 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgLifecyclePlugin.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgLifecyclePlugin.kt @@ -1,9 +1,9 @@ package com.ai.assistance.operit.plugins.toolpkg import com.ai.assistance.operit.core.application.OperitApplication -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime import com.ai.assistance.operit.plugins.toolpkg.sortedByToolPkgLoadOrder import com.ai.assistance.operit.plugins.OperitPlugin import com.ai.assistance.operit.plugins.lifecycle.AppLifecycleEvent diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgPromptHookBridge.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgPromptHookBridge.kt index 8b3140baa7..43da11e0d6 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgPromptHookBridge.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgPromptHookBridge.kt @@ -12,15 +12,15 @@ import com.ai.assistance.operit.core.chat.hooks.PromptTurn import com.ai.assistance.operit.core.chat.hooks.PromptTurnKind import com.ai.assistance.operit.core.chat.hooks.SystemPromptComposeHook import com.ai.assistance.operit.core.chat.hooks.ToolPromptComposeHook -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_PROMPT_FINALIZE -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_PROMPT_ESTIMATE_FINALIZE -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_PROMPT_ESTIMATE_HISTORY -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_PROMPT_HISTORY -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_PROMPT_INPUT -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_SYSTEM_PROMPT_COMPOSE -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_TOOL_PROMPT_COMPOSE +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_PROMPT_FINALIZE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_PROMPT_ESTIMATE_FINALIZE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_PROMPT_ESTIMATE_HISTORY +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_PROMPT_HISTORY +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_PROMPT_INPUT +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_SYSTEM_PROMPT_COMPOSE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_TOOL_PROMPT_COMPOSE import com.ai.assistance.operit.util.logging.AppLogger import java.util.concurrent.atomic.AtomicBoolean import org.json.JSONArray diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgSummaryHookBridge.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgSummaryHookBridge.kt index 3793a0ad0f..9d8ae6cc0d 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgSummaryHookBridge.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgSummaryHookBridge.kt @@ -6,9 +6,9 @@ import com.ai.assistance.operit.core.chat.hooks.SummaryGenerateHook import com.ai.assistance.operit.core.chat.hooks.SummaryHookContext import com.ai.assistance.operit.core.chat.hooks.SummaryHookMutation import com.ai.assistance.operit.core.chat.hooks.SummaryHookRegistry -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_SUMMARY_GENERATE +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_SUMMARY_GENERATE import com.ai.assistance.operit.data.model.FunctionType import com.ai.assistance.operit.util.logging.AppLogger import java.util.concurrent.atomic.AtomicBoolean diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgToolLifecycleBridge.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgToolLifecycleBridge.kt index f8f50cae40..86113306b2 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgToolLifecycleBridge.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgToolLifecycleBridge.kt @@ -1,12 +1,12 @@ package com.ai.assistance.operit.plugins.toolpkg import com.ai.assistance.operit.core.application.OperitApplication -import com.ai.assistance.operit.core.tools.AIToolHook -import com.ai.assistance.operit.core.tools.AIToolHookDecision -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_TOOL_LIFECYCLE +import com.ai.assistance.operit.core.tools.runtime.AIToolHook +import com.ai.assistance.operit.core.tools.runtime.AIToolHookDecision +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.parser.ToolPkgContainerRuntime +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_TOOL_LIFECYCLE import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.util.logging.AppLogger diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ai/ToolPkgJsAiProviderService.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ai/ToolPkgJsAiProviderService.kt index 7608034534..8154e89f95 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ai/ToolPkgJsAiProviderService.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ai/ToolPkgJsAiProviderService.kt @@ -2,10 +2,10 @@ package com.ai.assistance.operit.plugins.toolpkg.ai import android.content.Context import com.ai.assistance.operit.core.chat.hooks.PromptTurn -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_AI_PROVIDER_CALCULATE_INPUT_TOKENS -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_AI_PROVIDER_LIST_MODELS -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_AI_PROVIDER_SEND_MESSAGE -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_AI_PROVIDER_TEST_CONNECTION +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_AI_PROVIDER_CALCULATE_INPUT_TOKENS +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_AI_PROVIDER_LIST_MODELS +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_AI_PROVIDER_SEND_MESSAGE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_EVENT_AI_PROVIDER_TEST_CONNECTION import com.ai.assistance.operit.data.model.ModelConfigData import com.ai.assistance.operit.data.model.ModelOption import com.ai.assistance.operit.data.model.ModelParameter diff --git a/app/src/main/java/com/ai/assistance/operit/services/ChatServiceCore.kt b/app/src/main/java/com/ai/assistance/operit/services/ChatServiceCore.kt index af44f95dbf..25d6dd8be7 100644 --- a/app/src/main/java/com/ai/assistance/operit/services/ChatServiceCore.kt +++ b/app/src/main/java/com/ai/assistance/operit/services/ChatServiceCore.kt @@ -16,7 +16,7 @@ import com.ai.assistance.operit.services.core.ChatHistoryDelegate import com.ai.assistance.operit.services.core.MessageCoordinationDelegate import com.ai.assistance.operit.services.core.MessageProcessingDelegate import com.ai.assistance.operit.services.core.TokenStatisticsDelegate -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.UiStateDelegate import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.WorkspaceChangeTracker import com.ai.assistance.operit.util.stream.SharedStream diff --git a/app/src/main/java/com/ai/assistance/operit/services/TermuxCommandResultService.kt b/app/src/main/java/com/ai/assistance/operit/services/TermuxCommandResultService.kt index d39d3218aa..a6354219a4 100644 --- a/app/src/main/java/com/ai/assistance/operit/services/TermuxCommandResultService.kt +++ b/app/src/main/java/com/ai/assistance/operit/services/TermuxCommandResultService.kt @@ -3,7 +3,7 @@ package com.ai.assistance.operit.services import android.app.IntentService import android.content.Intent import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor.CommandResult +import com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor.CommandResult import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob diff --git a/app/src/main/java/com/ai/assistance/operit/services/core/AttachmentDelegate.kt b/app/src/main/java/com/ai/assistance/operit/services/core/AttachmentDelegate.kt index 5ed0c7115f..3ce44d5b37 100644 --- a/app/src/main/java/com/ai/assistance/operit/services/core/AttachmentDelegate.kt +++ b/app/src/main/java/com/ai/assistance/operit/services/core/AttachmentDelegate.kt @@ -5,13 +5,13 @@ import android.content.Context import android.net.Uri import android.provider.OpenableColumns import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.services.core.attachments.ImageAttachmentIndex import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import com.ai.assistance.operit.util.files.OperitPaths -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.DirectoryListingData import com.ai.assistance.operit.core.tools.FileContentData import com.ai.assistance.operit.core.tools.FileExistsData diff --git a/app/src/main/java/com/ai/assistance/operit/services/core/MessageCoordinationDelegate.kt b/app/src/main/java/com/ai/assistance/operit/services/core/MessageCoordinationDelegate.kt index 94298ad0a1..c1864cda86 100644 --- a/app/src/main/java/com/ai/assistance/operit/services/core/MessageCoordinationDelegate.kt +++ b/app/src/main/java/com/ai/assistance/operit/services/core/MessageCoordinationDelegate.kt @@ -26,7 +26,7 @@ import com.ai.assistance.operit.data.model.InputProcessingState import com.ai.assistance.operit.data.model.CharacterCardChatModelBindingMode import com.ai.assistance.operit.data.model.CharacterCardMemoryProfileBindingMode import com.ai.assistance.operit.data.model.ActivePrompt -import com.ai.assistance.operit.core.tools.ToolProgressBus +import com.ai.assistance.operit.core.tools.runtime.ToolProgressBus import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.UiStateDelegate import com.ai.assistance.operit.data.preferences.CharacterCardManager import com.ai.assistance.operit.data.preferences.CharacterGroupCardManager diff --git a/app/src/main/java/com/ai/assistance/operit/services/core/MessageProcessingDelegate.kt b/app/src/main/java/com/ai/assistance/operit/services/core/MessageProcessingDelegate.kt index a6ef2cafe7..f351fcb35c 100644 --- a/app/src/main/java/com/ai/assistance/operit/services/core/MessageProcessingDelegate.kt +++ b/app/src/main/java/com/ai/assistance/operit/services/core/MessageProcessingDelegate.kt @@ -15,7 +15,7 @@ import com.ai.assistance.operit.api.chat.EnhancedAIService import com.ai.assistance.operit.core.chat.AIMessageManager import com.ai.assistance.operit.core.chat.logMessageTiming import com.ai.assistance.operit.core.chat.messageTimingNow -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.agent.PhoneAgentJobRegistry import com.ai.assistance.operit.data.model.* import com.ai.assistance.operit.data.repository.ChatDraftRepository @@ -52,7 +52,7 @@ import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import com.ai.assistance.operit.core.tools.ToolProgressBus +import com.ai.assistance.operit.core.tools.runtime.ToolProgressBus import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.atomic.AtomicLong import kotlin.coroutines.coroutineContext diff --git a/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslActions.kt b/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslActions.kt index 7bc6c14f4f..b724f5bd96 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslActions.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslActions.kt @@ -3,7 +3,7 @@ package com.ai.assistance.operit.ui.common.composedsl import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import com.ai.assistance.operit.core.tools.javascript.JsEngine -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslRenderResult +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslRenderResult import kotlinx.coroutines.yield @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslDebugSnapshotStore.kt b/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslDebugSnapshotStore.kt index 95c4cb74ec..ae00808fb1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslDebugSnapshotStore.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslDebugSnapshotStore.kt @@ -1,8 +1,8 @@ package com.ai.assistance.operit.ui.common.composedsl import android.content.Context -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslNode -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslRenderResult +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslNode +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslRenderResult import org.json.JSONArray import org.json.JSONObject import org.json.JSONTokener diff --git a/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslGeneratedRenderers.kt b/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslGeneratedRenderers.kt index 68bedcdab6..62ba7a98f8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslGeneratedRenderers.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslGeneratedRenderers.kt @@ -49,8 +49,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.sp import coil.compose.rememberAsyncImagePainter -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslNode -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslParser +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslNode +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslParser /** * AUTO-GENERATED from Compose Material3/Foundation component bindings. diff --git a/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslScreen.kt index 7560157851..ecb50c52f2 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslScreen.kt @@ -162,14 +162,14 @@ import androidx.webkit.ScriptHandler import androidx.webkit.WebViewCompat import androidx.webkit.WebViewFeature import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.javascript.JsEngine import com.ai.assistance.operit.core.tools.javascript.JsJavaBridgeDelegates import com.ai.assistance.operit.core.tools.javascript.extractJsExecutionErrorMessage -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslNode -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslParser -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslRenderResult +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslNode +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslParser +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslRenderResult import com.ai.assistance.operit.plugins.chatmessage.ChatMessageMenuDialogRequest import com.ai.assistance.operit.ui.common.displays.MarkdownTextComposable import com.ai.assistance.operit.ui.common.markdown.DefaultXmlRenderer diff --git a/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslWebView.kt b/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslWebView.kt index fdf4cfe1ae..e70041b5b2 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslWebView.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/common/composedsl/ToolPkgComposeDslWebView.kt @@ -44,8 +44,8 @@ import androidx.webkit.WebViewFeature import com.ai.assistance.operit.core.tools.javascript.JsEngine import com.ai.assistance.operit.core.tools.javascript.JsJavaBridgeDelegates import com.ai.assistance.operit.core.tools.javascript.extractJsExecutionErrorMessage -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslNode -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslParser +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslNode +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslParser import com.ai.assistance.operit.ui.features.models.token.webview.WebViewConfig import com.ai.assistance.operit.util.logging.AppLogger import org.json.JSONObject diff --git a/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/XmlRenderPluginRegistry.kt b/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/XmlRenderPluginRegistry.kt index 1fad1b4a23..736b48d401 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/XmlRenderPluginRegistry.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/XmlRenderPluginRegistry.kt @@ -24,10 +24,10 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.LinearProgressIndicator -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslParser -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslRenderResult +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslParser +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslRenderResult import com.ai.assistance.operit.ui.common.composedsl.LocalComposeDslXmlStream import com.ai.assistance.operit.ui.common.composedsl.RenderToolPkgComposeDslNode import com.ai.assistance.operit.ui.common.composedsl.RetainToolPkgComposeDslActions diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionBookmarkSheet.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionBookmarkSheet.kt index 1c552771b6..977cb79026 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionBookmarkSheet.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionBookmarkSheet.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionBookmark +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionBookmark @Composable internal fun WebSessionBookmarkSheet( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionBrowserScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionBrowserScreen.kt index 3ddead823a..4ed03a1ab1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionBrowserScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionBrowserScreen.kt @@ -41,13 +41,13 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionBookmark -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionBrowserHostState -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionBrowserSheetRoute -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionHistoryEntry -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionPendingDialogState -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionWebViewHost -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.ui.WebSessionUserscriptUiState +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionBookmark +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionBrowserHostState +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionBrowserSheetRoute +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionHistoryEntry +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionPendingDialogState +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionWebViewHost +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.ui.WebSessionUserscriptUiState import java.util.Locale @Composable @@ -488,7 +488,7 @@ private fun PendingDialogOverlay( @Composable private fun WebSessionOverlaySheetContent( sheetRoute: WebSessionBrowserSheetRoute, - browserState: com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionBrowserState, + browserState: com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionBrowserState, bookmarks: List, globalHistory: List, userscriptUiState: WebSessionUserscriptUiState, diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionDownloadSheet.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionDownloadSheet.kt index 5098511c36..89085d4b19 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionDownloadSheet.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionDownloadSheet.kt @@ -25,10 +25,10 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.BrowserDownloadFilter -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.BrowserDownloadItem -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.BrowserDownloadUiState -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.formatBytes +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.BrowserDownloadFilter +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.BrowserDownloadItem +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.BrowserDownloadUiState +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.formatBytes @OptIn(ExperimentalLayoutApi::class) @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionHistorySheet.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionHistorySheet.kt index 7e4e42a08d..748db0b0a7 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionHistorySheet.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionHistorySheet.kt @@ -23,8 +23,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionHistoryEntry -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionSessionHistoryItem +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionHistoryEntry +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionSessionHistoryItem import java.text.DateFormat import java.util.Date diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionMenuSheet.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionMenuSheet.kt index 6e9bb1b515..0a3222027d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionMenuSheet.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionMenuSheet.kt @@ -26,7 +26,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptPageMenuCommand +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptPageMenuCommand @Composable internal fun WebSessionMenuSheet( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionMinimizedIndicator.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionMinimizedIndicator.kt index b2791fd557..c4ad9e6889 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionMinimizedIndicator.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionMinimizedIndicator.kt @@ -57,7 +57,7 @@ internal fun WebSessionMinimizedIndicator( contentDescription: String, activeDownloadCount: Int, hasFailedDownloads: Boolean, - externalOpenPrompt: com.ai.assistance.operit.core.tools.defaultTool.websession.browser.ExternalOpenPromptState?, + externalOpenPrompt: com.ai.assistance.operit.core.tools.builtin.web.session.browser.ExternalOpenPromptState?, onToggleFullscreen: () -> Unit, onDragBy: (dx: Int, dy: Int) -> Unit, onConfirmExternalOpen: (String) -> Unit, diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionTabSheet.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionTabSheet.kt index 8eec55e878..9e38d25eca 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionTabSheet.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionTabSheet.kt @@ -26,7 +26,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.websession.browser.WebSessionBrowserTab +import com.ai.assistance.operit.core.tools.builtin.web.session.browser.WebSessionBrowserTab @Composable internal fun WebSessionTabSheet( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionUserscriptSheet.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionUserscriptSheet.kt index 7bc05b6f5b..4728e35e31 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionUserscriptSheet.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/websession/browser/WebSessionUserscriptSheet.kt @@ -40,12 +40,12 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptInstallPreview -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptListItem -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptPageMenuCommand -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptPageRuntimeState -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.UserscriptPageRuntimeStatus -import com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.ui.WebSessionUserscriptUiState +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptInstallPreview +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptListItem +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptPageMenuCommand +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptPageRuntimeState +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.UserscriptPageRuntimeStatus +import com.ai.assistance.operit.core.tools.builtin.web.session.userscript.ui.WebSessionUserscriptUiState @Composable internal fun WebSessionUserscriptSheet( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/screens/WorkflowDetailScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/screens/WorkflowDetailScreen.kt index 9995d1fa7e..cc0449ba64 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/screens/WorkflowDetailScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/screens/WorkflowDetailScreen.kt @@ -31,7 +31,7 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.ai.assistance.operit.R import com.ai.assistance.operit.core.config.SystemToolPrompts -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.model.Workflow import com.ai.assistance.operit.data.model.WorkflowNode import com.ai.assistance.operit.data.model.TriggerNode diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/screens/WorkflowListScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/screens/WorkflowListScreen.kt index 2ead13578e..ec237d88a4 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/screens/WorkflowListScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/screens/WorkflowListScreen.kt @@ -81,7 +81,7 @@ import androidx.compose.ui.unit.sp import androidx.compose.ui.window.DialogProperties import androidx.lifecycle.viewmodel.compose.viewModel import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.ExecutionStatus import com.ai.assistance.operit.data.model.Workflow import com.ai.assistance.operit.ui.components.CustomScaffold diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/viewmodel/WorkflowViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/viewmodel/WorkflowViewModel.kt index 7a1626dfcd..9ea7c384c5 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/viewmodel/WorkflowViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/workflow/viewmodel/WorkflowViewModel.kt @@ -8,8 +8,8 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.core.workflow.NodeExecutionState import com.ai.assistance.operit.data.model.ConditionNode import com.ai.assistance.operit.data.model.ConditionOperator diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentSelector.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentSelector.kt index 720d26bbf1..febf065b99 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentSelector.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentSelector.kt @@ -79,8 +79,8 @@ import androidx.compose.ui.window.Popup import androidx.compose.ui.window.PopupProperties import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.features.conversation.chat.attachments.images.ChatImagePickerDialog -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager as ToolPackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager as ToolPackageManager import com.ai.assistance.operit.data.skill.SkillRepository import kotlinx.coroutines.launch import java.io.File diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedFileTargetDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedFileTargetDialog.kt index e60fff9eb1..72e5fe9c5e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedFileTargetDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedFileTargetDialog.kt @@ -35,9 +35,9 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageFileImportSupport -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.install.PackageFileImportSupport +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.ChatHistory import java.time.format.DateTimeFormatter import java.time.format.FormatStyle diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/agent/AgentChatInputSection.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/agent/AgentChatInputSection.kt index 4a89bbcdae..ee6c4943e9 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/agent/AgentChatInputSection.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/agent/AgentChatInputSection.kt @@ -115,7 +115,7 @@ import com.ai.assistance.operit.api.chat.EnhancedAIService import com.ai.assistance.operit.api.chat.model.ThinkingQualityMapping import com.ai.assistance.operit.api.chat.model.ThinkingQualityMappingRegistry import com.ai.assistance.operit.core.memory.extraction.MemoryAutoSaveScheduler -import com.ai.assistance.operit.core.tools.ToolProgressBus +import com.ai.assistance.operit.core.tools.runtime.ToolProgressBus import com.ai.assistance.operit.data.model.AttachmentInfo import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.data.model.CharacterCardChatModelBindingMode diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatInputSection.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatInputSection.kt index 8dadbeedd7..a0120ffc1c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatInputSection.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatInputSection.kt @@ -64,7 +64,7 @@ import androidx.compose.ui.tooling.preview.Preview import com.ai.assistance.operit.data.model.AttachmentInfo import com.ai.assistance.operit.data.model.InputProcessingState import com.ai.assistance.operit.data.model.ChatMessage -import com.ai.assistance.operit.core.tools.ToolProgressBus +import com.ai.assistance.operit.core.tools.runtime.ToolProgressBus import com.ai.assistance.operit.ui.common.animations.SimpleAnimatedVisibility import com.ai.assistance.operit.ui.features.conversation.chat.components.AttachmentChip import com.ai.assistance.operit.ui.features.conversation.chat.components.AttachmentSelectorPanel diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/HtmlPackagerScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/HtmlPackagerScreen.kt index fae329ef8a..ae04aad9bf 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/HtmlPackagerScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/HtmlPackagerScreen.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.documentfile.provider.DocumentFile -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.ui.components.CustomScaffold diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/AIChatScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/AIChatScreen.kt index 9401c1322f..db167cb41b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/AIChatScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/AIChatScreen.kt @@ -44,7 +44,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.lifecycle.ViewModel import androidx.lifecycle.viewmodel.compose.viewModel import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ApiProviderType import com.ai.assistance.operit.data.model.CharacterCardChatModelBindingMode diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt index 59dcc4a5f9..9d9eeb990c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt @@ -30,7 +30,7 @@ import com.ai.assistance.operit.core.chat.runtime.ChatRuntimeSlot import com.ai.assistance.operit.api.chat.EnhancedAIService import com.ai.assistance.operit.core.chat.AIMessageManager import com.ai.assistance.operit.core.chat.context.ContextWindowBreakdown -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.FileOperationData import com.ai.assistance.operit.data.model.ApiProviderType import com.ai.assistance.operit.data.model.AttachmentInfo @@ -95,7 +95,7 @@ import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace. import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspacePreviewRefreshBus import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspacePreviewRefreshEvent import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.toWorkspaceCommandOutputEntries -import com.ai.assistance.operit.core.tools.system.Terminal +import com.ai.assistance.operit.core.tools.system.terminal.Terminal import com.ai.assistance.operit.core.speech.text.TtsCleaner import com.ai.assistance.operit.core.speech.text.TtsSegmenter import com.ai.assistance.operit.ui.features.conversation.chat.util.findMentionTokens diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/LocalWebServer.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/LocalWebServer.kt index fbc4526202..96f9ea2286 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/LocalWebServer.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/LocalWebServer.kt @@ -7,7 +7,7 @@ import android.system.Os import android.system.OsConstants import android.util.Base64 import android.webkit.CookieManager -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.BinaryFileContentData import com.ai.assistance.operit.core.tools.DirectoryListingData import com.ai.assistance.operit.data.model.AITool diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceFileSelector.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceFileSelector.kt index b1d4325073..c9f63a4c45 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceFileSelector.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceFileSelector.kt @@ -41,8 +41,8 @@ import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager as ToolPackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager as ToolPackageManager import com.ai.assistance.operit.data.skill.SkillRepository import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.GitIgnoreFilter diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt index 3181112a10..cc473cc4f8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt @@ -43,7 +43,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.res.stringResource import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.DirectoryListingData import com.ai.assistance.operit.core.tools.FileContentData import com.ai.assistance.operit.core.tools.FileExistsData diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceBackupManager.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceBackupManager.kt index 572512822d..c1535678f8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceBackupManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceBackupManager.kt @@ -8,8 +8,8 @@ import com.ai.assistance.operit.core.tools.FileContentData import com.ai.assistance.operit.core.tools.FileExistsData import com.ai.assistance.operit.core.tools.FileInfoData import com.ai.assistance.operit.core.tools.FindFilesResultData -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.AIToolHook +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHook import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.util.logging.AppLogger import kotlinx.serialization.Serializable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceManager.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceManager.kt index 8b062c89eb..0693188880 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceManager.kt @@ -51,7 +51,7 @@ import androidx.compose.ui.zIndex import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceEntryAction import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceEntryRequest -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.FileContentData import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ChatHistory diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceReadOnlyDocumentPreview.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceReadOnlyDocumentPreview.kt index e1cf314baa..92d477019f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceReadOnlyDocumentPreview.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceReadOnlyDocumentPreview.kt @@ -35,7 +35,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.BinaryFileContentData import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceSetup.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceSetup.kt index cff79dd443..f67fe030da 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceSetup.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceSetup.kt @@ -18,8 +18,8 @@ import com.ai.assistance.operit.ui.features.conversation.chat.webview.createAndG import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.ui.features.conversation.chat.webview.createAndResetWorkspaceDirectory import kotlinx.coroutines.* diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt index 40de9edb8d..54638573c6 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt @@ -5,7 +5,7 @@ import android.content.Intent import android.util.Base64 import androidx.core.content.FileProvider import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.BinaryFileContentData import com.ai.assistance.operit.core.tools.FileExistsData import com.ai.assistance.operit.data.model.AITool diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkHost.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkHost.kt index 29976bfb2b..4fe30721e9 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkHost.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkHost.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.FileContentData import com.ai.assistance.operit.core.tools.FileExistsData import com.ai.assistance.operit.data.model.AITool diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceRuleFileReader.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceRuleFileReader.kt index 65cbfcf5ea..5db4f1f3dc 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceRuleFileReader.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceRuleFileReader.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process import android.content.Context -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.FileContentData import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/memory/viewmodel/MemoryViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/memory/viewmodel/MemoryViewModel.kt index 5c85fe149e..51b9145537 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/memory/viewmodel/MemoryViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/memory/viewmodel/MemoryViewModel.kt @@ -17,7 +17,7 @@ import com.ai.assistance.operit.data.repository.MemoryRepository import com.ai.assistance.operit.ui.features.conversation.memory.screens.graph.model.Edge import com.ai.assistance.operit.ui.features.conversation.memory.screens.graph.model.Graph import com.ai.assistance.operit.ui.features.conversation.memory.screens.graph.model.Node -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.R diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/memory/workbench/MemoryDocumentImporter.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/memory/workbench/MemoryDocumentImporter.kt index 1c03b76172..3bc00f6a52 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/memory/workbench/MemoryDocumentImporter.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/memory/workbench/MemoryDocumentImporter.kt @@ -3,7 +3,7 @@ package com.ai.assistance.operit.ui.features.conversation.memory.workbench import android.content.Context import android.net.Uri import android.provider.OpenableColumns -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/MCPPackageDetailsDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/MCPPackageDetailsDialog.kt index 31d01f46e7..c1b276068c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/MCPPackageDetailsDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/MCPPackageDetailsDialog.kt @@ -57,7 +57,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.LocalizedText import com.ai.assistance.operit.core.tools.PackageTool import com.ai.assistance.operit.core.tools.PackageToolParameter diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageAddActionDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageAddActionDialog.kt index b29d5a5ebe..ce83cf0600 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageAddActionDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageAddActionDialog.kt @@ -32,7 +32,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.packTool.PackageTemplateKind +import com.ai.assistance.operit.core.tools.packTool.install.PackageTemplateKind /** * 包管理加号弹出的中心选择面板。 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageDetailsDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageDetailsDialog.kt index 10ac316e75..ec768b2429 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageDetailsDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageDetailsDialog.kt @@ -34,8 +34,8 @@ import com.ai.assistance.operit.ui.features.extensions.packages.components.dialo import com.ai.assistance.operit.ui.features.extensions.packages.components.dialogs.packageui.PackageEnvironmentSection import com.ai.assistance.operit.ui.features.extensions.packages.components.dialogs.packageui.PackageToolCard import com.ai.assistance.operit.core.tools.ToolPackage -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.ToolPkgRuntimeMonitor +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.ToolPkgRuntimeMonitor import com.ai.assistance.operit.ui.common.icons.rememberLogoPainter import java.text.SimpleDateFormat import java.util.Date diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageTemplateIdentityDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageTemplateIdentityDialog.kt index d4a7371f74..43f2d9d556 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageTemplateIdentityDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/PackageTemplateIdentityDialog.kt @@ -18,8 +18,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.packTool.PackageTemplateFactory -import com.ai.assistance.operit.core.tools.packTool.PackageTemplateKind +import com.ai.assistance.operit.core.tools.packTool.install.PackageTemplateFactory +import com.ai.assistance.operit.core.tools.packTool.install.PackageTemplateKind /** 新建模板前填写显示名和包标识,避免落盘出未命名垃圾包。 */ @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/ScriptExecutionDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/ScriptExecutionDialog.kt index 2aa74c0b5d..39a41d3c6d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/ScriptExecutionDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/dialogs/ScriptExecutionDialog.kt @@ -25,7 +25,7 @@ import com.ai.assistance.operit.core.tools.PackageTool import com.ai.assistance.operit.core.tools.ScriptExecutionTraceData import com.ai.assistance.operit.core.tools.StringResultData import com.ai.assistance.operit.core.tools.javascript.JsToolManager -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/ArtifactLocalInstallSupport.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/ArtifactLocalInstallSupport.kt index eccad63694..c7da97b112 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/ArtifactLocalInstallSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/ArtifactLocalInstallSupport.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.ui.features.extensions.packages.market import android.content.Context -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.api.ArtifactProjectVersionResponse import com.ai.assistance.operit.data.api.MarketV2Entry import com.ai.assistance.operit.data.transfer.copyWithTransferProgress diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/GitHubForgePublishService.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/GitHubForgePublishService.kt index 2ae8808fef..901231ae5e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/GitHubForgePublishService.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/GitHubForgePublishService.kt @@ -12,7 +12,7 @@ import com.ai.assistance.operit.data.api.MarketV2PublishRequest import com.ai.assistance.operit.data.api.MarketV2PublishVersion import com.ai.assistance.operit.data.api.MarketV2Version import com.ai.assistance.operit.data.preferences.GitHubAuthPreferences -import com.ai.assistance.operit.core.tools.packTool.ToolPkgMarketOrigin +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOrigin import com.ai.assistance.operit.core.tools.packTool.minify.ToolPkgArtifactMinifier import java.io.File import java.net.URI diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/MarketEntryInstallController.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/MarketEntryInstallController.kt index 0079a31ee4..e81a28eabe 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/MarketEntryInstallController.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/MarketEntryInstallController.kt @@ -4,8 +4,8 @@ import com.ai.assistance.operit.ui.common.oktoast.OKToast import android.content.Context import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.api.MarketStatsApiService import com.ai.assistance.operit.data.api.MarketV2Entry import com.ai.assistance.operit.data.mcp.InstallResult diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/MarketInstallMarker.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/MarketInstallMarker.kt index dea710080e..6923c50a5c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/MarketInstallMarker.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/market/MarketInstallMarker.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.ui.features.extensions.packages.market import android.content.Context -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.api.MarketV2Entry import com.ai.assistance.operit.data.mcp.MCPLocalServer import com.ai.assistance.operit.data.skill.SkillRepository diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageManagerDialogs.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageManagerDialogs.kt index 97a65f4662..f62cb2a505 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageManagerDialogs.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageManagerDialogs.kt @@ -54,7 +54,7 @@ import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R import com.ai.assistance.operit.core.tools.EnvVar import com.ai.assistance.operit.core.tools.ToolPackage -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager @Composable fun PackageLoadErrorsDialog( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageManagerScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageManagerScreen.kt index 89a7e5d7cc..23aa2c3742 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageManagerScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageManagerScreen.kt @@ -52,15 +52,15 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.PackageTool import com.ai.assistance.operit.core.tools.ToolPackage import com.ai.assistance.operit.core.tools.EnvVar -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.PackageTemplateCreateError -import com.ai.assistance.operit.core.tools.packTool.PackageTemplateFactory -import com.ai.assistance.operit.core.tools.packTool.PackageTemplateKind -import com.ai.assistance.operit.core.tools.packTool.ToolPkgMarketOrigin +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.install.PackageTemplateCreateError +import com.ai.assistance.operit.core.tools.packTool.install.PackageTemplateFactory +import com.ai.assistance.operit.core.tools.packTool.install.PackageTemplateKind +import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOrigin import com.ai.assistance.operit.data.mcp.MCPRepository import com.ai.assistance.operit.data.preferences.EnvPreferences import com.ai.assistance.operit.data.preferences.ApiPreferences diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageSearch.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageSearch.kt index 66c8086c17..ca77b21fc6 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageSearch.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PackageSearch.kt @@ -3,7 +3,7 @@ package com.ai.assistance.operit.ui.features.extensions.packages.screens import android.content.Context import com.ai.assistance.operit.core.tools.PackageTool import com.ai.assistance.operit.core.tools.ToolPackage -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager fun packageMatchesSearch( context: Context, diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PluginTabContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PluginTabContent.kt index 79252ddec4..0c580ec93c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PluginTabContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/PluginTabContent.kt @@ -49,7 +49,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.core.tools.packTool.metadata.PluginActivity import com.ai.assistance.operit.ui.common.icons.rememberLogoPainter import com.ai.assistance.operit.ui.features.extensions.packages.components.EmptyState diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/QuickPluginCreatorSetupSupport.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/QuickPluginCreatorSetupSupport.kt index c0f2f5b0c0..08ad25bb0d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/QuickPluginCreatorSetupSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/QuickPluginCreatorSetupSupport.kt @@ -3,9 +3,9 @@ package com.ai.assistance.operit.ui.features.extensions.packages.screens import android.content.Context import android.os.Environment import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.data.model.ToolResult diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/artifact/viewmodel/ArtifactMarketViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/artifact/viewmodel/ArtifactMarketViewModel.kt index aefd5a2b4f..67bc40a82e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/artifact/viewmodel/ArtifactMarketViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/artifact/viewmodel/ArtifactMarketViewModel.kt @@ -8,8 +8,8 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.api.MarketStatsApiService import com.ai.assistance.operit.data.api.GitHubApiService import com.ai.assistance.operit.data.api.MarketV2EntryUpdateRequest diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/market/viewmodel/UnifiedMarketBrowseViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/market/viewmodel/UnifiedMarketBrowseViewModel.kt index 059d222c9e..1dfe096866 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/market/viewmodel/UnifiedMarketBrowseViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/market/viewmodel/UnifiedMarketBrowseViewModel.kt @@ -8,8 +8,8 @@ import com.ai.assistance.operit.data.api.MarketStatsApiService import com.ai.assistance.operit.data.api.MarketV2Entry import com.ai.assistance.operit.data.api.MarketV2ManifestCategory import com.ai.assistance.operit.data.api.MarketV2Notification -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.ui.features.extensions.packages.market.MarketEntryInstallController import com.ai.assistance.operit.ui.features.extensions.packages.market.MarketInstallProgress import com.ai.assistance.operit.ui.features.extensions.packages.market.MarketInstallStateStore diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/market/viewmodel/UnifiedMarketDetailViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/market/viewmodel/UnifiedMarketDetailViewModel.kt index 5e36f2b56d..8ec860b4d8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/market/viewmodel/UnifiedMarketDetailViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/extensions/packages/screens/market/viewmodel/UnifiedMarketDetailViewModel.kt @@ -4,8 +4,8 @@ import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.R import com.ai.assistance.operit.data.api.GitHubApiService import com.ai.assistance.operit.data.api.MarketStatsApiService diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/management/resources/hub/ResourceHubViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/management/resources/hub/ResourceHubViewModel.kt index 952d0985f3..ab4142aa6f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/management/resources/hub/ResourceHubViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/management/resources/hub/ResourceHubViewModel.kt @@ -2,7 +2,7 @@ package com.ai.assistance.operit.ui.features.management.resources.hub import android.app.Application import android.os.SystemClock -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import android.net.Uri import android.provider.DocumentsContract import android.provider.OpenableColumns diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/components/CharacterCardDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/components/CharacterCardDialog.kt index a95d3ac899..383c9ad24f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/components/CharacterCardDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/components/CharacterCardDialog.kt @@ -48,8 +48,8 @@ import com.ai.assistance.operit.data.model.getModelByIndex import com.ai.assistance.operit.data.model.getModelList import com.ai.assistance.operit.data.model.getValidModelIndex import com.ai.assistance.operit.core.config.SystemToolPrompts -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.preferences.ModelConfigManager import com.ai.assistance.operit.data.preferences.WaifuPreferences import com.ai.assistance.operit.data.preferences.WaifuSettings diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/display/DisplayBehaviorState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/display/DisplayBehaviorState.kt index cb90f266f2..bfadbdf37b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/display/DisplayBehaviorState.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/display/DisplayBehaviorState.kt @@ -5,7 +5,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import com.ai.assistance.operit.api.chat.AIForegroundService -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.data.preferences.ApiPreferences import com.ai.assistance.operit.data.preferences.DisplayPreferencesManager import com.ai.assistance.operit.data.preferences.OrientationReloadPolicy diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/toolpermissions/ToolPermissionPage.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/toolpermissions/ToolPermissionPage.kt index 091326876e..eaf21a2fb7 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/toolpermissions/ToolPermissionPage.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/toolpermissions/ToolPermissionPage.kt @@ -20,7 +20,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.ui.common.oktoast.OKToast import com.ai.assistance.operit.ui.main.LocalTopBarTitleContent import com.ai.assistance.operit.ui.main.TopBarTitleContent diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/ConfigurationResourceStorageScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/ConfigurationResourceStorageScreen.kt index cc06a87562..65444907f5 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/ConfigurationResourceStorageScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/ConfigurationResourceStorageScreen.kt @@ -28,7 +28,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.storage.ExtensionCategory import com.ai.assistance.operit.data.storage.ExtensionItem import com.ai.assistance.operit.data.storage.formatStorageSize diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/ConfigurationResourceStorageViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/ConfigurationResourceStorageViewModel.kt index b97de966d3..8ce39846ad 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/ConfigurationResourceStorageViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/ConfigurationResourceStorageViewModel.kt @@ -4,7 +4,7 @@ import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.storage.ConfigurationResourceEntry import com.ai.assistance.operit.data.storage.ConfigurationResourceInventory import com.ai.assistance.operit.data.storage.ConfigurationResourceSnapshot diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/DataStorageScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/DataStorageScreen.kt index 74d880d1f6..a278d73951 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/DataStorageScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/management/storage/DataStorageScreen.kt @@ -75,7 +75,7 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.viewmodel.compose.viewModel import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.defaultTool.standard.CookiePrivacyManager +import com.ai.assistance.operit.core.tools.builtin.web.CookiePrivacyManager import com.ai.assistance.operit.data.storage.CleanupTarget import com.ai.assistance.operit.data.storage.CleanupTargetUsage import com.ai.assistance.operit.data.storage.DataStorageSnapshot diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/components/PermissionLevelCard.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/components/PermissionLevelCard.kt index da4113acce..e8ebaecfad 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/components/PermissionLevelCard.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/components/PermissionLevelCard.kt @@ -49,7 +49,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.ai.assistance.operit.R import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilities -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.data.preferences.androidPermissionPreferences import com.ai.assistance.operit.ui.features.support.demo.permissions.SystemPermission import com.ai.assistance.operit.ui.features.support.demo.permissions.SystemPermissionStatus @@ -861,7 +861,7 @@ private fun ShizukuPermissionSection( // 检查Shizuku是否需要更新 val isShizukuUpdateNeeded = remember(isShizukuInstalled, isShizukuRunning, hasShizukuPermission) { try { - com.ai.assistance.operit.core.tools.system.ShizukuInstaller.isShizukuUpdateNeeded( + com.ai.assistance.operit.core.tools.permissions.authorization.ShizukuInstaller.isShizukuUpdateNeeded( context ) } catch (e: Exception) { diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/screens/ShizukuDemoScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/screens/ShizukuDemoScreen.kt index 0a41f47c99..4265b9adaf 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/screens/ShizukuDemoScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/screens/ShizukuDemoScreen.kt @@ -26,12 +26,12 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.viewmodel.compose.viewModel import com.ai.assistance.operit.R -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.ui.main.screens.Screen import com.ai.assistance.operit.ui.main.screens.ScreenNavigationHandler -import com.ai.assistance.operit.core.tools.system.AccessibilityProviderInstaller -import com.ai.assistance.operit.core.tools.system.ShizukuAuthorizer -import com.ai.assistance.operit.core.tools.system.ShizukuInstaller +import com.ai.assistance.operit.core.tools.permissions.authorization.AccessibilityProviderInstaller +import com.ai.assistance.operit.core.tools.permissions.authorization.ShizukuAuthorizer +import com.ai.assistance.operit.core.tools.permissions.authorization.ShizukuInstaller import com.ai.assistance.operit.data.repository.UIHierarchyManager import com.ai.assistance.operit.ui.features.support.demo.components.* import com.ai.assistance.operit.ui.features.support.demo.permissions.SystemPermissionSettings diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/state/DemoStateManager.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/state/DemoStateManager.kt index 2074cc8ceb..6b301ad23f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/state/DemoStateManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/state/DemoStateManager.kt @@ -9,8 +9,8 @@ import android.provider.Settings import com.ai.assistance.operit.util.logging.AppLogger import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf -import com.ai.assistance.operit.core.tools.system.OperitTerminalManager -import com.ai.assistance.operit.core.tools.system.RootAuthorizer +import com.ai.assistance.operit.core.tools.system.terminal.OperitTerminalManager +import com.ai.assistance.operit.core.tools.permissions.authorization.RootAuthorizer import com.ai.assistance.operit.data.repository.UIHierarchyManager import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay @@ -23,9 +23,9 @@ import android.content.pm.PackageManager import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope -import com.ai.assistance.operit.core.tools.system.AccessibilityProviderInstaller -import com.ai.assistance.operit.core.tools.system.ShizukuAuthorizer -import com.ai.assistance.operit.core.tools.system.Terminal +import com.ai.assistance.operit.core.tools.permissions.authorization.AccessibilityProviderInstaller +import com.ai.assistance.operit.core.tools.permissions.authorization.ShizukuAuthorizer +import com.ai.assistance.operit.core.tools.system.terminal.Terminal import com.ai.assistance.operit.data.mcp.plugins.MCPSharedSession import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.features.support.demo.permissions.SystemPermissionSettings diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/viewmodel/ShizukuDemoViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/viewmodel/ShizukuDemoViewModel.kt index de503bed4e..b62ecd3419 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/viewmodel/ShizukuDemoViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/viewmodel/ShizukuDemoViewModel.kt @@ -9,8 +9,8 @@ import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.system.RootAuthorizer +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.permissions.authorization.RootAuthorizer import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.features.support.demo.state.DemoStateManager import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/support/diagnostics/uidebugger/UIDebuggerViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/support/diagnostics/uidebugger/UIDebuggerViewModel.kt index 99409f3cd2..1c3ec92b02 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/support/diagnostics/uidebugger/UIDebuggerViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/support/diagnostics/uidebugger/UIDebuggerViewModel.kt @@ -4,7 +4,7 @@ import android.content.Context import android.graphics.Rect import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.core.tools.UIPageResultData import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.core.tools.system.action.ActionListener diff --git a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/screenocr/screen/FloatingScreenOcrScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/screenocr/screen/FloatingScreenOcrScreen.kt index d00842d996..51a6c7fbf3 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/screenocr/screen/FloatingScreenOcrScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/screenocr/screen/FloatingScreenOcrScreen.kt @@ -69,7 +69,7 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.AttachmentInfo import com.ai.assistance.operit.ui.floating.FloatContext diff --git a/app/src/main/java/com/ai/assistance/operit/ui/main/MainActivity.kt b/app/src/main/java/com/ai/assistance/operit/ui/main/MainActivity.kt index 089e6b6a9d..999f5a4920 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/main/MainActivity.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/main/MainActivity.kt @@ -34,7 +34,7 @@ import androidx.lifecycle.lifecycleScope import com.ai.assistance.operit.R import com.ai.assistance.operit.api.chat.AIForegroundService import com.ai.assistance.operit.core.application.OperitApplication -import com.ai.assistance.operit.core.tools.AIToolHandler +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler import com.ai.assistance.operit.data.preferences.AgreementPreferences import com.ai.assistance.operit.data.preferences.DisplayPreferencesManager import com.ai.assistance.operit.data.preferences.OrientationReloadPolicy diff --git a/app/src/main/java/com/ai/assistance/operit/ui/main/OperitApp.kt b/app/src/main/java/com/ai/assistance/operit/ui/main/OperitApp.kt index 802f09088e..61543ce3d5 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/main/OperitApp.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/main/OperitApp.kt @@ -24,8 +24,8 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.compose.ui.res.stringResource import androidx.navigation.compose.rememberNavController -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.data.mcp.MCPRepository import com.ai.assistance.operit.data.security.PluginDenylistRepository import com.ai.assistance.operit.data.preferences.ApiPreferences diff --git a/app/src/main/java/com/ai/assistance/operit/ui/main/components/DrawerContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/main/components/DrawerContent.kt index f356f98e62..15971e530d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/main/components/DrawerContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/main/components/DrawerContent.kt @@ -66,10 +66,10 @@ import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalRunMa import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalMainChatViewModel import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalMainChatSidebarState import com.ai.assistance.operit.ui.theme.LocalThemePreferenceSnapshot -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager import com.ai.assistance.operit.core.tools.permissions.PermissionCapabilityResolver -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import com.ai.assistance.operit.data.preferences.UserPreferencesManager import com.ai.assistance.operit.data.preferences.androidPermissionPreferences diff --git a/app/src/main/java/com/ai/assistance/operit/ui/main/navigation/AppRouteCatalog.kt b/app/src/main/java/com/ai/assistance/operit/ui/main/navigation/AppRouteCatalog.kt index 85af5b1b3d..829198027c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/main/navigation/AppRouteCatalog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/main/navigation/AppRouteCatalog.kt @@ -3,9 +3,9 @@ package com.ai.assistance.operit.ui.main.navigation import android.content.Context import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Extension -import com.ai.assistance.operit.core.tools.AIToolHandler -import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_NAV_SURFACE_MAIN_SIDEBAR_PLUGINS +import com.ai.assistance.operit.core.tools.runtime.AIToolHandler +import com.ai.assistance.operit.core.tools.packTool.runtime.PackageManager +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_NAV_SURFACE_MAIN_SIDEBAR_PLUGINS import com.ai.assistance.operit.ui.common.icons.MaterialIconNameResolver import com.ai.assistance.operit.ui.main.screens.Screen import com.ai.assistance.operit.ui.main.screens.ScreenRouteRegistry diff --git a/app/src/test/java/com/ai/assistance/operit/core/chat/protocol/ConversationMarkupManagerResultLimitTest.kt b/app/src/test/java/com/ai/assistance/operit/core/chat/protocol/ConversationMarkupManagerResultLimitTest.kt index 9558c23365..2040f4392b 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/chat/protocol/ConversationMarkupManagerResultLimitTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/chat/protocol/ConversationMarkupManagerResultLimitTest.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.core.chat.protocol import com.ai.assistance.operit.core.tools.StringResultData -import com.ai.assistance.operit.core.tools.ToolExecutionLimits +import com.ai.assistance.operit.core.tools.runtime.ToolExecutionLimits import com.ai.assistance.operit.data.model.ToolResult import com.ai.assistance.operit.core.chat.protocol.ChatMarkupRegex import org.junit.Assert.assertEquals diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolsTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolsTest.kt similarity index 99% rename from app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolsTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolsTest.kt index c6760ccdd6..d15a488c0e 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolsTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolsTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.a2ui +package com.ai.assistance.operit.core.tools.builtin.a2ui import com.ai.assistance.operit.core.chat.tools.ToolExecutionManager.ToolRuntimeContext import com.ai.assistance.operit.core.tools.StringResultData diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ToolPermissionModeSupportTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/builtin/settings/ToolPermissionModeSupportTest.kt similarity index 95% rename from app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ToolPermissionModeSupportTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/builtin/settings/ToolPermissionModeSupportTest.kt index e778d4597b..c97f772b36 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ToolPermissionModeSupportTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/builtin/settings/ToolPermissionModeSupportTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.settings import com.ai.assistance.operit.ui.permissions.PermissionLevel import org.junit.Assert.assertEquals diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ShellCommandSafetyTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/builtin/shell/ShellCommandSafetyTest.kt similarity index 98% rename from app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ShellCommandSafetyTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/builtin/shell/ShellCommandSafetyTest.kt index 171c3a1c21..59b12bbe11 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ShellCommandSafetyTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/builtin/shell/ShellCommandSafetyTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.standard +package com.ai.assistance.operit.core.tools.builtin.shell import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserNavigationPolicyTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserNavigationPolicyTest.kt similarity index 98% rename from app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserNavigationPolicyTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserNavigationPolicyTest.kt index 13e64bb888..e080f0701a 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserNavigationPolicyTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserNavigationPolicyTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.defaultTool.websession.browser +package com.ai.assistance.operit.core.tools.builtin.web.session.browser import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/javascript/ComposeDslActionRetentionTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/javascript/ComposeDslActionRetentionTest.kt index 3a0c7e1f15..6f8d9bdb9f 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/javascript/ComposeDslActionRetentionTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/javascript/ComposeDslActionRetentionTest.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.core.tools.javascript -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslNode -import com.ai.assistance.operit.core.tools.packTool.ToolPkgComposeDslRenderResult +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslNode +import com.ai.assistance.operit.core.tools.packTool.uidsl.ToolPkgComposeDslRenderResult import org.junit.Assert.assertEquals import org.junit.Test diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageFileImportSupportTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageFileImportSupportTest.kt similarity index 93% rename from app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageFileImportSupportTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageFileImportSupportTest.kt index d35cf46331..758a06c0d9 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageFileImportSupportTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageFileImportSupportTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.install import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageSourceDeletionTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageSourceDeletionTest.kt similarity index 97% rename from app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageSourceDeletionTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageSourceDeletionTest.kt index 0029e8141d..44142da237 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageSourceDeletionTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageSourceDeletionTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.install import java.io.File import org.junit.Assert.* diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageTemplateFactoryTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageTemplateFactoryTest.kt similarity index 98% rename from app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageTemplateFactoryTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageTemplateFactoryTest.kt index 21b9a260f0..b2e2dce0c4 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageTemplateFactoryTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageTemplateFactoryTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.install import java.io.File import java.util.zip.ZipFile diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiDeclarationTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiDeclarationTest.kt similarity index 94% rename from app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiDeclarationTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiDeclarationTest.kt index 4120602b8e..ea22409f93 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiDeclarationTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiDeclarationTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.metadata import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMarketOriginCodecTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgMarketOriginCodecTest.kt similarity index 97% rename from app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMarketOriginCodecTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgMarketOriginCodecTest.kt index 852d956d03..901b81b2ba 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMarketOriginCodecTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgMarketOriginCodecTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.metadata import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManifestSelectionTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgManifestSelectionTest.kt similarity index 96% rename from app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManifestSelectionTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgManifestSelectionTest.kt index ad599bdbc0..0baf087163 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManifestSelectionTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgManifestSelectionTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.parser import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageActivationResultTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageActivationResultTest.kt similarity index 97% rename from app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageActivationResultTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageActivationResultTest.kt index cb08885360..0d021ab2fa 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageActivationResultTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageActivationResultTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.runtime import com.ai.assistance.operit.core.tools.PackageActivationErrorCode import com.ai.assistance.operit.core.tools.PackageActivationErrorData diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManagerTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgManagerTest.kt similarity index 98% rename from app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManagerTest.kt rename to app/src/test/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgManagerTest.kt index 07da7c22b6..4ef2f1134d 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManagerTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgManagerTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.core.tools.packTool +package com.ai.assistance.operit.core.tools.packTool.runtime import android.content.Context import com.ai.assistance.operit.core.tools.javascript.JsEngine diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitiesTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitiesTest.kt index 6fb6590b6f..0159b753dd 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitiesTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitiesTest.kt @@ -1,7 +1,7 @@ package com.ai.assistance.operit.core.tools.permissions -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel -import com.ai.assistance.operit.core.tools.system.ShellIdentity +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.system.shell.ShellIdentity import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Test diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitySessionTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitySessionTest.kt index 8d60cc3334..1ef141d541 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitySessionTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionCapabilitySessionTest.kt @@ -1,6 +1,6 @@ package com.ai.assistance.operit.core.tools.permissions -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Test diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionOperationRouterTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionOperationRouterTest.kt index 3a9fcf4e80..9dd4d378e8 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionOperationRouterTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/permissions/PermissionOperationRouterTest.kt @@ -1,6 +1,6 @@ package com.ai.assistance.operit.core.tools.permissions -import com.ai.assistance.operit.core.tools.system.AndroidPermissionLevel +import com.ai.assistance.operit.core.tools.permissions.AndroidPermissionLevel import kotlinx.coroutines.CancellationException import kotlinx.coroutines.runBlocking import org.junit.Assert.assertEquals diff --git a/app/src/test/java/com/ai/assistance/operit/core/tools/system/uiautomator/UiAutomatorDumpGuardTest.kt b/app/src/test/java/com/ai/assistance/operit/core/tools/system/uiautomator/UiAutomatorDumpGuardTest.kt index e2bf47f33c..e1219bb19b 100644 --- a/app/src/test/java/com/ai/assistance/operit/core/tools/system/uiautomator/UiAutomatorDumpGuardTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/core/tools/system/uiautomator/UiAutomatorDumpGuardTest.kt @@ -1,6 +1,6 @@ package com.ai.assistance.operit.core.tools.system.uiautomator -import com.ai.assistance.operit.core.tools.system.AndroidShellExecutor +import com.ai.assistance.operit.core.tools.system.shell.AndroidShellExecutor import java.io.File import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger diff --git a/docs/TODO/chore/README.md b/docs/TODO/chore/README.md index 86074d4ee5..3139c84750 100644 --- a/docs/TODO/chore/README.md +++ b/docs/TODO/chore/README.md @@ -6,6 +6,8 @@ ## 计划索引 +- [工具权限收口与目录整理](tools-permissions-layout/index.md) + - [1.12.2+15 分仓与布局修复发行](release-1.12.2-plus-15/index.md) - [正式版、补丁与离线资源分仓](release-repositories/index.md) diff --git a/docs/TODO/chore/tools-permissions-layout/01-permissions.md b/docs/TODO/chore/tools-permissions-layout/01-permissions.md index 9e793884e5..48621d0dcb 100644 --- a/docs/TODO/chore/tools-permissions-layout/01-permissions.md +++ b/docs/TODO/chore/tools-permissions-layout/01-permissions.md @@ -20,6 +20,6 @@ - [x] 管理员包含原无障碍和 Shell 操作,Root 保留原操作行为 - [x] 运行时模式只有标准、管理员、Root,旧偏好可迁移 - [x] 工具名称、参数和结果格式保持现有契约 -- [x] 静态引用与语法检查完成,操作体迁移逐项对比;仓库验证尚未派发 +- [x] 静态引用与语法检查完成,操作体迁移逐项对比;仓库编译与运行验证结果在 PR 中记录 [DONE] 权限收口代码及静态核对完成,运行验证以工作流结果为准。 diff --git a/docs/TODO/chore/tools-permissions-layout/02-layout.md b/docs/TODO/chore/tools-permissions-layout/02-layout.md new file mode 100644 index 0000000000..f7ab80bf3d --- /dev/null +++ b/docs/TODO/chore/tools-permissions-layout/02-layout.md @@ -0,0 +1,303 @@ +# 02 工具目录迁移 + +权限收口提交完成后读取工具源码,再以 [files.json](files.json) 作为本批逐文件迁移依据。清单记录当前路径、目标路径、源包名、目标包名和源文件摘要;执行前核对摘要,执行后核对文件与包名。 + +## 目标结构 + +以下仅展示本批涉及的目录,其余已有职责目录保持原有归属。 + +```text +core/tools/ + builtin/ + filesystem/ + ui/ + device/ + system/ + shell/ + terminal/ + web/ + session/ + calculator/ + workflow/ + chat/ + settings/ + media/ + memory/ + a2ui/ + packTool/ + PackageDebugRefreshReceiver.kt + ToolPkgDebugInstallReceiver.kt + ToolPkgComposeDslDebugDumpReceiver.kt + parser/ + loader/ + runtime/ + install/ + minify/ + uidsl/ + metadata/ + runtime/ + permissions/ + authorization/ + system/ + shell/ + capture/ + terminal/ +``` + +## 迁移规则 + +- 内置工具按功能组织,标准、管理员、Root 实现放在同一功能目录 +- 插件包按解析、加载、运行、安装、压缩、UI DSL 和元数据归类 +- 工具执行与注册入口集中到 runtime,授权安装与检测集中到 permissions/authorization +- 同步 Kotlin 引用、同包隐式依赖、Manifest 组件、脚本显式组件及测试资源路径 +- 目录迁移保持具体操作体,既有逻辑完善分别记录在权限收口提交中 + +- 安装、刷新与 UI DSL 调试广播接收器保留既有公开组件名,现有 ADB 与编辑器调用继续使用原入口 + +## 文件清单 + +共 117 个文件,迁移 111 个,保留已合理分区或已有公开入口的文件 6 个。以下路径均相对于仓库根目录。 + +- 迁移:`app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/ffmpeg/ffmpeg_probe.js` + - 目标:`app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/media/ffmpeg/ffmpeg_probe.js` +- 迁移:`app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/main.js` + - 目标:`app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/main.js` +- 迁移:`app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/probe.js` + - 目标:`app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/probe.js` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/ToolGetter.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ToolGetter.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolDefinitions.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolDefinitions.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolRuntime.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolRuntime.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardCalculator.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/calculator/StandardCalculator.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardChatManagerTool.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/chat/StandardChatManagerTool.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardDeviceInfoToolExecutor.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/device/StandardDeviceInfoToolExecutor.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/PathValidator.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/PathValidator.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminFileSystemTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/AdminFileSystemTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/LinuxFileSystemTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/LinuxFileSystemTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/SafFileSystemTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/SafFileSystemTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/StandardFileSystemTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/BluetoothSessionManager.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/BluetoothSessionManager.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFFmpegTool.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardFFmpegTool.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardMusicPlaybackTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardMusicPlaybackTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/MemoryQueryToolExecutor.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/memory/MemoryQueryToolExecutor.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSoftwareSettingsModifyTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/settings/StandardSoftwareSettingsModifyTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ToolPermissionModeSupport.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/settings/ToolPermissionModeSupport.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ShellCommandSafety.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/shell/ShellCommandSafety.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardShellToolExecutor.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/shell/StandardShellToolExecutor.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminSystemOperationTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/AdminSystemOperationTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardIntentToolExecutor.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardIntentToolExecutor.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSendBroadcastToolExecutor.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSendBroadcastToolExecutor.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSystemOperationTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSystemOperationTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardTerminalCommandExecutor.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/terminal/StandardTerminalCommandExecutor.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminUITools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/AdminUITools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootUITools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/RootUITools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardUITools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/StandardUITools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/CookiePrivacyManager.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/CookiePrivacyManager.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardBrowserSessionTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardBrowserSessionTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardHttpTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardHttpTools.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWebVisitTool.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardWebVisitTool.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserDownloadSupport.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserDownloadSupport.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserNavigationPolicy.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserNavigationPolicy.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserPageExecutionSupport.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserPageExecutionSupport.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserToolSupport.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserToolSupport.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserWebViewSupport.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserWebViewSupport.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionBrowserHost.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionBrowserHost.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionBrowserHostState.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionBrowserHostState.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionHistoryStore.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionHistoryStore.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionPermissionRequestActivity.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionPermissionRequestActivity.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionWebViewHost.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionWebViewHost.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptCapabilityRegistry.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptCapabilityRegistry.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptMatcher.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptMatcher.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptMetadataParser.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptMetadataParser.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptModels.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptModels.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/install/UserscriptImportCoordinator.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/install/UserscriptImportCoordinator.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/install/UserscriptImportPickerActivity.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/install/UserscriptImportPickerActivity.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptBootstrapScript.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptBootstrapScript.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptCookieService.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptCookieService.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptStorageNotifier.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptStorageNotifier.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptTabStateStore.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptTabStateStore.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptWebRequestEngine.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptWebRequestEngine.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/WebSessionUserscriptManager.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/WebSessionUserscriptManager.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptEntities.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptEntities.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptJsonStore.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptJsonStore.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptRepository.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptRepository.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/ui/WebSessionUserscriptUiStateStore.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/ui/WebSessionUserscriptUiStateStore.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWorkflowTools.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/builtin/workflow/StandardWorkflowTools.kt` +- 保留:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageDebugRefreshReceiver.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageDebugRefreshReceiver.kt` +- 保留:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgComposeDslDebugDumpReceiver.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgComposeDslDebugDumpReceiver.kt` +- 保留:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgDebugInstallReceiver.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgDebugInstallReceiver.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageFileImportSupport.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageFileImportSupport.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageSourceDeletion.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageSourceDeletion.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageTemplateFactory.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageTemplateFactory.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgLoadOrder.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/loader/ToolPkgLoadOrder.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgLoader.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/loader/ToolPkgLoader.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/BuiltInPackageDefaults.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/BuiltInPackageDefaults.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiVersion.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiVersion.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgCommonPluginConstants.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgCommonPluginConstants.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManifestRequirement.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgManifestRequirement.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMarketOrigin.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgMarketOrigin.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgTemplateModels.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgTemplateModels.kt` +- 保留:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/PluginActivityStore.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/PluginActivityStore.kt` +- 保留:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgArtifactMinifier.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgArtifactMinifier.kt` +- 保留:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgJsAstMinifier.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgJsAstMinifier.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMainRegistrationScriptParser.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgMainRegistrationScriptParser.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgParser.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageActivationResult.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageActivationResult.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManager.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageManager.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManagerToolPkgFacade.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageManagerToolPkgFacade.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgHookModels.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgHookModels.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManager.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgManager.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgRuntimeMonitor.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgRuntimeMonitor.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgComposeDslParser.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/uidsl/ToolPkgComposeDslParser.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidPermissionLevel.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/permissions/AndroidPermissionLevel.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/AccessibilityProviderInstaller.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/AccessibilityProviderInstaller.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/RootAuthorizer.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/RootAuthorizer.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/ShizukuAuthorizer.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/ShizukuAuthorizer.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/ShizukuInstaller.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/ShizukuInstaller.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/AIToolHandler.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/runtime/AIToolHandler.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/AIToolHook.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/runtime/AIToolHook.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/ToolExecutionLimits.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolExecutionLimits.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/ToolProgressBus.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolProgressBus.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/MediaProjectionCaptureManager.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/MediaProjectionCaptureManager.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/MediaProjectionHolder.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/MediaProjectionHolder.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/ScreenCaptureActivity.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/ScreenCaptureActivity.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/ScreenCaptureService.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/ScreenCaptureService.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidShellExecutor.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/AndroidShellExecutor.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/OperitTerminalManager.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/system/terminal/OperitTerminalManager.kt` +- 迁移:`app/src/main/java/com/ai/assistance/operit/core/tools/system/Terminal.kt` + - 目标:`app/src/main/java/com/ai/assistance/operit/core/tools/system/terminal/Terminal.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolsTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolsTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ToolPermissionModeSupportTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/builtin/settings/ToolPermissionModeSupportTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ShellCommandSafetyTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/builtin/shell/ShellCommandSafetyTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserNavigationPolicyTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserNavigationPolicyTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageFileImportSupportTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageFileImportSupportTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageSourceDeletionTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageSourceDeletionTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageTemplateFactoryTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageTemplateFactoryTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiDeclarationTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiDeclarationTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMarketOriginCodecTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgMarketOriginCodecTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManifestSelectionTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgManifestSelectionTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageActivationResultTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageActivationResultTest.kt` +- 迁移:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManagerTest.kt` + - 目标:`app/src/test/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgManagerTest.kt` + +## 验收 + +- [x] 清单中所有目标路径及包名一致 +- [x] 旧引用、同包隐式依赖和显式组件调用已同步 +- [x] 移动文件的操作体保持,静态语法与差异检查完成 +- [x] 仓库验证入口与交付方式已记录,实际运行结果见 PR + +[DONE] 清单中的目录迁移及静态核对完成,编译与 JVM 单测结果由仓库工作流确认。 diff --git a/docs/TODO/chore/tools-permissions-layout/files.json b/docs/TODO/chore/tools-permissions-layout/files.json new file mode 100644 index 0000000000..1a8dcc4801 --- /dev/null +++ b/docs/TODO/chore/tools-permissions-layout/files.json @@ -0,0 +1,1060 @@ +{ + "schemaVersion": 1, + "baseCommit": "718707fd19ab7c27e38c8807055c80809d25e6dc", + "scope": "工具权限收口后的目录迁移", + "files": [ + { + "source": "app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/ffmpeg/ffmpeg_probe.js", + "target": "app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/media/ffmpeg/ffmpeg_probe.js", + "sourcePackage": null, + "targetPackage": null, + "group": "android-js/builtin/media/ffmpeg", + "operation": "move", + "sourceSha256": "1fa1a507372b221f4f2d81617edc482afed954e2130a7f27479b42a0c86fc93c" + }, + { + "source": "app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/main.js", + "target": "app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/main.js", + "sourcePackage": null, + "targetPackage": null, + "group": "android-js/builtin/web/browser", + "operation": "move", + "sourceSha256": "29befc725e9bb7872a7b5e68ae55e5ddfe0d731b07d870944687f0ca3b9f32a9" + }, + { + "source": "app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/probe.js", + "target": "app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/probe.js", + "sourcePackage": null, + "targetPackage": null, + "group": "android-js/builtin/web/browser", + "operation": "move", + "sourceSha256": "4e9a9170e4f9714b6bac55b72f45e15c429312d254e53f4526b9dfbd6c64313d" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/ToolGetter.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ToolGetter.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin", + "group": "builtin", + "operation": "move", + "sourceSha256": "a68f991a7d7dcab3efc983fb5999847e236426bcb7e37f79eb981c5fafef691a" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolDefinitions.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolDefinitions.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.a2ui", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.a2ui", + "group": "builtin/a2ui", + "operation": "move", + "sourceSha256": "5336bc3f49a03912712f14588ac630a719cedc626c7f9e6c6d6b2143e7006c96" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolRuntime.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolRuntime.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.a2ui", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.a2ui", + "group": "builtin/a2ui", + "operation": "move", + "sourceSha256": "ff01825f817b7c0fbe1fe7c3ff93b0ce8c1f842c80871f667d59b8699db743da" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.a2ui", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.a2ui", + "group": "builtin/a2ui", + "operation": "move", + "sourceSha256": "25e4ccb6b94570ffd06e32649399e3b10bb5be425e671075965e01e2182dc513" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardCalculator.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/calculator/StandardCalculator.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.calculator", + "group": "builtin/calculator", + "operation": "move", + "sourceSha256": "79bcdcb659c1391b575854e47d6cec56b9f1c0bb3728223355055660ae93f894" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardChatManagerTool.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/chat/StandardChatManagerTool.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.chat", + "group": "builtin/chat", + "operation": "move", + "sourceSha256": "ec054348c9996be0c507c134bc5078d20fcfccf0ba9925b4f54a3e4c0e11456e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardDeviceInfoToolExecutor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/device/StandardDeviceInfoToolExecutor.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.device", + "group": "builtin/device", + "operation": "move", + "sourceSha256": "4ec9a994a0dda069b7ef05428241f87e5cc1cdec0845354286dbaa7f3c16fb8a" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminFileSystemTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/AdminFileSystemTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.admin", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.filesystem", + "group": "builtin/filesystem", + "operation": "move", + "sourceSha256": "9e92411bd6fd6d094889792eacd6f1e25ce3839d6f80e81dbafc29cc70e05b06" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/LinuxFileSystemTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/LinuxFileSystemTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.filesystem", + "group": "builtin/filesystem", + "operation": "move", + "sourceSha256": "90d9f5b4cfd6c4e6a211d560b9734484003bd2dfb9ea27bc4a115959108fabc6" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/PathValidator.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/PathValidator.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.filesystem", + "group": "builtin/filesystem", + "operation": "move", + "sourceSha256": "666052a44cc6b747a6e309f2eabd34a7985cad9d0c2beeb0fcc79a1202f66868" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/SafFileSystemTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/SafFileSystemTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.filesystem", + "group": "builtin/filesystem", + "operation": "move", + "sourceSha256": "2a5d727822768e073d7ec59f4a9defb66d1dfe5a54b91ad0d1f6c1c10ef245b9" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/StandardFileSystemTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.filesystem", + "group": "builtin/filesystem", + "operation": "move", + "sourceSha256": "c91d4761af374e11c124e2d84dbb8ad115027406d76244e251bdb202ed5759fa" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/BluetoothSessionManager.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/BluetoothSessionManager.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.media", + "group": "builtin/media", + "operation": "move", + "sourceSha256": "a90c17d7f7393097ec8bb087a19f0595651109b342d5c0d7c04b6408f66edb53" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFFmpegTool.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardFFmpegTool.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.media", + "group": "builtin/media", + "operation": "move", + "sourceSha256": "2f8cf167a5c2e530ce6f8fa65dda91715c0a0bad6fe2f507e32e4af32c538018" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardMusicPlaybackTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardMusicPlaybackTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.media", + "group": "builtin/media", + "operation": "move", + "sourceSha256": "8ee46026a26b5cf9b3d46a9930f341ece9d8aa35bf4b5a9d64968c7a4cccbeeb" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/MemoryQueryToolExecutor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/memory/MemoryQueryToolExecutor.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.memory", + "group": "builtin/memory", + "operation": "move", + "sourceSha256": "bd3ec607ee528c0874761658d25f6721da6df2614c3261f7a8227b2c7770b11e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSoftwareSettingsModifyTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/settings/StandardSoftwareSettingsModifyTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.settings", + "group": "builtin/settings", + "operation": "move", + "sourceSha256": "7be8c2bf6842c4204fe215f82bcf0bb54f85b0d361ccba6aa4a33bbdcb060b2a" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ToolPermissionModeSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/settings/ToolPermissionModeSupport.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.settings", + "group": "builtin/settings", + "operation": "move", + "sourceSha256": "5ca4b53b37c7ec51b1c99afe76beeeaf0ccbb077daa2c17fa9ec68ca8a5ba6ef" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ShellCommandSafety.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/shell/ShellCommandSafety.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.shell", + "group": "builtin/shell", + "operation": "move", + "sourceSha256": "ed8dbbe94e9e7392f92e3925c8567e9f2fd439a37205b4d48c27d95dfd815128" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardShellToolExecutor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/shell/StandardShellToolExecutor.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.shell", + "group": "builtin/shell", + "operation": "move", + "sourceSha256": "bbc33d60d4ff81ee4545510431ebad946b1adc6e2e10adbcc4594a97e6b844af" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminSystemOperationTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/AdminSystemOperationTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.admin", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.system", + "group": "builtin/system", + "operation": "move", + "sourceSha256": "2905543b02cfd2e69381d84f10e886fcc1c44f04a89b3f00c2eed70648dfa423" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardIntentToolExecutor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardIntentToolExecutor.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.system", + "group": "builtin/system", + "operation": "move", + "sourceSha256": "f734bf44f9d63c5c605fb0eb45252e1fa8a258340b918ce59d04a38817eab229" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSendBroadcastToolExecutor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSendBroadcastToolExecutor.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.system", + "group": "builtin/system", + "operation": "move", + "sourceSha256": "586b2f4b275f8c80014b0b2af462ad294e512760551e34c08b30ea3fdfc2c317" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSystemOperationTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSystemOperationTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.system", + "group": "builtin/system", + "operation": "move", + "sourceSha256": "3b5445ba9b2c384a9d37c0ae36bad92f7a5afa9e52014eb7e54190d5ea722b0e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardTerminalCommandExecutor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/terminal/StandardTerminalCommandExecutor.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.terminal", + "group": "builtin/terminal", + "operation": "move", + "sourceSha256": "1f24869e00d0a1f2f72ee71132499b313bb7bc53be57dfd62fc3e18be8c89ce4" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/AdminUITools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/AdminUITools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.admin", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.ui", + "group": "builtin/ui", + "operation": "move", + "sourceSha256": "00484a4936ebb5d26c269480a7d439773b7a77c2ba8f81a5208827f960ab9e87" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/RootUITools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/RootUITools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.root", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.ui", + "group": "builtin/ui", + "operation": "move", + "sourceSha256": "01df2c3548d66af6a772013af9614e9bbada3184f7faa446bcae05a944c59e22" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardUITools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/StandardUITools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.ui", + "group": "builtin/ui", + "operation": "move", + "sourceSha256": "ce013a4d5c295ab04d71c5f0cc442b8ce97391384772b680c836ca9cf7741532" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/CookiePrivacyManager.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/CookiePrivacyManager.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web", + "group": "builtin/web", + "operation": "move", + "sourceSha256": "96f3b8544756e0aa14e8f13e819916fd5972dcd0e2da4e1bb4b0bfe418c47515" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardBrowserSessionTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardBrowserSessionTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web", + "group": "builtin/web", + "operation": "move", + "sourceSha256": "c62dc5e41efe3e9e4b1300a856c04cfff9e99dda826068e45d3185da1ef22992" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardHttpTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardHttpTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web", + "group": "builtin/web", + "operation": "move", + "sourceSha256": "49403df45a4ed708dd93bef1478f445fd6aa0d034f7cca10ddee32a19aa0ea7e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWebVisitTool.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardWebVisitTool.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web", + "group": "builtin/web", + "operation": "move", + "sourceSha256": "09a85bab17fd04a915f7c037998589c4a130936c52f9b735ea5f747a742fe3b3" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserDownloadSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserDownloadSupport.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "5967edebda6dca56448928740f9a1aa0543927e71aac63fa01e22e08f5bc60a6" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserNavigationPolicy.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserNavigationPolicy.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "adfc6cbbe604381db73cdab6ea71d6c655fbdeee69cff7ad7170b0de768a98ca" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserPageExecutionSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserPageExecutionSupport.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "f0e6f0797ee3ea32b99425ecec7bd099033d072a22117d0f811dc6910868c2c2" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserToolSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserToolSupport.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "030977e04709519a935acdb47861545942088f9d8408bd91cd249d407d652294" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserWebViewSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserWebViewSupport.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "9205b2ab66bd49ac83f55b57812b84c651a73e4750e2d83bb5da00370d59eabc" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionBrowserHost.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionBrowserHost.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "7ff7e74727f41c7fcc642deaee7a38e97b44967948dfc7c085431b6a38a7f77e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionBrowserHostState.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionBrowserHostState.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "1e88fa02a47d45a7a1493c7a012de89687be28d3b23498fa71ac29a5ee240d6e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionHistoryStore.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionHistoryStore.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "75669d76a0c1383a9302ee6e92b5e4c5b23661da4d8f6d9fb3c87da739509c80" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionPermissionRequestActivity.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionPermissionRequestActivity.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "410e33dc6cc2e35920694af3001643dae05ca030a81defcdd26a0f014f6a4a13" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/WebSessionWebViewHost.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/WebSessionWebViewHost.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "e712246b317bbf58e82daf13ae259b668e7d51c3d48b6d10924488d94af2da6a" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptCapabilityRegistry.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptCapabilityRegistry.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "b019a3852ad7518c7d913f88f52a0bc9eacfebbbc44de78c33911094f4d2f86f" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptMatcher.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptMatcher.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "4dc8728f983f447f9387c877d4d4719781186f810ad9dc1ce62cb31e73d3b3c6" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptMetadataParser.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptMetadataParser.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "61b10ffe14c148b71438f3e6f1e76fb3880255a83e52d8887d9169468fbf69c2" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/UserscriptModels.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/UserscriptModels.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "e7a21b310f70dbc28bd9524067959ffe0a8fbf0c1abe2545954b031b3e668b3a" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/install/UserscriptImportCoordinator.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/install/UserscriptImportCoordinator.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.install", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.install", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "7a6a1b511c4a3be25410b1530580bdca421ab929f8e072cd60abe15a9c991f38" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/install/UserscriptImportPickerActivity.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/install/UserscriptImportPickerActivity.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.install", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.install", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "61ffdbbd288462d933a93ef9328e63fd543a4a98961249d628f880ff2acefd4c" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptBootstrapScript.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptBootstrapScript.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "6758b1a711108961479560eeafe43bbe8994c98aa531a93d4678601cda0249c5" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptCookieService.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptCookieService.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "d6a464a71d9ea7b9defd9ebae36ea7aa843f320307c49dad7b9f1d8ac5bc46bd" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptStorageNotifier.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptStorageNotifier.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "997da1faf8ef4f8c87a93a94bcb9f1e72a69236e41a415be865ea71ba7d621e0" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptTabStateStore.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptTabStateStore.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "d5b0ab291d79aca089d5be30697d12bcf58581ba0dc72f3eb3923a0cae042e14" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/UserscriptWebRequestEngine.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/UserscriptWebRequestEngine.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "b07612abbc090f08ab5c524cd958cc4a5bd2d6ff9802cabcab355879e6d7c963" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/runtime/WebSessionUserscriptManager.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/runtime/WebSessionUserscriptManager.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.runtime", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.runtime", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "9e786ffb6f20163cbf85514c38c334ebf3d9dc736fd20a2fd7e2a5618bdb0aeb" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptEntities.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptEntities.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.storage", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.storage", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "f1df9f8a0b4733ce6cfcaab0e37a464c1ba44edddc355d097fe1950328ef8594" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptJsonStore.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptJsonStore.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.storage", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.storage", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "e9d2907f1c7386357e4b4a7056202428ff33c7dca74e7a6cfb8b744ef16f825e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/storage/UserscriptRepository.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/storage/UserscriptRepository.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.storage", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.storage", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "1e61186ebc622fa8f92d76c52b7ebcf520642d0841e920ab708b4862f5896cda" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/websession/userscript/ui/WebSessionUserscriptUiStateStore.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/session/userscript/ui/WebSessionUserscriptUiStateStore.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.userscript.ui", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.userscript.ui", + "group": "builtin/web/session", + "operation": "move", + "sourceSha256": "47bc1e6d52bb122a246c6911b807c8aaac73d3d25ddcf314f82ab3e8c3b4513e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWorkflowTools.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/builtin/workflow/StandardWorkflowTools.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.workflow", + "group": "builtin/workflow", + "operation": "move", + "sourceSha256": "373e12784000553bc6675f1fa97e974391cf1750abd25e7111a254741da8080c" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageDebugRefreshReceiver.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageDebugRefreshReceiver.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool", + "group": "packTool", + "operation": "keep", + "sourceSha256": "52ecb7abe0804ab14e0d52cae26e8d86050b36c3aee480c637ff2216d96d1298" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgComposeDslDebugDumpReceiver.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgComposeDslDebugDumpReceiver.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool", + "group": "packTool", + "operation": "keep", + "sourceSha256": "d8697d409ae36d9717af512aa626d0cc37222ccb17ccbec2585a60beec505272" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgDebugInstallReceiver.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgDebugInstallReceiver.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool", + "group": "packTool", + "operation": "keep", + "sourceSha256": "64b7a06d29f761e0ddc30d3af7e44ca03c8aa9dca2c901b4f2c78a8494d2d52a" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageFileImportSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageFileImportSupport.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.install", + "group": "packTool/install", + "operation": "move", + "sourceSha256": "90b1c892d4fbb8d0e46e5ade9b96c3b351ea59edf9a425422ac01e254729c374" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageSourceDeletion.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageSourceDeletion.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.install", + "group": "packTool/install", + "operation": "move", + "sourceSha256": "0d814bdc07218ce2bd3dcfc0e5846efa1a65fed52283d51958c79e2e154e1b3e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageTemplateFactory.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/install/PackageTemplateFactory.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.install", + "group": "packTool/install", + "operation": "move", + "sourceSha256": "1ad69beee67364b4e3e1609f9ec79c21089451a69f4f1cd940e56d2819dcb549" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgLoadOrder.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/loader/ToolPkgLoadOrder.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.loader", + "group": "packTool/loader", + "operation": "move", + "sourceSha256": "ec146016ab2252e215aeb5194560b0356401471d000eef2b85509e9a15a0ead5" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgLoader.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/loader/ToolPkgLoader.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.loader", + "group": "packTool/loader", + "operation": "move", + "sourceSha256": "772918135e21bdc11214adb25763d0cd0bec98ca822394749e34e5909f72568d" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/BuiltInPackageDefaults.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/BuiltInPackageDefaults.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.metadata", + "group": "packTool/metadata", + "operation": "move", + "sourceSha256": "bf72c6bb35ead143ce98e3a547a68c3b88c0d9034e362fb252302b229c7d9164" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/PluginActivityStore.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/PluginActivityStore.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool.metadata", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.metadata", + "group": "packTool/metadata", + "operation": "keep", + "sourceSha256": "abaabd71f03e52746368ef550c4bf7ba88a73de7d2def22bed8b22cb90b0a74e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiVersion.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiVersion.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.metadata", + "group": "packTool/metadata", + "operation": "move", + "sourceSha256": "bb032bc49a9ec11d86d044af71d344bba1c86c98cad1eadade211e7de0a6bab6" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgCommonPluginConstants.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgCommonPluginConstants.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.metadata", + "group": "packTool/metadata", + "operation": "move", + "sourceSha256": "43e54dd3a4bbd173aa7910b5a3f7fe0824495b00c7daeabe92888590470eb01b" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManifestRequirement.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgManifestRequirement.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.metadata", + "group": "packTool/metadata", + "operation": "move", + "sourceSha256": "207a40a4f36b648bdf8b512f744bec00330184e4ec56c183a74d0509558863e2" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMarketOrigin.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgMarketOrigin.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.metadata", + "group": "packTool/metadata", + "operation": "move", + "sourceSha256": "2f53cd45a6cb65683186f9856ac568361f57ece70e2393b68d4a8f29737609b3" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgTemplateModels.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgTemplateModels.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.metadata", + "group": "packTool/metadata", + "operation": "move", + "sourceSha256": "8a0554909f06c342677fd77823a693620055e76338612b1d34daf8e0df3351cb" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgArtifactMinifier.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgArtifactMinifier.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool.minify", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.minify", + "group": "packTool/minify", + "operation": "keep", + "sourceSha256": "717867cd2823353f83cbd57e9a612c82008159598c586f61396206b9ea84f50e" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgJsAstMinifier.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/minify/ToolPkgJsAstMinifier.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool.minify", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.minify", + "group": "packTool/minify", + "operation": "keep", + "sourceSha256": "8ae17659255fb28f636398e92b424decb75336bfd61de2734866fae539228a9d" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMainRegistrationScriptParser.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgMainRegistrationScriptParser.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.parser", + "group": "packTool/parser", + "operation": "move", + "sourceSha256": "d9481fe46c859ea3dd5ddacb705cd02af2ac1604d0220b53787d0ad11597c415" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgParser.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.parser", + "group": "packTool/parser", + "operation": "move", + "sourceSha256": "d3fb8f689da940852e923c357408fa459a688dd232ff371e93c957698cd4f9b0" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageActivationResult.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageActivationResult.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.runtime", + "group": "packTool/runtime", + "operation": "move", + "sourceSha256": "43043dc603fcd7c2d7feadcdd76d118ecbca353b31ce5374254f6785d2fcf62c" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManager.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageManager.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.runtime", + "group": "packTool/runtime", + "operation": "move", + "sourceSha256": "281b64ae3fafb4da46d473e241408f60d49a131775408f1f6abf2a4bcd905ef4" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManagerToolPkgFacade.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageManagerToolPkgFacade.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.runtime", + "group": "packTool/runtime", + "operation": "move", + "sourceSha256": "e129b9e9735ccb23f8ae6843f15878b7d064bf7d0b5adb414deb795ebe685103" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgHookModels.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgHookModels.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.runtime", + "group": "packTool/runtime", + "operation": "move", + "sourceSha256": "1a426bd351bea56d13718ca437321df689fff60dbcc5e2b286bf2b3071672f50" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManager.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgManager.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.runtime", + "group": "packTool/runtime", + "operation": "move", + "sourceSha256": "51ab8e4f41ad47fe36d246143591b34d9707b60746bf6148212ac02d5e0a9ff6" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgRuntimeMonitor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgRuntimeMonitor.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.runtime", + "group": "packTool/runtime", + "operation": "move", + "sourceSha256": "bc9ab08144cb8fc5ccf9682425ecbbea81eab7918ea6529409b548f57414d6b3" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgComposeDslParser.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/packTool/uidsl/ToolPkgComposeDslParser.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.uidsl", + "group": "packTool/uidsl", + "operation": "move", + "sourceSha256": "8d33ab0f27409c6df3334331a66920118f61a8b24e87ebe3cbbc501ccd0b3fac" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidPermissionLevel.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/permissions/AndroidPermissionLevel.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.permissions", + "group": "permissions", + "operation": "move", + "sourceSha256": "d22443b90ca90002883556824c1144036f080e0d0e67f1c54d7cc78d3d40a642" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/AccessibilityProviderInstaller.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/AccessibilityProviderInstaller.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.permissions.authorization", + "group": "permissions/authorization", + "operation": "move", + "sourceSha256": "b912919a645c74561f560adfffd4130bca10e7c1a557202a8157f547586f63bb" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/RootAuthorizer.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/RootAuthorizer.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.permissions.authorization", + "group": "permissions/authorization", + "operation": "move", + "sourceSha256": "899a11eb57ea093f148bfe42b9eb5a4e1d37a62c8bee6f0a30327b636b0b0cd0" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/ShizukuAuthorizer.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/ShizukuAuthorizer.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.permissions.authorization", + "group": "permissions/authorization", + "operation": "move", + "sourceSha256": "47be3245a57b6d22be40fe97b146fcada81791a753c07317ac05dd230351652b" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/ShizukuInstaller.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/permissions/authorization/ShizukuInstaller.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.permissions.authorization", + "group": "permissions/authorization", + "operation": "move", + "sourceSha256": "85942359b635a9704e50d074b7338b05f080e290e49c8404976f9297971af40c" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/AIToolHandler.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/runtime/AIToolHandler.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools", + "targetPackage": "com.ai.assistance.operit.core.tools.runtime", + "group": "runtime", + "operation": "move", + "sourceSha256": "169a8a24283b29a1a8e4c0b1418442ba416ca992d37494cb185a00e96c31577b" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/AIToolHook.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/runtime/AIToolHook.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools", + "targetPackage": "com.ai.assistance.operit.core.tools.runtime", + "group": "runtime", + "operation": "move", + "sourceSha256": "3e4913e96095fe38051786992842d48cc9cd0823540ad9845f07793c1905f412" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/ToolExecutionLimits.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolExecutionLimits.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools", + "targetPackage": "com.ai.assistance.operit.core.tools.runtime", + "group": "runtime", + "operation": "move", + "sourceSha256": "14dcd24cb56dbec6c76327b1842739966b55e24bf39f25b9ccff11abb9c97d4d" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/ToolProgressBus.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolProgressBus.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools", + "targetPackage": "com.ai.assistance.operit.core.tools.runtime", + "group": "runtime", + "operation": "move", + "sourceSha256": "8cef67b48a465c515c2f2ef7d97b253c900eac3e07fef3aade2d8532037217d0" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools", + "targetPackage": "com.ai.assistance.operit.core.tools.runtime", + "group": "runtime", + "operation": "move", + "sourceSha256": "9f6fbd82f24b3c865a9d270640e233063bad87b434381864585bd3b08715cba0" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/MediaProjectionCaptureManager.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/MediaProjectionCaptureManager.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.system.capture", + "group": "system/capture", + "operation": "move", + "sourceSha256": "4716293bd0fb4457e068cbc88aefad77630d431a376dc172e0e6fb53284f7c2f" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/MediaProjectionHolder.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/MediaProjectionHolder.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.system.capture", + "group": "system/capture", + "operation": "move", + "sourceSha256": "25a5452b759b206dbbf09810e96940583b121e01e08867fa798fc01b1bebd9b6" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/ScreenCaptureActivity.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/ScreenCaptureActivity.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.system.capture", + "group": "system/capture", + "operation": "move", + "sourceSha256": "b81234d7f27ffe5fdd17ac9848251d37eb04f98c3650442bc60816fdca037769" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/ScreenCaptureService.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/system/capture/ScreenCaptureService.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.system.capture", + "group": "system/capture", + "operation": "move", + "sourceSha256": "39de34c1dd487169c68d511a228cbd986a134b3a4b4c6ad2b6e8d9c1665e74d7" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/AndroidShellExecutor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/system/shell/AndroidShellExecutor.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.system.shell", + "group": "system/shell", + "operation": "move", + "sourceSha256": "cdca5059498e1b37e079d72a650d22b93424411626654e144edde03c2837f246" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/OperitTerminalManager.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/system/terminal/OperitTerminalManager.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.system.terminal", + "group": "system/terminal", + "operation": "move", + "sourceSha256": "a3c477aaa53a61773a2cd1049cda6179cbfc13b61f4cb34330bd1296a49747f2" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/core/tools/system/Terminal.kt", + "target": "app/src/main/java/com/ai/assistance/operit/core/tools/system/terminal/Terminal.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.system", + "targetPackage": "com.ai.assistance.operit.core.tools.system.terminal", + "group": "system/terminal", + "operation": "move", + "sourceSha256": "45a22a4932c2af47b5db3311f5e43966b1e76cfddb2aa543d52faf7e87228a10" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/a2ui/A2uiToolsTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/builtin/a2ui/A2uiToolsTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.a2ui", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.a2ui", + "group": "tests/builtin/a2ui", + "operation": "move", + "sourceSha256": "a83003debdc5de0ea0d036c749dc4ce6411484006de3965508dfa37c5bd355d0" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ToolPermissionModeSupportTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/builtin/settings/ToolPermissionModeSupportTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.settings", + "group": "tests/builtin/settings", + "operation": "move", + "sourceSha256": "dcfda6fc6fe18b27b6d6b8d41cdfbbec74c3f1572318c8a74bded90de3ceffe3" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/standard/ShellCommandSafetyTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/builtin/shell/ShellCommandSafetyTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.standard", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.shell", + "group": "tests/builtin/shell", + "operation": "move", + "sourceSha256": "3b2017bb1684fd2944d9b27dcaadfccb58d89147610c43d459bbea08af92049f" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/defaultTool/websession/browser/BrowserNavigationPolicyTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/builtin/web/session/browser/BrowserNavigationPolicyTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.defaultTool.websession.browser", + "targetPackage": "com.ai.assistance.operit.core.tools.builtin.web.session.browser", + "group": "tests/builtin/web/session/browser", + "operation": "move", + "sourceSha256": "ea47f6a2bd3017de431c3a836cc7bbd3909e5c55feb250973668e37cf0a6a377" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageFileImportSupportTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageFileImportSupportTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.install", + "group": "tests/packTool/install", + "operation": "move", + "sourceSha256": "e3d2784fd4a2cf4a4031433d5e192ca63e962eab1727357515ad6625eecf080c" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageSourceDeletionTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageSourceDeletionTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.install", + "group": "tests/packTool/install", + "operation": "move", + "sourceSha256": "d80e4119332e0c939867331e7e7f33ba30e1cfa58bc432d76c53a2711cfb2bd3" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageTemplateFactoryTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/install/PackageTemplateFactoryTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.install", + "group": "tests/packTool/install", + "operation": "move", + "sourceSha256": "ece1af8d1ca93308a36aac08251dea5e95db3c201cf44403a579457d939e5ab7" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiDeclarationTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiDeclarationTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.metadata", + "group": "tests/packTool/metadata", + "operation": "move", + "sourceSha256": "de21af2f58f85d67659fe7e2659085a40b17afc144ef528c75b9b9a1dc638334" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMarketOriginCodecTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgMarketOriginCodecTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.metadata", + "group": "tests/packTool/metadata", + "operation": "move", + "sourceSha256": "ac68a386de7dab0b8dfb2758230acc6b6e3ff3f0e9461b9f0e5594e9bc9f59ec" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManifestSelectionTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgManifestSelectionTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.parser", + "group": "tests/packTool/parser", + "operation": "move", + "sourceSha256": "68442d9fa53207bec8e609a47a6e30a8331d620c05fd3cc17343d5c7268e356d" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/PackageActivationResultTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/runtime/PackageActivationResultTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.runtime", + "group": "tests/packTool/runtime", + "operation": "move", + "sourceSha256": "e951755e4839bbaadbf1eb164c8936e11684ba15d63e5c23fc9893d1864a2a03" + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgManagerTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/core/tools/packTool/runtime/ToolPkgManagerTest.kt", + "sourcePackage": "com.ai.assistance.operit.core.tools.packTool", + "targetPackage": "com.ai.assistance.operit.core.tools.packTool.runtime", + "group": "tests/packTool/runtime", + "operation": "move", + "sourceSha256": "81ffb753a0aa956bc0082690a1102c2f6b72b1bd0b9632b856a86de37638f1ec" + } + ] +} diff --git a/docs/TODO/chore/tools-permissions-layout/index.md b/docs/TODO/chore/tools-permissions-layout/index.md index 2f225ef9a8..1f448399d7 100644 --- a/docs/TODO/chore/tools-permissions-layout/index.md +++ b/docs/TODO/chore/tools-permissions-layout/index.md @@ -1,6 +1,6 @@ --- fork: https://github.com/3316891527/Operit -status: in-progress +status: implemented --- # 工具权限收口与目录整理 @@ -13,17 +13,20 @@ status: in-progress ## 执行顺序 1. [权限实现收口](01-permissions.md):删除旧工具等级和无行为的中间层,管理员按实际授权使用无障碍、Shizuku,Root 复用管理员能力。 -2. 目录迁移:读取权限收口后的工具源码,先记录逐文件当前路径、目标路径及目标包名,再按清单迁移并同步引用。 +2. [目录迁移](02-layout.md):读取权限收口后的工具源码,先记录逐文件当前路径、目标路径及目标包名,再按清单迁移并同步引用。 迁移清单只记录本次实际迁移的文件。目录整理以保持工具调用接口及现有行为为目标。 ## 验证与交付 -记录静态引用、路径、配置及差异检查;本地不执行编译、构建或测试。推送工作分支后先派发仓库工作流,再创建以 `dev` 为目标的 PR。工作流受理与实际运行结果分别记录。 +记录静态引用、路径、配置及差异检查,编译与 JVM 单测通过仓库工作流验证。推送工作分支后先派发仓库工作流,再创建以 `dev` 为目标的 PR。工作流受理与实际运行结果分别记录。 + +详见[验证记录](verification.md)。 ## 进度 - [x] 权限实现统一为三档,旧配置只在迁移入口识别 -- [ ] 形成逐文件目标路径清单 -- [ ] 完成清单中全部迁移及调用方同步 -- [ ] 完成静态核对、提交、工作流派发与 PR +- [x] 形成逐文件目标路径清单 +- [x] 完成清单中全部迁移及调用方同步 +- [x] 完成静态核对并准备工作分支交付 +- [ ] 远端构建与 JVM 单测结果确认 diff --git a/docs/TODO/chore/tools-permissions-layout/verification.md b/docs/TODO/chore/tools-permissions-layout/verification.md new file mode 100644 index 0000000000..fe438ca2da --- /dev/null +++ b/docs/TODO/chore/tools-permissions-layout/verification.md @@ -0,0 +1,27 @@ +# 验证记录 + +本次交付分为权限实现收口和工具目录迁移两个提交。目录迁移以 [files.json](files.json) 为依据,当前共 117 个文件,其中迁移 111 个,保留 6 个。 + +## 静态核对 + +- 权限收口逐项比较 61 个原操作体及辅助方法,以及 17 个管理员文件操作路由,保留原操作实现和只读标记 +- 目录迁移比较 264 份受影响 Kotlin 文件的声明内容,除包名、导入和清单对应的显式路径引用外未发现其他变化 +- 核对清单全部目标文件、目标包名、迁移符号导入及工具导入名称冲突 +- 静态语法扫描未发现新增问题;最终类型检查与编译结果以仓库工作流为准 +- 核对变更 XML、Python 语法、Markdown 本地链接与 Git 差异空白 +- 安装、刷新与 UI DSL 调试广播保持原公开组件名,现有 ADB 和编辑器调用仍使用原入口 + +## 仓库验证 + +- [Build](../../../../.github/workflows/build.yml):工作分支执行 `assembleDebug` +- [Android Tests](../../../../.github/workflows/android-tests.yml):工作分支执行 Android JVM 单测 +- PR 的 Candidate checks 根据实际差异选择技术检查 + +本地未执行编译、构建或测试。工作流派发受理与最终运行结果分别记录在 PR 中,派发成功不代表构建或测试已经通过。 + +## 对应回归范围 + +- `PermissionCapabilitiesTest` 覆盖三档用户模式与 16 种授权状态组合,共 48 组能力选择,以及显式显示器和 Shell 身份选择 +- `PermissionOperationRouterTest` 与 `PermissionCapabilitySessionTest` 覆盖原有操作路由及会话能力缓存 +- `AndroidPermissionModeMigrationTest` 覆盖旧偏好转换为管理员,以及 Root 和其他偏好的保留 +- 插件包、内置工具和 JS 测试随目录迁移同步包名、引用和资源路径,具体运行结果以仓库工作流为准 \ No newline at end of file diff --git a/docs/doc-src/architecture/DEFAULT_TOOLS_ARCH.md b/docs/doc-src/architecture/DEFAULT_TOOLS_ARCH.md index 1f1c896205..89f15c781b 100644 --- a/docs/doc-src/architecture/DEFAULT_TOOLS_ARCH.md +++ b/docs/doc-src/architecture/DEFAULT_TOOLS_ARCH.md @@ -40,7 +40,7 @@ ### 2.2 必改:工具注册(toolName -> executor) -- **文件**:`app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` +- **文件**:`app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` - **你要做的事**: - 确认工具名不变时,一般无需改注册,但要确认调用到的 executor 没变 - 若工具名/分组变更,需要同步调整注册项 @@ -52,15 +52,19 @@ ### 2.3 必改:Kotlin 执行实现(参数读取与校验) - **常见目录**: - - `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/*` - - `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/debugger/*` - - `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/admin/*` - - `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/root/*` - - `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/*` - - `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/ToolGetter.kt`(按权限级别选择具体实现) + - `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/` + - `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/` + - `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/` + - `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/` + - `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ToolGetter.kt`(按三档模式取得工具) +- **权限模型**: + - 用户模式只有 `STANDARD`、`ADMIN`、`ROOT` + - 管理员工具直接包含无障碍与 Shell 操作,按实际授权选择执行能力 + - Root 复用管理员公共能力,并保留专有 UI 实现 + - 无障碍、Shizuku 是执行后端,历史无障碍、调试模式仅由偏好迁移入口转换为管理员 - **你要做的事**: - 将旧参数的读取逻辑替换为新参数(`tool.parameters.find { it.name == "..." }`) - - 如果某个工具在 `debugger/root/admin/accessibility` 目录下有 override / 替代实现:这些实现里同样要同步更新参数读取与校验 + - 同一功能目录中的标准、管理员、Root 实现有 override 时,同步更新参数读取与校验 - 新增参数合法性校验:必填、互斥、默认值、兼容性策略 - 更新错误消息(要能引导正确用法) diff --git a/docs/doc-src/toolpkg_developer_documentation/04_modules/android.md b/docs/doc-src/toolpkg_developer_documentation/04_modules/android.md index af9546679f..ded8c98465 100644 --- a/docs/doc-src/toolpkg_developer_documentation/04_modules/android.md +++ b/docs/doc-src/toolpkg_developer_documentation/04_modules/android.md @@ -152,5 +152,5 @@ console.log(result.action, result.result); - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsLibraries.kt` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsTools.kt` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsInitRuntimeScriptBuilder.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardIntentToolExecutor.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardIntentToolExecutor.kt` - `docs/doc-src/toolpkg_developer_documentation/04_modules/system.md` diff --git a/docs/doc-src/toolpkg_developer_documentation/04_modules/ffmpeg.md b/docs/doc-src/toolpkg_developer_documentation/04_modules/ffmpeg.md index 1d544dd3c7..c2e5e976aa 100644 --- a/docs/doc-src/toolpkg_developer_documentation/04_modules/ffmpeg.md +++ b/docs/doc-src/toolpkg_developer_documentation/04_modules/ffmpeg.md @@ -255,5 +255,5 @@ interface RuntimeStreamInfo { - `examples/types/tool-types.d.ts` - `app/src/main/assets/packages/ffmpeg.js` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFFmpegTool.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardFFmpegTool.kt` - `app/src/main/java/com/ai/assistance/operit/core/tools/ToolResultDataClasses.kt` diff --git a/docs/doc-src/toolpkg_developer_documentation/04_modules/files.md b/docs/doc-src/toolpkg_developer_documentation/04_modules/files.md index 037aa7e81f..9a7ecd8203 100644 --- a/docs/doc-src/toolpkg_developer_documentation/04_modules/files.md +++ b/docs/doc-src/toolpkg_developer_documentation/04_modules/files.md @@ -457,7 +457,7 @@ await Tools.Files.download({ - `examples/types/files.d.ts` - `examples/types/results.d.ts` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/LinuxFileSystemTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/SafFileSystemTools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/StandardFileSystemTools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/LinuxFileSystemTools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/filesystem/SafFileSystemTools.kt` diff --git a/docs/doc-src/toolpkg_developer_documentation/04_modules/memory.md b/docs/doc-src/toolpkg_developer_documentation/04_modules/memory.md index 494709a0a6..70c2051876 100644 --- a/docs/doc-src/toolpkg_developer_documentation/04_modules/memory.md +++ b/docs/doc-src/toolpkg_developer_documentation/04_modules/memory.md @@ -395,8 +395,8 @@ console.log(link.linkType, link.weight); - `examples/types/memory.d.ts` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/MemoryQueryToolExecutor.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/memory/MemoryQueryToolExecutor.kt` - `app/src/main/java/com/ai/assistance/operit/core/tools/ToolResultDataClasses.kt` - [结果类型参考](./results.md) - [全局运行时 API](../03_runtime/global_api.md) diff --git a/docs/doc-src/toolpkg_developer_documentation/04_modules/network.md b/docs/doc-src/toolpkg_developer_documentation/04_modules/network.md index 2a6da43f17..022897582f 100644 --- a/docs/doc-src/toolpkg_developer_documentation/04_modules/network.md +++ b/docs/doc-src/toolpkg_developer_documentation/04_modules/network.md @@ -500,7 +500,7 @@ await Tools.Net.browserClick({ - `examples/types/network.d.ts` - `examples/types/results.d.ts` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardHttpTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardWebVisitTool.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardBrowserSessionTools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardHttpTools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardWebVisitTool.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardBrowserSessionTools.kt` diff --git a/docs/doc-src/toolpkg_developer_documentation/04_modules/okhttp.md b/docs/doc-src/toolpkg_developer_documentation/04_modules/okhttp.md index 9a6e254be6..47cee8b1b0 100644 --- a/docs/doc-src/toolpkg_developer_documentation/04_modules/okhttp.md +++ b/docs/doc-src/toolpkg_developer_documentation/04_modules/okhttp.md @@ -254,8 +254,8 @@ console.log(response.text()); - `app/src/main/assets/js/OkHttp3.js` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsAssetLoader.kt` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsLibraries.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardHttpTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/web/StandardHttpTools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` - `app/src/main/java/com/ai/assistance/operit/core/tools/ToolResultDataClasses.kt` - [网络模块参考](./network.md) - [结果类型参考](./results.md) diff --git a/docs/doc-src/toolpkg_developer_documentation/04_modules/system.md b/docs/doc-src/toolpkg_developer_documentation/04_modules/system.md index f540c61e50..077bc41c15 100644 --- a/docs/doc-src/toolpkg_developer_documentation/04_modules/system.md +++ b/docs/doc-src/toolpkg_developer_documentation/04_modules/system.md @@ -596,11 +596,11 @@ await Tools.System.music.play({ - `examples/types/system.d.ts` - `examples/types/results.d.ts` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSystemOperationTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardTerminalCommandExecutor.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/BluetoothSessionManager.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardMusicPlaybackTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardIntentToolExecutor.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardSendBroadcastToolExecutor.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSystemOperationTools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/terminal/StandardTerminalCommandExecutor.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/BluetoothSessionManager.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/media/StandardMusicPlaybackTools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardIntentToolExecutor.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/system/StandardSendBroadcastToolExecutor.kt` - [公共结果类型](results.md) diff --git a/docs/doc-src/toolpkg_developer_documentation/04_modules/tasker.md b/docs/doc-src/toolpkg_developer_documentation/04_modules/tasker.md index 98ed4abba2..7d25af7e20 100644 --- a/docs/doc-src/toolpkg_developer_documentation/04_modules/tasker.md +++ b/docs/doc-src/toolpkg_developer_documentation/04_modules/tasker.md @@ -19,7 +19,7 @@ triggerEvent: (params) => toolCall('trigger_tasker_event', params || {}) 相关实现位于: - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` - `app/src/main/java/com/ai/assistance/operit/integrations/tasker/AIAgentTasker.kt` ## `Tasker.TriggerTaskerEventParams` @@ -155,6 +155,6 @@ await Tools.Tasker.triggerEvent({ - `examples/types/tasker.d.ts` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` - `app/src/main/java/com/ai/assistance/operit/integrations/tasker/AIAgentTasker.kt` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsInitRuntimeScriptBuilder.kt` diff --git a/docs/doc-src/toolpkg_developer_documentation/04_modules/tool-types.md b/docs/doc-src/toolpkg_developer_documentation/04_modules/tool-types.md index d67d720b3b..30b046b3b1 100644 --- a/docs/doc-src/toolpkg_developer_documentation/04_modules/tool-types.md +++ b/docs/doc-src/toolpkg_developer_documentation/04_modules/tool-types.md @@ -312,7 +312,7 @@ disable_workflow - `examples/types/core.d.ts` - `examples/types/results.d.ts` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsTools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` - [公共结果类型](results.md) - [Files 参考](files.md) - [Network 参考](network.md) diff --git a/docs/doc-src/toolpkg_developer_documentation/04_modules/ui.md b/docs/doc-src/toolpkg_developer_documentation/04_modules/ui.md index 8f44e3243d..7cf31a9a16 100644 --- a/docs/doc-src/toolpkg_developer_documentation/04_modules/ui.md +++ b/docs/doc-src/toolpkg_developer_documentation/04_modules/ui.md @@ -262,7 +262,8 @@ await Tools.UI.clickElement({ - `examples/types/results.d.ts` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsTools.kt` - `app/src/main/assets/js/UINode.js` -- `app/src/main/java/com/ai/assistance/operit/core/tools/ToolRegistration.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardUITools.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/accessbility/AccessibilityUITools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/runtime/ToolRegistration.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/StandardUITools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/AdminUITools.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/builtin/ui/RootUITools.kt` - `docs/doc-src/toolpkg_developer_documentation/04_modules/results.md` diff --git a/docs/doc-src/toolpkg_developer_documentation/05_hooks/render_and_toggle.md b/docs/doc-src/toolpkg_developer_documentation/05_hooks/render_and_toggle.md index 8f9741ee31..06941a881e 100644 --- a/docs/doc-src/toolpkg_developer_documentation/05_hooks/render_and_toggle.md +++ b/docs/doc-src/toolpkg_developer_documentation/05_hooks/render_and_toggle.md @@ -102,7 +102,7 @@ ToolPkg.registerInputMenuTogglePlugin({ ## 权威实现 - `plugins/toolpkg/ToolPkgCommonBridgePlugin.kt`:tag 匹配、渲染结果消费、输入 toggle 缓存和 create/toggle 调度。 -- `core/tools/packTool/ToolPkgParser.kt`、`ToolPkgMainRegistrationScriptParser.kt`:注册定义解析。 +- `core/tools/packTool/parser/ToolPkgParser.kt`、`ToolPkgMainRegistrationScriptParser.kt`:注册定义解析。 - `examples/types/toolpkg.d.ts`:公开 payload、定义和返回类型。 相关页面:[ToolPkg 注册 API](../03_runtime/registry.md)、[Compose DSL](../06_ui_and_compose/compose_dsl.md)、[Hook 总索引](./index.md)。 \ No newline at end of file diff --git a/docs/doc-src/toolpkg_developer_documentation/05_hooks/tool_lifecycle.md b/docs/doc-src/toolpkg_developer_documentation/05_hooks/tool_lifecycle.md index 94f705b97c..d81fb91e3e 100644 --- a/docs/doc-src/toolpkg_developer_documentation/05_hooks/tool_lifecycle.md +++ b/docs/doc-src/toolpkg_developer_documentation/05_hooks/tool_lifecycle.md @@ -104,7 +104,7 @@ ToolPkg.registerToolLifecycleHook({ ## 实现依据 - `plugins/toolpkg/ToolPkgToolLifecycleBridge.kt`:事件构造、队列投递、拦截返回解析和 fail-closed 行为。 -- `core/tools/AIToolHook.kt`、`AIToolHandler.kt`:拦截发生在权限检查与 executor 激活前。 +- `core/tools/runtime/AIToolHook.kt`、`AIToolHandler.kt`:拦截发生在权限检查与 executor 激活前。 - `examples/types/toolpkg.d.ts`:当前声明形状。 相关页面:[ToolPkg 注册 API](../03_runtime/registry.md)、[Hook 总索引](./index.md)、[接口覆盖索引](../09_compatibility/coverage.md)。 diff --git a/docs/doc-src/toolpkg_developer_documentation/09_compatibility/api_versions.md b/docs/doc-src/toolpkg_developer_documentation/09_compatibility/api_versions.md index 166400779f..8e25e982a1 100644 --- a/docs/doc-src/toolpkg_developer_documentation/09_compatibility/api_versions.md +++ b/docs/doc-src/toolpkg_developer_documentation/09_compatibility/api_versions.md @@ -74,8 +74,8 @@ status: complete ## 权威实现 -- `app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiVersion.kt` -- `app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgParser.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiVersion.kt` +- `app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsEngine.kt` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolPkgApiRuntime.kt` - `app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolPkgRegistration.kt` diff --git a/docs/doc-src/toolpkg_developer_documentation/index.md b/docs/doc-src/toolpkg_developer_documentation/index.md index d6287da3c9..9fecb80a5c 100644 --- a/docs/doc-src/toolpkg_developer_documentation/index.md +++ b/docs/doc-src/toolpkg_developer_documentation/index.md @@ -75,8 +75,8 @@ ToolPkg API 版本表示包所依赖的宿主接口契约,独立于包自身 - 全局声明与导出入口:[`examples/types/index.d.ts`](../../../examples/types/index.d.ts) - ToolPkg 注册、Hook、IPC 和 WASM 类型:[`examples/types/toolpkg.d.ts`](../../../examples/types/toolpkg.d.ts) - 各模块声明:[`examples/types/`](../../../examples/types/) -- 包 Manifest 与解析行为:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgParser.kt` -- API 版本支持策略:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgApiVersion.kt` +- 包 Manifest 与解析行为:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt` +- API 版本支持策略:`app/src/main/java/com/ai/assistance/operit/core/tools/packTool/metadata/ToolPkgApiVersion.kt` - JS 侧版本门禁与 ToolPkg facade:`app/src/main/java/com/ai/assistance/operit/core/tools/javascript/JsToolPkgApiRuntime.kt`、`JsToolPkgRegistration.kt` - Hook 触发及结果消费:`app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/` diff --git a/tools/adb/JS_ADB_README.md b/tools/adb/JS_ADB_README.md index 3bd22c348b..ac6d8b909c 100644 --- a/tools/adb/JS_ADB_README.md +++ b/tools/adb/JS_ADB_README.md @@ -51,7 +51,7 @@ This makes them suitable for: ## JS Test Suites In This Repo -The directory [app/src/androidTest/js](/d:/Code/prog/assistance/app/src/androidTest/js) contains real JS runtime tests and probes, including: +The directory [app/src/androidTest/js](../../app/src/androidTest/js) contains real JS runtime tests and probes, including: - bridge contract tests - bridge edge-case tests @@ -61,11 +61,11 @@ The directory [app/src/androidTest/js](/d:/Code/prog/assistance/app/src/androidT Representative locations: -- [app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_contract](/d:/Code/prog/assistance/app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_contract) -- [app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_edges](/d:/Code/prog/assistance/app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_edges) -- [app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/script_mode_contract](/d:/Code/prog/assistance/app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/script_mode_contract) -- [app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/main.js](/d:/Code/prog/assistance/app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/main.js) -- [app/src/androidTest/js/com/ai/assistance/operit/util/ttscleaner/ttscleaner.js](/d:/Code/prog/assistance/app/src/androidTest/js/com/ai/assistance/operit/util/ttscleaner/ttscleaner.js) +- [app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_contract](../../app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_contract) +- [app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_edges](../../app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_edges) +- [app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/script_mode_contract](../../app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/script_mode_contract) +- [app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/main.js](../../app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/main.js) +- [app/src/androidTest/js/com/ai/assistance/operit/util/ttscleaner/ttscleaner.js](../../app/src/androidTest/js/com/ai/assistance/operit/util/ttscleaner/ttscleaner.js) ## Quick Choice @@ -134,7 +134,7 @@ More realistic examples: ```cmd tools\adb\execute_js_dir.bat app\src\androidTest\js com\ai\assistance\operit\core\tools\javascript\bridge_contract\bridge_contract_runner.js run @params.json -tools\adb\execute_js_dir.bat app\src\androidTest\js com\ai\assistance\operit\core\tools\defaultTool\standard\browser\main.js run "{}" +tools\adb\execute_js_dir.bat app\src\androidTest\js com\ai\assistance\operit\core\tools\builtin\web\browser\main.js run "{}" ``` You can still pass inline JSON directly. The scripts now write that JSON into a temporary file and push it to the device, which avoids the old `adb shell am broadcast --es params ...` quoting breakage. On PowerShell, prefer single-quoted JSON like `'{"param1":"value1"}'` or use `@params.json`. @@ -400,7 +400,7 @@ This is best for: ### 2. Add a directory-based runtime test -If the test needs multiple local modules, put it under [app/src/androidTest/js](/d:/Code/prog/assistance/app/src/androidTest/js) and organize it as a small directory-based suite. +If the test needs multiple local modules, put it under [app/src/androidTest/js](../../app/src/androidTest/js) and organize it as a small directory-based suite. Recommended shape: diff --git a/tools/adb/JS_ADB_README_zh.md b/tools/adb/JS_ADB_README_zh.md index 6239f145a0..94f7d2083c 100644 --- a/tools/adb/JS_ADB_README_zh.md +++ b/tools/adb/JS_ADB_README_zh.md @@ -66,7 +66,7 @@ ## 真实测试资产 -仓库里的 [app/src/androidTest/js](/d:/Code/prog/assistance/app/src/androidTest/js) 不是普通示例目录,而是这套工具的重要使用场景之一。 +仓库里的 [app/src/androidTest/js](../../app/src/androidTest/js) 不是普通示例目录,而是这套工具的重要使用场景之一。 其中包括: @@ -78,11 +78,11 @@ 典型目录: -- [bridge_contract](/d:/Code/prog/assistance/app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_contract) -- [bridge_edges](/d:/Code/prog/assistance/app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_edges) -- [script_mode_contract](/d:/Code/prog/assistance/app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/script_mode_contract) -- [browser main.js](/d:/Code/prog/assistance/app/src/androidTest/js/com/ai/assistance/operit/core/tools/defaultTool/standard/browser/main.js) -- [ttscleaner.js](/d:/Code/prog/assistance/app/src/androidTest/js/com/ai/assistance/operit/util/ttscleaner/ttscleaner.js) +- [bridge_contract](../../app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_contract) +- [bridge_edges](../../app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/bridge_edges) +- [script_mode_contract](../../app/src/androidTest/js/com/ai/assistance/operit/core/tools/javascript/script_mode_contract) +- [browser main.js](../../app/src/androidTest/js/com/ai/assistance/operit/core/tools/builtin/web/browser/main.js) +- [ttscleaner.js](../../app/src/androidTest/js/com/ai/assistance/operit/util/ttscleaner/ttscleaner.js) ## 先记结论 @@ -120,7 +120,7 @@ Windows: ```cmd tools\adb\execute_js_dir.bat app\src\androidTest\js com\ai\assistance\operit\core\tools\javascript\bridge_contract\bridge_contract_runner.js run @params.json -tools\adb\execute_js_dir.bat app\src\androidTest\js com\ai\assistance\operit\core\tools\defaultTool\standard\browser\main.js run "{}" +tools\adb\execute_js_dir.bat app\src\androidTest\js com\ai\assistance\operit\core\tools\builtin\web\browser\main.js run "{}" ``` Linux/macOS: @@ -338,7 +338,7 @@ d:\Code\prog\assistance\.venv\Scripts\python.exe d:\Code\prog\assistance\tools\e ### 2. 加目录化运行时测试 -如果你的测试会引用多个本地模块,建议直接放到 [app/src/androidTest/js](/d:/Code/prog/assistance/app/src/androidTest/js) 下面,按一个小目录来组织。 +如果你的测试会引用多个本地模块,建议直接放到 [app/src/androidTest/js](../../app/src/androidTest/js) 下面,按一个小目录来组织。 推荐组织方式: @@ -555,8 +555,8 @@ exports.myFunction = myFunction; 相关接收器: -- [ScriptExecutionReceiver.kt](/d:/Code/prog/assistance/app/src/main/java/com/ai/assistance/operit/core/tools/javascript/ScriptExecutionReceiver.kt) -- [ToolPkgDebugInstallReceiver.kt](/d:/Code/prog/assistance/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgDebugInstallReceiver.kt) +- [ScriptExecutionReceiver.kt](../../app/src/main/java/com/ai/assistance/operit/core/tools/javascript/ScriptExecutionReceiver.kt) +- [ToolPkgDebugInstallReceiver.kt](../../app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgDebugInstallReceiver.kt) ## 故障排查 diff --git a/tools/package_layout/verify_layout_completion.py b/tools/package_layout/verify_layout_completion.py index 4557eba51a..cdf6b9a0c7 100644 --- a/tools/package_layout/verify_layout_completion.py +++ b/tools/package_layout/verify_layout_completion.py @@ -133,7 +133,7 @@ def main(): native_files = [path for path in tree if path.endswith(('.aidl', '.cpp', '.h', '.rs'))] for path in native_files: require(blob_hash((ROOT / path).read_bytes()) == tree[path][1], 'JNI 或 Binder 协议文件发生变化:' + path) - parser_text = (ROOT / 'app/src/main/java/com/ai/assistance/operit/core/tools/packTool/ToolPkgMainRegistrationScriptParser.kt').read_text() + parser_text = (ROOT / 'app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgMainRegistrationScriptParser.kt').read_text() require(parser_text.count('item.optString("runtime").trim().ifBlank { TOOLPKG_RUNTIME_COMPOSE_DSL }') == 2, '界面模块或路由的默认 Compose DSL 被修改') require('return@forEachIndexed' in parser_text, '旧导航声明未忽略') result = { diff --git a/tools/string/count_ui_strings.py b/tools/string/count_ui_strings.py index 38071d38bc..03379a3ec1 100644 --- a/tools/string/count_ui_strings.py +++ b/tools/string/count_ui_strings.py @@ -38,7 +38,7 @@ '\\ui\\features\\settings\\screens\\TagMarketBilingualData.kt', '\\data\\preferences\\CharacterCardBilingualData.kt', '\\data\\preferences\\PromptBilingualData.kt', - '\\core\\tools\\defaultTool\\standard\\StandardUITools.kt' + '\\core\\tools\\builtin\\ui\\StandardUITools.kt' ] def _should_skip_file(file_path: Path) -> bool: From cf31c7c74c255cd1d314d95ef7d7b9b43a23cfaa Mon Sep 17 00:00:00 2001 From: kong <135376906+3316891527@users.noreply.github.com> Date: Thu, 29 Oct 2026 12:51:17 +0000 Subject: [PATCH 3/7] =?UTF-8?q?fix(tools):=20=E8=A1=A5=E9=BD=90=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=99=A8=E5=AD=97=E7=AC=A6=E4=B8=B2=E6=8F=92=E5=80=BC?= =?UTF-8?q?=E5=B8=B8=E9=87=8F=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ToolPkgMainRegistrationScriptParser.kt | 5 +++++ .../tools/packTool/parser/ToolPkgParser.kt | 22 +++++++++++++++++++ .../tools-permissions-layout/verification.md | 3 ++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgMainRegistrationScriptParser.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgMainRegistrationScriptParser.kt index c842002f6f..dc18a0f981 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgMainRegistrationScriptParser.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgMainRegistrationScriptParser.kt @@ -6,13 +6,16 @@ import com.ai.assistance.operit.util.logging.AppLogger import org.json.JSONArray import org.json.JSONObject import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_AI_PROVIDER +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_APP_LIFECYCLE_HOOK import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_INPUT_HOOK import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_MESSAGE_HOOK import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_MESSAGE_MENU_ITEM import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_RUNTIME_HOOK import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_VIEW_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_DESKTOP_WIDGET import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_INPUT_MENU_TOGGLE_PLUGIN import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_MESSAGE_PROCESSING_PLUGIN +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_NAVIGATION_ENTRY import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_ESTIMATE_FINALIZE_HOOK import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_ESTIMATE_HISTORY_HOOK import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_FINALIZE_HOOK @@ -22,6 +25,8 @@ import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATIO import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_SYSTEM_PROMPT_COMPOSE_HOOK import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_TOOL_LIFECYCLE_HOOK import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_TOOL_PROMPT_COMPOSE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_UI_MODULE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_UI_ROUTE import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_XML_RENDER_PLUGIN import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_RUNTIME_COMPOSE_DSL import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgMarketOriginCodec diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt index fd31dfa42c..2c191fd16d 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/parser/ToolPkgParser.kt @@ -18,6 +18,28 @@ import kotlinx.serialization.json.JsonPrimitive import org.hjson.JsonValue import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_NAV_SURFACE_MAIN_SIDEBAR_PLUGINS import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_NAV_SURFACE_PACKAGE_DETAILS +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_AI_PROVIDER +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_APP_LIFECYCLE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_INPUT_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_MESSAGE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_MESSAGE_MENU_ITEM +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_RUNTIME_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_CHAT_VIEW_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_DESKTOP_WIDGET +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_INPUT_MENU_TOGGLE_PLUGIN +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_MESSAGE_PROCESSING_PLUGIN +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_NAVIGATION_ENTRY +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_ESTIMATE_FINALIZE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_ESTIMATE_HISTORY_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_FINALIZE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_HISTORY_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_PROMPT_INPUT_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_SUMMARY_GENERATE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_SYSTEM_PROMPT_COMPOSE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_TOOL_LIFECYCLE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_TOOL_PROMPT_COMPOSE_HOOK +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_UI_ROUTE +import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_REGISTRATION_XML_RENDER_PLUGIN import com.ai.assistance.operit.core.tools.packTool.metadata.TOOLPKG_RUNTIME_COMPOSE_DSL import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgApiCompatibility import com.ai.assistance.operit.core.tools.packTool.metadata.ToolPkgManifestRequirement diff --git a/docs/TODO/chore/tools-permissions-layout/verification.md b/docs/TODO/chore/tools-permissions-layout/verification.md index fe438ca2da..13a02bf7cb 100644 --- a/docs/TODO/chore/tools-permissions-layout/verification.md +++ b/docs/TODO/chore/tools-permissions-layout/verification.md @@ -1,12 +1,13 @@ # 验证记录 -本次交付分为权限实现收口和工具目录迁移两个提交。目录迁移以 [files.json](files.json) 为依据,当前共 117 个文件,其中迁移 111 个,保留 6 个。 +本次交付分为权限实现收口和工具目录迁移两部分。目录迁移以 [files.json](files.json) 为依据,当前共 117 个文件,其中迁移 111 个,保留 6 个。 ## 静态核对 - 权限收口逐项比较 61 个原操作体及辅助方法,以及 17 个管理员文件操作路由,保留原操作实现和只读标记 - 目录迁移比较 264 份受影响 Kotlin 文件的声明内容,除包名、导入和清单对应的显式路径引用外未发现其他变化 - 核对清单全部目标文件、目标包名、迁移符号导入及工具导入名称冲突 +- 共享注册常量的跨包导入同时覆盖普通引用和字符串插值,保留注册校验及错误提示的现有内容 - 静态语法扫描未发现新增问题;最终类型检查与编译结果以仓库工作流为准 - 核对变更 XML、Python 语法、Markdown 本地链接与 Git 差异空白 - 安装、刷新与 UI DSL 调试广播保持原公开组件名,现有 ADB 和编辑器调用仍使用原入口 From 528a8070cb29774133234c353949943b79e640a5 Mon Sep 17 00:00:00 2001 From: kong <135376906+3316891527@users.noreply.github.com> Date: Thu, 29 Oct 2026 13:26:47 +0000 Subject: [PATCH 4/7] =?UTF-8?q?fix(tests):=20=E4=BF=AE=E5=A4=8D=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E5=8D=A1=E7=89=87=E6=B5=8B=E8=AF=95=20XML=20=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E4=B8=B2=E5=BC=95=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/markdown/ToolCardStreamBoundaryAndroidTest.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/androidTest/java/com/ai/assistance/operit/ui/common/markdown/ToolCardStreamBoundaryAndroidTest.kt b/app/src/androidTest/java/com/ai/assistance/operit/ui/common/markdown/ToolCardStreamBoundaryAndroidTest.kt index 164e8cba38..be8e2e9389 100644 --- a/app/src/androidTest/java/com/ai/assistance/operit/ui/common/markdown/ToolCardStreamBoundaryAndroidTest.kt +++ b/app/src/androidTest/java/com/ai/assistance/operit/ui/common/markdown/ToolCardStreamBoundaryAndroidTest.kt @@ -24,8 +24,9 @@ class ToolCardStreamBoundaryAndroidTest { @get:Rule val composeRule = createComposeRule() private fun chars(text: String): Stream = stream { text.forEach { emit(it) } } + // XML 属性含双引号,使用原始字符串避免测试样例被误解析为 Kotlin 代码。 private fun tool(value: String): String = - "$value" + """$value""" private fun render(prefix: String?, tail: String): StreamMarkdownRendererState { val state = StreamMarkdownRendererState() @@ -52,13 +53,13 @@ class ToolCardStreamBoundaryAndroidTest { @Test fun closedToolPrefixKeepsFollowingRequestAndResultSeparate() { val first = tool("首次") - val result = "已创建" + val result = """已创建""" val next = tool("第二次") assertBlocks(render(first, result + next), listOf(first, result, next)) } @Test fun unfinishedToolContinuesOnceAndNewToolsStartNewCards() { - val prefix = "开始" + val prefix = """开始""" val close = "继续" val next = listOf(tool("第二次"), tool("第三次")) assertBlocks(render(prefix, close + next.joinToString("")), listOf(prefix + close) + next) @@ -96,7 +97,7 @@ class ToolCardStreamBoundaryAndroidTest { } @Test fun xmlReplayIncludesRestoredPrefixAndEndsBeforeMessageCompletion() { - val prefix = "开始" + val prefix = """开始""" val body = "继续" val end = "" val source = MutableSharedStreamImpl(replay = Int.MAX_VALUE) From a9dd831752956dd68fb2edb1395683e47f8a08ff Mon Sep 17 00:00:00 2001 From: kong <135376906+3316891527@users.noreply.github.com> Date: Thu, 29 Oct 2026 16:01:27 +0000 Subject: [PATCH 5/7] =?UTF-8?q?fix(workspace):=20=E6=B5=81=E5=BC=8F?= =?UTF-8?q?=E5=A4=8D=E5=88=B6=E6=96=87=E4=BB=B6=E5=B9=B6=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E7=B2=98=E8=B4=B4=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/files/transfer/FileCopyObservers.kt | 21 ++ .../core/files/transfer/LocalTransferPaths.kt | 27 +++ .../core/files/transfer/StreamingFileCopy.kt | 182 ++++++++++++++++++ .../standard/StandardFileSystemTools.kt | 94 ++++++--- .../chat/webview/workspace/FileManager.kt | 20 +- .../browser/WorkspaceBrowserOperations.kt | 98 +++++++--- .../browser/transfer/WorkspaceCopyProgress.kt | 16 ++ .../transfer/WorkspaceCopyProgressDialog.kt | 102 ++++++++++ .../values-en/strings_workspace_transfer.xml | 18 ++ .../values-es/strings_workspace_transfer.xml | 18 ++ .../values-id/strings_workspace_transfer.xml | 18 ++ .../values-ja/strings_workspace_transfer.xml | 18 ++ .../values-ko/strings_workspace_transfer.xml | 18 ++ .../values-ms/strings_workspace_transfer.xml | 18 ++ .../strings_workspace_transfer.xml | 18 ++ .../values-ro/strings_workspace_transfer.xml | 18 ++ .../res/values/strings_workspace_transfer.xml | 18 ++ .../files/transfer/StreamingFileCopyTest.kt | 176 +++++++++++++++++ docs/TODO/fix/README.md | 2 + .../01-validation.md | 61 ++++++ .../index.md | 25 +++ 21 files changed, 930 insertions(+), 56 deletions(-) create mode 100644 app/src/main/java/com/ai/assistance/operit/core/files/transfer/FileCopyObservers.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/core/files/transfer/LocalTransferPaths.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/core/files/transfer/StreamingFileCopy.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgress.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt create mode 100644 app/src/main/res/values-en/strings_workspace_transfer.xml create mode 100644 app/src/main/res/values-es/strings_workspace_transfer.xml create mode 100644 app/src/main/res/values-id/strings_workspace_transfer.xml create mode 100644 app/src/main/res/values-ja/strings_workspace_transfer.xml create mode 100644 app/src/main/res/values-ko/strings_workspace_transfer.xml create mode 100644 app/src/main/res/values-ms/strings_workspace_transfer.xml create mode 100644 app/src/main/res/values-pt-rBR/strings_workspace_transfer.xml create mode 100644 app/src/main/res/values-ro/strings_workspace_transfer.xml create mode 100644 app/src/main/res/values/strings_workspace_transfer.xml create mode 100644 app/src/test/java/com/ai/assistance/operit/core/files/transfer/StreamingFileCopyTest.kt create mode 100644 docs/TODO/fix/workspace-copy-streaming-progress/01-validation.md create mode 100644 docs/TODO/fix/workspace-copy-streaming-progress/index.md diff --git a/app/src/main/java/com/ai/assistance/operit/core/files/transfer/FileCopyObservers.kt b/app/src/main/java/com/ai/assistance/operit/core/files/transfer/FileCopyObservers.kt new file mode 100644 index 0000000000..26eb2d20ce --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/core/files/transfer/FileCopyObservers.kt @@ -0,0 +1,21 @@ +package com.ai.assistance.operit.core.files.transfer + +import java.util.UUID +import java.util.concurrent.ConcurrentHashMap + +internal class FileCopyObserver( + val onProgress: (FileCopyProgress) -> Unit, + val checkCancelled: () -> Unit, +) + +/** 工具执行跨越同步入口和 IO 协程;用一次性令牌关联进度,避免并行粘贴串到同一个全局状态。 */ +internal object FileCopyObservers { + const val PARAMETER = "__workspace_copy_id" + private val observers = ConcurrentHashMap() + + fun register(observer: FileCopyObserver): String = UUID.randomUUID().toString().also { observers[it] = observer } + + fun find(id: String?): FileCopyObserver? = id?.let(observers::get) + + fun remove(id: String) { observers.remove(id) } +} \ No newline at end of file diff --git a/app/src/main/java/com/ai/assistance/operit/core/files/transfer/LocalTransferPaths.kt b/app/src/main/java/com/ai/assistance/operit/core/files/transfer/LocalTransferPaths.kt new file mode 100644 index 0000000000..a439abc5e1 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/core/files/transfer/LocalTransferPaths.kt @@ -0,0 +1,27 @@ +package com.ai.assistance.operit.core.files.transfer + +import android.content.Context +import com.ai.assistance.operit.terminal.provider.filesystem.PRootMountMapping +import java.io.File + +/** 与终端共用软挂载映射,不能把 /sdcard 简单拼接到 Ubuntu rootfs 下。 */ +internal object LocalTransferPaths { + fun resolve(context: Context, path: String, environment: String): File { + if (environment.equals("android", ignoreCase = true)) return File(path) + require(environment.equals("linux", ignoreCase = true)) { "Not a local file environment: $environment" } + val expanded = when { + path == "~" -> "/root" + path.startsWith("~/") -> "/root/" + path.substring(2) + else -> path + } + return File(PRootMountMapping.mapLinuxPathToHostPath( + linuxPath = expanded, + ubuntuRoot = File(context.filesDir, "usr/var/lib/proot-distro/installed-rootfs/ubuntu"), + homeDir = context.filesDir.absolutePath, + appDataDir = context.applicationInfo.dataDir, + packageName = context.packageName, + chrootEnabled = context.getSharedPreferences("terminal_settings", Context.MODE_PRIVATE) + .getBoolean("chroot_enabled", false), + )) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ai/assistance/operit/core/files/transfer/StreamingFileCopy.kt b/app/src/main/java/com/ai/assistance/operit/core/files/transfer/StreamingFileCopy.kt new file mode 100644 index 0000000000..acbb488d56 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/core/files/transfer/StreamingFileCopy.kt @@ -0,0 +1,182 @@ +package com.ai.assistance.operit.core.files.transfer + +import java.io.File +import java.io.IOException +import java.nio.file.FileAlreadyExistsException +import java.nio.file.FileVisitResult +import java.nio.file.Files +import java.nio.file.LinkOption +import java.nio.file.Path +import java.nio.file.OpenOption +import java.nio.file.SimpleFileVisitor +import java.nio.file.StandardCopyOption +import java.nio.file.StandardOpenOption +import java.nio.file.attribute.BasicFileAttributes + +internal enum class FileCopyPhase { SCANNING, COPYING, COMPLETED } + +internal data class FileCopyProgress( + val phase: FileCopyPhase, + val currentFile: String, + val copiedBytes: Long, + val totalBytes: Long?, + val copiedFiles: Long, + val totalFiles: Long, + val bytesPerSecond: Double?, +) { + val fraction: Float? + get() = when { + phase == FileCopyPhase.COMPLETED -> 1f + phase == FileCopyPhase.SCANNING || totalBytes == null -> null + totalBytes > 0 -> (copiedBytes.toDouble() / totalBytes).toFloat().coerceIn(0f, 0.999f) + totalFiles > 0 -> (copiedFiles.toDouble() / totalFiles).toFloat().coerceIn(0f, 0.999f) + else -> 0f + } + + val remainingBytes: Long? + get() = totalBytes?.let { (it - copiedBytes).coerceAtLeast(0L) } +} + +/** 两次逐层遍历分别统计和复制,不缓存整棵目录树,也不将文件内容转成字符串。 */ +internal object StreamingFileCopy { + const val BUFFER_SIZE = 256 * 1024 + private const val REPORT_INTERVAL_NANOS = 200_000_000L + private const val SPEED_WINDOW_NANOS = 500_000_000L + + fun copy( + source: File, + destination: File, + recursive: Boolean = true, + overwrite: Boolean = false, + onProgress: (FileCopyProgress) -> Unit = {}, + checkCancelled: () -> Unit = {}, + ): FileCopyProgress { + val sourcePath = source.absoluteFile.toPath().normalize() + val destinationPath = destination.absoluteFile.toPath().normalize() + val attributes = Files.readAttributes(sourcePath, BasicFileAttributes::class.java, LinkOption.NOFOLLOW_LINKS) + val realSource = source.canonicalFile.toPath() + val realDestination = destination.canonicalFile.toPath() + require(realSource != realDestination && (!attributes.isDirectory || !realDestination.startsWith(realSource))) { + "Cannot copy a path onto itself or into its own directory" + } + require(recursive || !attributes.isDirectory) { "Cannot copy a directory without recursive=true" } + if (!overwrite && Files.exists(destinationPath, LinkOption.NOFOLLOW_LINKS)) { + throw FileAlreadyExistsException(destination.path) + } + + var phase = FileCopyPhase.SCANNING + var currentFile = source.name + var totalBytes = 0L + var totalFiles = 0L + var copiedBytes = 0L + var copiedFiles = 0L + var lastReportedAt = System.nanoTime() + var windowStartedAt = lastReportedAt + var windowStartedBytes = 0L + var speed: Double? = null + + fun report(force: Boolean = false): FileCopyProgress? { + checkCancelled() + val now = System.nanoTime() + if (phase == FileCopyPhase.COPYING && now - windowStartedAt >= SPEED_WINDOW_NANOS) { + speed = (copiedBytes - windowStartedBytes) * 1_000_000_000.0 / (now - windowStartedAt) + windowStartedAt = now + windowStartedBytes = copiedBytes + } + if (!force && now - lastReportedAt < REPORT_INTERVAL_NANOS) return null + lastReportedAt = now + return FileCopyProgress( + phase, currentFile, copiedBytes, + totalBytes.takeUnless { phase == FileCopyPhase.SCANNING }, totalFiles = totalFiles, + copiedFiles = copiedFiles, bytesPerSecond = speed, + ).also(onProgress) + } + + fun select(path: Path) { + checkCancelled() + currentFile = sourcePath.relativize(path).toString().ifEmpty { source.name } + } + + report(force = true) + Files.walkFileTree(sourcePath, object : SimpleFileVisitor() { + override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult { + select(dir) + report() + return FileVisitResult.CONTINUE + } + + override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult { + select(file) + require(attrs.isRegularFile || attrs.isSymbolicLink) { "Unsupported file type: $file" } + totalFiles = Math.addExact(totalFiles, 1L) + if (attrs.isRegularFile) totalBytes = Math.addExact(totalBytes, attrs.size()) + report() + return FileVisitResult.CONTINUE + } + }) + + phase = FileCopyPhase.COPYING + windowStartedAt = System.nanoTime() + windowStartedBytes = 0L + report(force = true) + if (attributes.isDirectory && !overwrite) { + destinationPath.parent?.let { Files.createDirectories(it) } + // 原子创建顶层目标,统计期间出现同名目录时也不能合并写入。 + Files.createDirectory(destinationPath) + } + // 整个任务复用这一块缓冲区,内存占用不随文件大小或文件数量增长。 + val buffer = ByteArray(BUFFER_SIZE) + Files.walkFileTree(sourcePath, object : SimpleFileVisitor() { + private fun target(path: Path): Path = destinationPath.resolve(sourcePath.relativize(path)) + + override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult { + select(dir) + Files.createDirectories(target(dir)) + report() + return FileVisitResult.CONTINUE + } + + override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult { + select(file) + val target = target(file) + target.parent?.let { Files.createDirectories(it) } + if (attrs.isSymbolicLink) { + // 不遍历链接目标,避免目录环和将链接指向的外部目录一并复制。 + if (overwrite) Files.copy(file, target, LinkOption.NOFOLLOW_LINKS, StandardCopyOption.REPLACE_EXISTING) + else Files.copy(file, target, LinkOption.NOFOLLOW_LINKS) + } else { + require(attrs.isRegularFile) { "Unsupported file type: $file" } + val options = if (overwrite) { + arrayOf(StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE, LinkOption.NOFOLLOW_LINKS) + } else { + arrayOf(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE, LinkOption.NOFOLLOW_LINKS) + } + var fileBytes = 0L + Files.newInputStream(file, LinkOption.NOFOLLOW_LINKS).use { input -> + Files.newOutputStream(target, *options).use { output -> + while (true) { + checkCancelled() + val count = input.read(buffer) + if (count < 0) break + if (count == 0) continue + output.write(buffer, 0, count) + fileBytes += count + copiedBytes += count + report() + } + } + } + if (fileBytes != attrs.size()) throw IOException("Source size changed while copying: $file") + } + copiedFiles++ + report() + return FileVisitResult.CONTINUE + } + }) + if (copiedBytes != totalBytes || copiedFiles != totalFiles) { + throw IOException("Source directory changed while copying: $source") + } + phase = FileCopyPhase.COMPLETED + return checkNotNull(report(force = true)) + } +} diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.kt index 59f36e65c8..9b36d9c790 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.kt @@ -1,6 +1,13 @@ package com.ai.assistance.operit.core.tools.defaultTool.standard import android.content.Context +import com.ai.assistance.operit.core.files.transfer.FileCopyObserver +import com.ai.assistance.operit.core.files.transfer.FileCopyObservers +import com.ai.assistance.operit.core.files.transfer.LocalTransferPaths +import com.ai.assistance.operit.core.files.transfer.StreamingFileCopy +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive import com.ai.assistance.operit.R import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.api.chat.EnhancedAIService @@ -2417,30 +2424,52 @@ open class StandardFileSystemTools(protected val context: Context) { } } - /** Helper method to recursively copy a directory */ - private fun copyDirectory(sourceDir: File, destDir: File): Boolean { - try { - if (!destDir.exists()) { - destDir.mkdirs() - } - - sourceDir.listFiles()?.forEach { file -> - val destFile = File(destDir, file.name) - if (file.isDirectory) { - copyDirectory(file, destFile) - } else { - file.inputStream().use { input -> - destFile.outputStream().use { output -> - input.copyTo(output) - } - } - } - } + /** 目录内任一项失败都必须失败,避免移动操作在不完整复制后删除来源。 */ + private fun copyDirectory(sourceDir: File, destDir: File): Boolean = try { + StreamingFileCopy.copy(sourceDir, destDir, overwrite = true) + true + } catch (e: Exception) { + AppLogger.e(TAG, "Error copying directory", e) + false + } - return true + /** 本机复制直接连接两个文件流,保持二进制内容并提供任务独立的进度。 */ + private suspend fun copyLocalFile( + toolName: String, + sourcePath: String, + destPath: String, + sourceEnvironment: String, + destEnvironment: String, + recursive: Boolean, + observer: FileCopyObserver?, + ): ToolResult = withContext(Dispatchers.IO) { + try { + val executionContext = currentCoroutineContext() + val progress = StreamingFileCopy.copy( + source = LocalTransferPaths.resolve(context, sourcePath, sourceEnvironment), + destination = LocalTransferPaths.resolve(context, destPath, destEnvironment), + recursive = recursive, + overwrite = observer == null, + onProgress = { observer?.onProgress?.invoke(it) }, + checkCancelled = { + executionContext.ensureActive() + observer?.checkCancelled?.invoke() + }, + ) + ToolResult( + toolName = toolName, + success = true, + result = FileOperationData(operation = "copy", path = sourcePath, successful = true, + details = "Copied $sourceEnvironment:$sourcePath to $destEnvironment:$destPath (${progress.copiedBytes} bytes)"), + error = "", + ) + } catch (e: CancellationException) { + throw e } catch (e: Exception) { - AppLogger.e(TAG, "Error copying directory", e) - return false + AppLogger.e(TAG, "Error streaming local file copy", e) + ToolResult(toolName = toolName, success = false, + result = FileOperationData(operation = "copy", path = sourcePath, successful = false, details = e.message.orEmpty()), + error = "Failed to copy $sourcePath: ${e.message}") } } @@ -2704,7 +2733,7 @@ open class StandardFileSystemTools(protected val context: Context) { if (result.success) { copiedDirs++ } else { - AppLogger.w(TAG, "Failed to copy directory: $srcFullPath") + return result } } else { val result = copyFileCrossEnvironment( @@ -2718,7 +2747,7 @@ open class StandardFileSystemTools(protected val context: Context) { if (result.success) { copiedFiles++ } else { - AppLogger.w(TAG, "Failed to copy file: $srcFullPath") + return result } } } @@ -2799,6 +2828,23 @@ open class StandardFileSystemTools(protected val context: Context) { ) } + val observer = FileCopyObservers.find(tool.parameters.find { it.name == FileCopyObservers.PARAMETER }?.value) + val localEnvironments = listOf(srcEnv, dstEnv).all { + it.equals("android", ignoreCase = true) || it.equals("linux", ignoreCase = true) + } + val usesLinux = isLinuxEnvironment(srcEnv) || isLinuxEnvironment(dstEnv) + // 按实际后端选择传输:SSH 保持远程提供方,本机路径使用终端相同的软挂载映射。 + if (localEnvironments && (!usesLinux || !isSshFileSystemActive()) && + (usesLinux || observer != null)) { + if (!isLinuxEnvironment(srcEnv)) { + PathValidator.validateAndroidPath(sourcePath, tool.name, "source")?.let { return it } + } + if (!isLinuxEnvironment(dstEnv)) { + PathValidator.validateAndroidPath(destPath, tool.name, "destination")?.let { return it } + } + return copyLocalFile(tool.name, sourcePath, destPath, srcEnv, dstEnv, recursive, observer) + } + // 检查是否是跨环境复制 val isCrossEnvironment = srcEnv.lowercase() != dstEnv.lowercase() diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt index 3181112a10..2d60b018af 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt @@ -68,6 +68,7 @@ import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace. import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.text.readWorkspaceTextWithinLimit import com.ai.assistance.operit.util.files.FileUtils import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.* +import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer.WorkspaceCopyProgressDialog import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserClipboard import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserClipboardItem import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserContextMenu @@ -114,6 +115,8 @@ fun FileBrowser( var currentEnvironment by rememberSaveable(initialPath, environment) { mutableStateOf(environment) } var fileList by remember { mutableStateOf>(emptyList()) } var isOperationLoading by remember { mutableStateOf(false) } + var fileOperationJob by remember { mutableStateOf(null) } + var cancellingFileOperation by remember { mutableStateOf(false) } var isDirectoryLoading by remember { mutableStateOf(false) } var directoryLoadJob by remember { mutableStateOf(null) } var directoryLoadVersion by remember { mutableIntStateOf(0) } @@ -143,6 +146,7 @@ fun FileBrowser( val listState = rememberLazyListState() val operations = remember(context) { FileBrowserOperations(context) } val clipboard by FileBrowserClipboard.content.collectAsState() + val copyProgress by operations.copyProgress.collectAsState() var showSortMenu by remember { mutableStateOf(false) } var selectionMode by rememberSaveable(currentPath, currentEnvironment) { mutableStateOf(false) } var selectedNames by rememberSaveable(currentPath, currentEnvironment) { mutableStateOf(emptySet()) } @@ -450,7 +454,8 @@ fun FileBrowser( fun runOperation(block: suspend () -> Unit) { if (isLoading) return isOperationLoading = true - coroutineScope.launch { + cancellingFileOperation = false + fileOperationJob = coroutineScope.launch { try { block() errorMessage = null @@ -461,8 +466,9 @@ fun FileBrowser( errorMessage = e.message } finally { isOperationLoading = false + fileOperationJob = null + loadDirectory(currentPath) } - loadDirectory(currentPath) } } @@ -658,6 +664,14 @@ fun FileBrowser( }) { Text(stringResource(R.string.workspace_open_external)) } } }, confirmButton = {}) } + copyProgress?.let { progress -> + key(progress.sourceEnvironment, progress.source, progress.destinationEnvironment, progress.destination) { + WorkspaceCopyProgressDialog(progress, cancelling = cancellingFileOperation, onCancel = { + cancellingFileOperation = true + fileOperationJob?.cancel() + }) + } + } propertiesTarget?.let { target -> WorkspacePropertiesDialog(target, onDismiss = { propertiesTarget = null }, @@ -891,7 +905,7 @@ fun FileBrowser( } // 文件列表 - if (isLoading) { + if (isLoading && copyProgress == null) { Box( modifier = Modifier.fillMaxSize().weight(1f), contentAlignment = Alignment.Center diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt index 40de9edb8d..765626d03c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt @@ -5,6 +5,13 @@ import android.content.Intent import android.util.Base64 import androidx.core.content.FileProvider import com.ai.assistance.operit.R +import com.ai.assistance.operit.core.files.transfer.FileCopyObserver +import com.ai.assistance.operit.core.files.transfer.FileCopyObservers +import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer.WorkspaceCopyProgress +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import com.ai.assistance.operit.core.tools.AIToolHandler import com.ai.assistance.operit.core.tools.BinaryFileContentData import com.ai.assistance.operit.core.tools.FileExistsData @@ -19,6 +26,8 @@ import kotlinx.coroutines.withContext internal class FileBrowserOperations(context: Context) { private val context = context.applicationContext private val handler = AIToolHandler.getInstance(this.context) + private val copyState = MutableStateFlow(null) + val copyProgress = copyState.asStateFlow() private fun parameters(environment: String?, vararg values: Pair) = buildList { values.forEach { (name, value) -> add(ToolParameter(name, value)) } @@ -51,37 +60,68 @@ internal class FileBrowserOperations(context: Context) { val items = FileBrowserClipboard.content.value if (items.isEmpty()) return@withContext val destinationEnv = environment ?: "android" - val parent = execute("file_exists", parameters(environment, "path" to directory)).result - check(parent is FileExistsData && parent.exists && parent.isDirectory) { - context.getString(R.string.workspace_error_invalid_path, directory) - } - val targets = items.map { item -> - val sourceEnv = item.environment ?: "android" - val destination = directory.trimEnd('/') + "/" + item.path.substringAfterLast('/') - check(sourceEnv != destinationEnv || - (destination != item.path && !destination.startsWith(item.path.trimEnd('/') + "/"))) { - context.getString(R.string.workspace_invalid_paste) + val executionContext = currentCoroutineContext() + fun progress(item: FileBrowserClipboardItem, index: Int) = WorkspaceCopyProgress( + source = item.path, + destination = directory.trimEnd('/') + "/" + item.path.trimEnd('/').substringAfterLast('/'), + sourceEnvironment = item.environment ?: "android", + destinationEnvironment = destinationEnv, + itemIndex = index + 1, + itemCount = items.size, + moving = item.cut, + ) + copyState.value = progress(items.first(), 0) + try { + val parent = execute("file_exists", parameters(environment, "path" to directory)).result + check(parent is FileExistsData && parent.exists && parent.isDirectory) { + context.getString(R.string.workspace_error_invalid_path, directory) } - item to destination - } - check(targets.map { it.second }.distinct().size == targets.size) { - context.getString(R.string.file_op_confirm_overwrite) - } - // 全批次先检查目标,避免遇到重名时已经移动了前面的文件。 - targets.forEach { (_, destination) -> requireNewDestination(destination, environment) } - for ((item, destination) in targets) { - val sourceEnv = item.environment ?: "android" - requireNewDestination(destination, environment) - if (item.cut && sourceEnv == destinationEnv) { - execute("move_file", parameters(environment, "source" to item.path, "destination" to destination)) - } else { - execute("copy_file", listOf(ToolParameter("source", item.path), ToolParameter("destination", destination), - ToolParameter("source_environment", sourceEnv), ToolParameter("dest_environment", destinationEnv), - ToolParameter("recursive", item.isDirectory.toString()))) - // 每项复制成功才删除其来源,失败后剩余剪切项仍可继续粘贴。 - if (item.cut) delete(item.path, item.environment, item.isDirectory) + val targets = items.map { item -> + val sourceEnv = item.environment ?: "android" + val destination = directory.trimEnd('/') + "/" + item.path.trimEnd('/').substringAfterLast('/') + check(sourceEnv != destinationEnv || + (destination != item.path && !destination.startsWith(item.path.trimEnd('/') + "/"))) { + context.getString(R.string.workspace_invalid_paste) + } + item to destination + } + check(targets.map { it.second }.distinct().size == targets.size) { + context.getString(R.string.file_op_confirm_overwrite) + } + // 全批次先检查目标,避免遇到重名时已经移动了前面的文件。 + targets.forEach { (_, destination) -> requireNewDestination(destination, environment) } + for ((index, target) in targets.withIndex()) { + executionContext.ensureActive() + val (item, destination) = target + val sourceEnv = item.environment ?: "android" + val itemProgress = progress(item, index) + copyState.value = itemProgress + requireNewDestination(destination, environment) + if (item.cut && sourceEnv == destinationEnv) { + execute("move_file", parameters(environment, "source" to item.path, "destination" to destination)) + } else { + val token = FileCopyObservers.register(FileCopyObserver( + onProgress = { copyState.value = itemProgress.copy(detail = it) }, + checkCancelled = { executionContext.ensureActive() }, + )) + try { + execute("copy_file", listOf(ToolParameter("source", item.path), ToolParameter("destination", destination), + ToolParameter("source_environment", sourceEnv), ToolParameter("dest_environment", destinationEnv), + ToolParameter("recursive", item.isDirectory.toString()), ToolParameter(FileCopyObservers.PARAMETER, token))) + } finally { + FileCopyObservers.remove(token) + } + // 取消或复制失败时不删除来源;整项成功后才允许完成跨环境剪切。 + executionContext.ensureActive() + if (item.cut) { + copyState.value = checkNotNull(copyState.value).copy(finishing = true) + delete(item.path, item.environment, item.isDirectory) + } + } + if (item.cut) FileBrowserClipboard.clear(item) } - if (item.cut) FileBrowserClipboard.clear(item) + } finally { + copyState.value = null } } diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgress.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgress.kt new file mode 100644 index 0000000000..d8b0c6b0ba --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgress.kt @@ -0,0 +1,16 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer + +import com.ai.assistance.operit.core.files.transfer.FileCopyProgress + +/** 一项可包含整个目录;批量粘贴同时显示项目序号,字节进度对应当前项目。 */ +internal data class WorkspaceCopyProgress( + val source: String, + val destination: String, + val sourceEnvironment: String, + val destinationEnvironment: String, + val itemIndex: Int, + val itemCount: Int, + val moving: Boolean, + val detail: FileCopyProgress? = null, + val finishing: Boolean = false, +) \ No newline at end of file diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt new file mode 100644 index 0000000000..3253b38bcd --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt @@ -0,0 +1,102 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer + +import android.text.format.Formatter +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import com.ai.assistance.operit.R +import com.ai.assistance.operit.core.files.transfer.FileCopyPhase + +@Composable +internal fun WorkspaceCopyProgressDialog(progress: WorkspaceCopyProgress, cancelling: Boolean, onCancel: () -> Unit) { + val context = LocalContext.current + val detail = progress.detail + val fraction = detail?.fraction?.let { if (progress.moving || cancelling) it.coerceAtMost(0.999f) else it } + val animatedFraction by animateFloatAsState(fraction ?: 0f, tween(180), label = "workspaceCopyProgress") + val unknown = "—" + fun size(bytes: Long): String = Formatter.formatFileSize(context, bytes) + val currentFile = if (detail == null) progress.source.trimEnd('/').substringAfterLast('/') else detail.currentFile + val status = when { + cancelling -> R.string.workspace_transfer_cancelling + progress.finishing -> R.string.workspace_transfer_finishing + detail?.phase == FileCopyPhase.SCANNING -> R.string.workspace_transfer_scanning + detail == null -> R.string.workspace_transfer_processing + progress.moving -> R.string.workspace_transfer_moving + else -> R.string.workspace_transfer_copying + } + Dialog(onDismissRequest = {}, properties = DialogProperties(dismissOnBackPress = false, dismissOnClickOutside = false)) { + Surface(shape = MaterialTheme.shapes.extraLarge, color = MaterialTheme.colorScheme.surface, tonalElevation = 6.dp) { + Column(Modifier.fillMaxWidth().verticalScroll(rememberScrollState()).padding(24.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) { + Text( + stringResource(if (progress.moving) R.string.workspace_transfer_moving else R.string.workspace_transfer_copying), + modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, + style = MaterialTheme.typography.titleLarge, + ) + if (progress.itemCount > 1) { + Text(stringResource(R.string.workspace_transfer_item, progress.itemIndex, progress.itemCount), + style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) + } + TransferDetail(stringResource(R.string.workspace_transfer_name), currentFile) + TransferDetail(stringResource(R.string.workspace_transfer_source), "${progress.sourceEnvironment}:${progress.source}") + TransferDetail(stringResource(R.string.workspace_transfer_destination), "${progress.destinationEnvironment}:${progress.destination}") + TransferDetail(stringResource(R.string.workspace_transfer_copied), + if (detail == null) unknown else "${size(detail.copiedBytes)} / ${detail.totalBytes?.let(::size) ?: unknown}") + TransferDetail(stringResource(R.string.workspace_transfer_remaining), detail?.remainingBytes?.let(::size) ?: unknown) + TransferDetail(stringResource(R.string.workspace_transfer_speed), detail?.bytesPerSecond?.let { "${size(it.toLong())}/s" } ?: unknown) + if (detail != null) { + Text(stringResource(R.string.workspace_transfer_files, detail.copiedFiles, detail.totalFiles), + style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) + } + Spacer(Modifier.height(2.dp)) + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) { + Text(stringResource(status), Modifier.weight(1f), style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant) + if (fraction != null) Text(stringResource(R.string.workspace_transfer_percent, (fraction * 100).toInt()), + style = MaterialTheme.typography.labelLarge, color = MaterialTheme.colorScheme.primary) + } + val bar = Modifier.fillMaxWidth().height(6.dp).clip(RoundedCornerShape(3.dp)) + if (fraction == null) LinearProgressIndicator(modifier = bar) + else LinearProgressIndicator(progress = { animatedFraction }, modifier = bar) + TextButton(onClick = onCancel, enabled = !cancelling, modifier = Modifier.align(Alignment.End)) { + Text(stringResource(R.string.cancel)) + } + } + } + } +} + +@Composable +private fun TransferDetail(label: String, value: String) { + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp)) { + Text(label, Modifier.weight(0.25f), style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant) + Text(value, Modifier.weight(0.75f), maxLines = 2, overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurface) + } +} \ No newline at end of file diff --git a/app/src/main/res/values-en/strings_workspace_transfer.xml b/app/src/main/res/values-en/strings_workspace_transfer.xml new file mode 100644 index 0000000000..7e798bc680 --- /dev/null +++ b/app/src/main/res/values-en/strings_workspace_transfer.xml @@ -0,0 +1,18 @@ + + + Copying... + Moving... + Counting files... + Processing... + Removing source... + Name + From + To + Copied + Remaining + Speed + Item %1$d / %2$d · Current item progress + Files: %1$d / %2$d + %1$d%% + Cancelling... + diff --git a/app/src/main/res/values-es/strings_workspace_transfer.xml b/app/src/main/res/values-es/strings_workspace_transfer.xml new file mode 100644 index 0000000000..4065b7a347 --- /dev/null +++ b/app/src/main/res/values-es/strings_workspace_transfer.xml @@ -0,0 +1,18 @@ + + + Copiando... + Moviendo... + Contando archivos... + Procesando... + Eliminando el origen... + Nombre + Origen + Destino + Copiado + Restante + Velocidad + Elemento %1$d / %2$d · Progreso del elemento actual + Archivos: %1$d / %2$d + %1$d%% + Cancelando... + diff --git a/app/src/main/res/values-id/strings_workspace_transfer.xml b/app/src/main/res/values-id/strings_workspace_transfer.xml new file mode 100644 index 0000000000..a9ff34ac8c --- /dev/null +++ b/app/src/main/res/values-id/strings_workspace_transfer.xml @@ -0,0 +1,18 @@ + + + Menyalin... + Memindahkan... + Menghitung file... + Memproses... + Menghapus sumber... + Nama + Dari + Ke + Disalin + Tersisa + Kecepatan + Item %1$d / %2$d · Progres item saat ini + File: %1$d / %2$d + %1$d%% + Membatalkan... + diff --git a/app/src/main/res/values-ja/strings_workspace_transfer.xml b/app/src/main/res/values-ja/strings_workspace_transfer.xml new file mode 100644 index 0000000000..d458f1ca1f --- /dev/null +++ b/app/src/main/res/values-ja/strings_workspace_transfer.xml @@ -0,0 +1,18 @@ + + + コピー中... + 移動中... + ファイルを集計中... + 処理中... + コピー元を削除中... + 名前 + コピー元 + コピー先 + コピー済み + 残り + 速度 + %1$d / %2$d 項目 · 現在の項目の進捗 + ファイル:%1$d / %2$d + %1$d%% + キャンセル中... + diff --git a/app/src/main/res/values-ko/strings_workspace_transfer.xml b/app/src/main/res/values-ko/strings_workspace_transfer.xml new file mode 100644 index 0000000000..15f9a2eac9 --- /dev/null +++ b/app/src/main/res/values-ko/strings_workspace_transfer.xml @@ -0,0 +1,18 @@ + + + 복사 중... + 이동 중... + 파일 집계 중... + 처리 중... + 원본 삭제 중... + 이름 + 원본 + 대상 + 복사됨 + 남은 용량 + 속도 + 항목 %1$d / %2$d · 현재 항목 진행률 + 파일: %1$d / %2$d + %1$d%% + 취소 중... + diff --git a/app/src/main/res/values-ms/strings_workspace_transfer.xml b/app/src/main/res/values-ms/strings_workspace_transfer.xml new file mode 100644 index 0000000000..842b71f202 --- /dev/null +++ b/app/src/main/res/values-ms/strings_workspace_transfer.xml @@ -0,0 +1,18 @@ + + + Menyalin... + Memindahkan... + Mengira fail... + Memproses... + Memadam sumber... + Nama + Dari + Ke + Disalin + Baki + Kelajuan + Item %1$d / %2$d · Kemajuan item semasa + Fail: %1$d / %2$d + %1$d%% + Membatalkan... + diff --git a/app/src/main/res/values-pt-rBR/strings_workspace_transfer.xml b/app/src/main/res/values-pt-rBR/strings_workspace_transfer.xml new file mode 100644 index 0000000000..94ac601a6e --- /dev/null +++ b/app/src/main/res/values-pt-rBR/strings_workspace_transfer.xml @@ -0,0 +1,18 @@ + + + Copiando... + Movendo... + Contando arquivos... + Processando... + Removendo origem... + Nome + Origem + Destino + Copiado + Restante + Velocidade + Item %1$d / %2$d · Progresso do item atual + Arquivos: %1$d / %2$d + %1$d%% + Cancelando... + diff --git a/app/src/main/res/values-ro/strings_workspace_transfer.xml b/app/src/main/res/values-ro/strings_workspace_transfer.xml new file mode 100644 index 0000000000..096290f8da --- /dev/null +++ b/app/src/main/res/values-ro/strings_workspace_transfer.xml @@ -0,0 +1,18 @@ + + + Se copiază... + Se mută... + Se numără fișierele... + Se procesează... + Se șterge sursa... + Nume + Sursă + Destinație + Copiat + Rămas + Viteză + Element %1$d / %2$d · Progresul elementului curent + Fișiere: %1$d / %2$d + %1$d%% + Se anulează... + diff --git a/app/src/main/res/values/strings_workspace_transfer.xml b/app/src/main/res/values/strings_workspace_transfer.xml new file mode 100644 index 0000000000..47aed9510d --- /dev/null +++ b/app/src/main/res/values/strings_workspace_transfer.xml @@ -0,0 +1,18 @@ + + + 正在复制... + 正在移动... + 正在统计文件... + 正在处理... + 正在清理来源... + 名称 + 来源 + 目标 + 已复制 + 剩余 + 速度 + 第 %1$d / %2$d 项 · 当前项进度 + 文件:%1$d / %2$d + %1$d%% + 正在取消... + diff --git a/app/src/test/java/com/ai/assistance/operit/core/files/transfer/StreamingFileCopyTest.kt b/app/src/test/java/com/ai/assistance/operit/core/files/transfer/StreamingFileCopyTest.kt new file mode 100644 index 0000000000..b7d29ae84a --- /dev/null +++ b/app/src/test/java/com/ai/assistance/operit/core/files/transfer/StreamingFileCopyTest.kt @@ -0,0 +1,176 @@ +package com.ai.assistance.operit.core.files.transfer + +import java.io.File +import java.io.IOException +import java.nio.file.FileAlreadyExistsException +import java.nio.file.Files +import java.nio.file.Paths +import java.security.MessageDigest +import java.util.concurrent.CancellationException +import org.junit.Assert.assertArrayEquals +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertThrows +import org.junit.Assert.assertTrue +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder + +class StreamingFileCopyTest { + @get:Rule val temporary = TemporaryFolder() + + private fun digest(file: File): ByteArray { + val digest = MessageDigest.getInstance("SHA-256") + val buffer = ByteArray(64 * 1024) + file.inputStream().use { input -> + while (true) { + val count = input.read(buffer) + if (count < 0) break + digest.update(buffer, 0, count) + } + } + return digest.digest() + } + + @Test fun binaryLargerThanFiftyMiBIsCopiedWithoutTextConversion() { + val source = temporary.newFile("binary.dat") + val destination = File(temporary.root, "result.dat") + // 测试输入自身也逐块生成,不能让测试通过分配整文件字节数组掩盖问题。 + val pattern = ByteArray(256 * 1024) { ((it * 37 + 129) % 256).toByte() } + source.outputStream().use { output -> repeat(256) { output.write(pattern) } } + val progress = mutableListOf() + val result = StreamingFileCopy.copy(source, destination, onProgress = { progress += it }) + assertEquals(64L * 1024 * 1024, destination.length()) + assertArrayEquals(digest(source), digest(destination)) + assertEquals(source.length(), result.copiedBytes) + assertEquals(source.length(), result.totalBytes) + assertEquals(FileCopyPhase.SCANNING, progress.first().phase) + assertEquals(null, progress.first().totalBytes) + assertEquals(FileCopyPhase.COMPLETED, progress.last().phase) + assertEquals(1f, result.fraction) + assertTrue(progress.filter { it.phase != FileCopyPhase.COMPLETED }.all { it.fraction != 1f }) + } + + @Test fun directoryIncludesHiddenFilesEmptyDirectoriesAndZeroByteFiles() { + val source = temporary.newFolder("source") + File(source, ".git/objects").mkdirs() + File(source, ".git/objects/binary").writeBytes(byteArrayOf(0, -1, -2, 10)) + File(source, "empty").mkdir() + File(source, "zero").createNewFile() + repeat(80) { File(source, "item-$it").writeText("内容$it") } + val destination = File(temporary.root, "copied") + val result = StreamingFileCopy.copy(source, destination) + assertTrue(File(destination, "empty").isDirectory) + assertTrue(File(destination, "zero").isFile) + assertArrayEquals(byteArrayOf(0, -1, -2, 10), File(destination, ".git/objects/binary").readBytes()) + repeat(80) { assertEquals("内容$it", File(destination, "item-$it").readText()) } + assertEquals(82L, result.copiedFiles) + assertEquals(0L, result.remainingBytes) + } + + @Test fun symbolicDirectoryLinksAreCopiedWithoutFollowingTheirTargets() { + val source = temporary.newFolder("links") + File(source, "data").writeBytes(byteArrayOf(1, 2, 3)) + Files.createSymbolicLink(File(source, "loop").toPath(), Paths.get(".")) + val destination = File(temporary.root, "links-copy") + val result = StreamingFileCopy.copy(source, destination) + assertEquals(Paths.get("."), Files.readSymbolicLink(File(destination, "loop").toPath())) + assertEquals(2L, result.copiedFiles) + assertEquals(3L, result.copiedBytes) + } + + @Test fun samePathDescendantAndAliasedDescendantAreRejectedBeforeWriting() { + val source = temporary.newFolder("parent") + File(source, "child").mkdir() + assertThrows(IllegalArgumentException::class.java) { StreamingFileCopy.copy(source, source) } + val descendant = File(source, "child/../copy") + assertThrows(IllegalArgumentException::class.java) { StreamingFileCopy.copy(source, descendant) } + val alias = File(temporary.root, "alias") + Files.createSymbolicLink(alias.toPath(), source.toPath()) + assertThrows(IllegalArgumentException::class.java) { StreamingFileCopy.copy(source, File(alias, "copy")) } + assertFalse(File(source, "copy").exists()) + } + + @Test fun existingDestinationIsProtectedAndExplicitOverwriteTruncatesIt() { + val source = temporary.newFile("new-data").apply { writeBytes(byteArrayOf(0, -1)) } + val destination = temporary.newFile("old-data").apply { writeText("original content") } + assertThrows(FileAlreadyExistsException::class.java) { StreamingFileCopy.copy(source, destination) } + assertEquals("original content", destination.readText()) + StreamingFileCopy.copy(source, destination, overwrite = true) + assertArrayEquals(byteArrayOf(0, -1), destination.readBytes()) + } + + @Test fun failedDirectoryCopyDoesNotReportCompletionOrRemoveItsSource() { + val source = temporary.newFolder("failure-source") + File(source, "data").writeText("保留来源") + val blockedParent = temporary.newFile("blocked") + val progress = mutableListOf() + assertThrows(IOException::class.java) { + StreamingFileCopy.copy(source, File(blockedParent, "result"), onProgress = { progress += it }) + } + assertEquals("保留来源", File(source, "data").readText()) + assertTrue(progress.none { it.phase == FileCopyPhase.COMPLETED }) + } + + @Test fun cancellationDuringAFileStopsBeforeCompletionAndRetainsSource() { + val source = temporary.newFile("cancel-source") + val buffer = ByteArray(StreamingFileCopy.BUFFER_SIZE) { 31 } + source.outputStream().use { output -> repeat(4) { output.write(buffer) } } + val destination = File(temporary.root, "cancel-target") + val progress = mutableListOf() + assertThrows(CancellationException::class.java) { + StreamingFileCopy.copy(source, destination, onProgress = { progress += it }, checkCancelled = { + if (destination.length() >= StreamingFileCopy.BUFFER_SIZE) throw CancellationException("取消复制") + }) + } + assertEquals(4L * StreamingFileCopy.BUFFER_SIZE, source.length()) + assertTrue(destination.length() < source.length()) + assertTrue(progress.none { it.phase == FileCopyPhase.COMPLETED }) + } + + @Test fun sourceTreeChangesAreReportedAsFailureRatherThanCompleteProgress() { + val source = temporary.newFolder("changing-source") + File(source, "first").writeText("first") + val destination = File(temporary.root, "changing-target") + var changed = false + val progress = mutableListOf() + assertThrows(IOException::class.java) { + StreamingFileCopy.copy(source, destination, onProgress = { + progress += it + if (!changed && it.phase == FileCopyPhase.COPYING) { + changed = true + File(source, "added").writeText("added") + } + }) + } + assertTrue(source.exists()) + assertTrue(progress.none { it.phase == FileCopyPhase.COMPLETED }) + } + + @Test fun destinationCreatedDuringScanningIsNotMergedOrOverwritten() { + val source = temporary.newFolder("conflict-source") + File(source, "data").writeText("source") + val destination = File(temporary.root, "conflict-target") + assertThrows(FileAlreadyExistsException::class.java) { + StreamingFileCopy.copy(source, destination, onProgress = { + if (it.phase == FileCopyPhase.COPYING && !destination.exists()) { + destination.mkdir() + File(destination, "existing").writeText("保留目标") + } + }) + } + assertEquals("保留目标", File(destination, "existing").readText()) + assertFalse(File(destination, "data").exists()) + } + + @Test fun emptyDirectoryCompletesWithZeroBytesAndRecursiveFlagIsEnforced() { + val source = temporary.newFolder("empty-source") + val destination = File(temporary.root, "empty-target") + assertThrows(IllegalArgumentException::class.java) { StreamingFileCopy.copy(source, destination, recursive = false) } + assertFalse(destination.exists()) + val result = StreamingFileCopy.copy(source, destination) + assertTrue(destination.isDirectory) + assertEquals(0L, result.copiedBytes) + assertEquals(1f, result.fraction) + } +} \ No newline at end of file diff --git a/docs/TODO/fix/README.md b/docs/TODO/fix/README.md index 46c524e841..17b32a4175 100644 --- a/docs/TODO/fix/README.md +++ b/docs/TODO/fix/README.md @@ -6,6 +6,8 @@ ## 计划索引 +- [工作区复制内存与进度](workspace-copy-streaming-progress/index.md) + - [流式气泡停更修复](streaming-bubble-freeze/index.md) - [提示、插件配置入口与 Waifu 首次展示](ux-stream-ui-followup/index.md) - [语音条 WebView 挂载焦点修复](toolpkg-webview-focus/index.md) · `toolpkg-webview-focus` diff --git a/docs/TODO/fix/workspace-copy-streaming-progress/01-validation.md b/docs/TODO/fix/workspace-copy-streaming-progress/01-validation.md new file mode 100644 index 0000000000..c0bbd20ea4 --- /dev/null +++ b/docs/TODO/fix/workspace-copy-streaming-progress/01-validation.md @@ -0,0 +1,61 @@ +# 工作区复制验证 + +## 已完成的静态核对 + +- `git diff --check` 通过 +- 9 组新增语言资源 XML 均能解析,每组包含 15 个界面条目 +- 核对复制入口继续经过既有文件工具及权限路由,本机传输复用终端挂载映射 +- 核对传输缓冲区为任务级复用的 256 KiB,目录遍历不缓存完整文件清单 +- 核对界面通过单次调用令牌接收进度,结束、失败时均移除观察者并清空面板状态 + +未执行本地编译、构建或测试。新增 10 条 JVM 回归用例由仓库 Android Tests 运行,远端结果以对应工作流为准;Android 实机内存峰值和 UI 尚未测量。 + +## 回归范围 + +| 编号 | 做什么 | 预期行为 | +| --- | --- | --- | +| A1 | 复制 64 MiB 二进制文件并流式计算 SHA-256 | 大小与摘要一致;统计阶段总量未知,成功完成后才出现 100% | +| A2 | 复制含隐藏文件、80 个小文件、空目录和零字节文件的目录 | 内容和目录齐全,文件数及剩余字节正确 | +| A3 | 复制带指向自身目录链接的目录 | 复制链接本身,不遍历链接目标 | +| A4 | 复制到自身、含 `..` 的子目录及别名子目录 | 写入前拒绝,不创建目标 | +| A5 | 复制到已存在文件并分别关闭、开启覆盖 | 关闭时保留目标,开启时正确截断并写入 | +| A6 | 将目录复制到无法创建文件的目标 | 返回失败,不报告完成,来源保留 | +| A7 | 在文件传输中取消调用 | 及时停止,不报告完成,来源保留 | +| A8 | 在统计完成后增加来源文件 | 来源变更导致失败,不报告完整成功 | +| A9 | 在统计完成后创建同名目标目录 | 不合并或覆盖刚出现的目标 | +| A10 | 复制空目录并检查递归开关 | 关闭递归时拒绝;开启时以零字节完整完成 | +| M1 | 将 `/root/Operit` 从本机 Linux 复制到手机目录,再反向复制大文件 | 原始字节保持一致,不出现整文件字符串或字节数组累积 | +| M2 | 在 Linux 使用 `~/`、`/sdcard` 和宿主挂载路径复制 | 映射与终端一致,同一实际位置仍被拒绝 | +| M3 | 单选、全选、多选和跨目录粘贴 | 全批次预检重名;多项显示序号及当前项目进度 | +| M4 | 跨环境剪切,并制造目标写入失败 | 对应项完整复制成功后才删除来源;未完成的剪切项留在剪贴板 | +| M5 | 在标准、管理员和 Root 模式执行既有文件操作 | 权限后端沿用既有路由;Shell 路径没有字节数据时显示处理中 | +| M6 | 使用远程 SSH 和 SAF 粘贴 | 使用既有提供方;未知总量不显示虚构字节数或百分比 | +| M7 | 在深浅主题、大字体及横屏查看复制面板 | 标题居中、路径可辨认、百分比位于 6dp 进度条右上方;超高内容可滚动 | +| M8 | 成功、失败、点击取消和离开文件浏览器 | 面板与观察者正确结束,错误仍显示在文件浏览器中 | + +复制链接到不支持符号链接的目标存储会明确失败并保留来源。失败时已经写入的部分目标保留,不自动删除其他文件。扫描与复制期间持续修改来源不会构成目录快照。 + +## 结果记录 + +自动用例尚未运行,实机项尚未验证。下表用于填写实际结果。 + +| 编号 | 结果与证据 | +| --- | --- | +| A1 | | +| A2 | | +| A3 | | +| A4 | | +| A5 | | +| A6 | | +| A7 | | +| A8 | | +| A9 | | +| A10 | | +| M1 | | +| M2 | | +| M3 | | +| M4 | | +| M5 | | +| M6 | | +| M7 | | +| M8 | | \ No newline at end of file diff --git a/docs/TODO/fix/workspace-copy-streaming-progress/index.md b/docs/TODO/fix/workspace-copy-streaming-progress/index.md new file mode 100644 index 0000000000..4a7a37abf7 --- /dev/null +++ b/docs/TODO/fix/workspace-copy-streaming-progress/index.md @@ -0,0 +1,25 @@ +--- +fork: https://github.com/3316891527/Operit +status: implemented-awaiting-ci +--- + +# 工作区复制内存与进度 + +工作区将内置 Ubuntu 文件复制到手机目录时,跨环境实现会完整读取文件、经过字符串转换,反向复制还会累积完整字节数组。目录递归会忽略子项失败,粘贴界面只显示旋转圆环。 + +本批优化本机 Android 与内置 Ubuntu 的文件复制,保持公开工具参数、权限路由和覆盖规则。传输逻辑放入 `core/files/transfer/`,不修改终端子模块、应用身份或数据库。 + +- [x] 使用固定缓冲区复制二进制,逐层遍历目录,不保留完整目录清单 +- [x] 使用终端现有挂载映射处理 Ubuntu、手机共享目录及 `~` +- [x] 为单次粘贴隔离进度,显示当前文件、来源、目标、已复制量、剩余量、速度及百分比 +- [x] 统计期间显示明确状态,已知总量后显示确定进度;完成前不显示 100% +- [x] 子项失败立即返回失败,剪切来源只在对应项完整成功后删除 +- [x] 补充二进制大文件、隐藏文件、空目录、同路径、符号链接及失败/取消的 10 条 JVM 回归用例 +- [x] 完成差异空白、XML 和调用关系的静态核对 +- [ ] 远端构建与测试结果确认 + +远程 SSH、SAF 和独立 Shell 复制继续使用各自原有工具实现;只有后端提供真实字节进度时才显示字节百分比,否则显示当前项目和处理中状态。不会以经过时间推算百分比。 + +完整范围和可填写结果见[验证记录](01-validation.md)。本地未编译、构建或执行测试;CI 与 PR 交付到独立工作分支,目标为 `dev`。 + +[DONE] 实现与静态核对,编译、测试和实机结果仍待验证。 From 9b9bb75d93b96b72204067fa576db30e5279d960 Mon Sep 17 00:00:00 2001 From: kong <135376906+3316891527@users.noreply.github.com> Date: Fri, 30 Oct 2026 01:00:42 +0000 Subject: [PATCH 6/7] =?UTF-8?q?fix(workspace):=20=E8=A1=A5=E9=BD=90?= =?UTF-8?q?=E5=8D=95=E9=A1=B9=E5=92=8C=E6=89=B9=E9=87=8F=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E7=AA=97=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/webview/workspace/FileManager.kt | 19 ++- .../browser/WorkspaceBrowserOperations.kt | 23 ++- .../transfer/WorkspaceCopyProgressDialog.kt | 96 +++--------- .../transfer/WorkspaceDeleteProgress.kt | 51 +++++++ .../transfer/WorkspaceDeleteProgressDialog.kt | 28 ++++ .../transfer/WorkspaceFileOperationDialog.kt | 79 ++++++++++ .../values-en/strings_workspace_transfer.xml | 4 + .../values-es/strings_workspace_transfer.xml | 4 + .../values-id/strings_workspace_transfer.xml | 4 + .../values-ja/strings_workspace_transfer.xml | 4 + .../values-ko/strings_workspace_transfer.xml | 4 + .../values-ms/strings_workspace_transfer.xml | 4 + .../strings_workspace_transfer.xml | 4 + .../values-ro/strings_workspace_transfer.xml | 4 + .../res/values/strings_workspace_transfer.xml | 4 + .../transfer/WorkspaceDeleteOperationTest.kt | 141 ++++++++++++++++++ docs/TODO/fix/README.md | 2 +- .../01-validation.md | 37 ++++- .../index.md | 9 +- 19 files changed, 430 insertions(+), 91 deletions(-) create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgress.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceFileOperationDialog.kt create mode 100644 app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt index 2d60b018af..d7965608b7 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt @@ -69,6 +69,7 @@ import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace. import com.ai.assistance.operit.util.files.FileUtils import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.* import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer.WorkspaceCopyProgressDialog +import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer.WorkspaceDeleteProgressDialog import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserClipboard import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserClipboardItem import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserContextMenu @@ -147,6 +148,7 @@ fun FileBrowser( val operations = remember(context) { FileBrowserOperations(context) } val clipboard by FileBrowserClipboard.content.collectAsState() val copyProgress by operations.copyProgress.collectAsState() + val deleteProgress by operations.deleteProgress.collectAsState() var showSortMenu by remember { mutableStateOf(false) } var selectionMode by rememberSaveable(currentPath, currentEnvironment) { mutableStateOf(false) } var selectedNames by rememberSaveable(currentPath, currentEnvironment) { mutableStateOf(emptySet()) } @@ -481,11 +483,12 @@ fun FileBrowser( TextButton(onClick = { pendingBatchDelete = null runOperation { - for (target in targets) { - operations.delete(target.path, target.environment, target.isDirectory) - selectedNames = selectedNames - target.path.substringAfterLast('/') + operations.delete(targets) { target -> + withContext(Dispatchers.Main) { + selectedNames = selectedNames - target.path.substringAfterLast('/') + if (selectedNames.isEmpty()) selectionMode = false + } } - if (selectedNames.isEmpty()) selectionMode = false } }, enabled = !isLoading) { Text(stringResource(R.string.file_manager_delete), color = MaterialTheme.colorScheme.error) } }, @@ -672,6 +675,12 @@ fun FileBrowser( }) } } + deleteProgress?.let { progress -> + WorkspaceDeleteProgressDialog(progress, cancelling = cancellingFileOperation, onCancel = { + cancellingFileOperation = true + fileOperationJob?.cancel() + }) + } propertiesTarget?.let { target -> WorkspacePropertiesDialog(target, onDismiss = { propertiesTarget = null }, @@ -905,7 +914,7 @@ fun FileBrowser( } // 文件列表 - if (isLoading && copyProgress == null) { + if (isLoading && copyProgress == null && deleteProgress == null) { Box( modifier = Modifier.fillMaxSize().weight(1f), contentAlignment = Alignment.Center diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt index 765626d03c..0dad1cdc14 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt @@ -8,6 +8,7 @@ import com.ai.assistance.operit.R import com.ai.assistance.operit.core.files.transfer.FileCopyObserver import com.ai.assistance.operit.core.files.transfer.FileCopyObservers import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer.WorkspaceCopyProgress +import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer.WorkspaceDeleteOperation import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.MutableStateFlow @@ -28,6 +29,10 @@ internal class FileBrowserOperations(context: Context) { private val handler = AIToolHandler.getInstance(this.context) private val copyState = MutableStateFlow(null) val copyProgress = copyState.asStateFlow() + private val deletion = WorkspaceDeleteOperation { target -> + deleteEntry(target.path, target.environment, target.isDirectory) + } + val deleteProgress = deletion.progress private fun parameters(environment: String?, vararg values: Pair) = buildList { values.forEach { (name, value) -> add(ToolParameter(name, value)) } @@ -51,9 +56,18 @@ internal class FileBrowserOperations(context: Context) { Unit } - suspend fun delete(path: String, environment: String?, directory: Boolean) = withContext(Dispatchers.IO) { + private fun deleteEntry(path: String, environment: String?, directory: Boolean) { execute("delete_file", parameters(environment, "path" to path, "recursive" to directory.toString())) - Unit + } + + suspend fun delete(path: String, environment: String?, directory: Boolean): Unit = + delete(listOf(FileBrowserClipboardItem(path, environment, cut = false, isDirectory = directory))) + + suspend fun delete( + targets: List, + onDeleted: suspend (FileBrowserClipboardItem) -> Unit = {}, + ): Unit = withContext(Dispatchers.IO) { + deletion.run(targets, onDeleted) } suspend fun paste(directory: String, environment: String?) = withContext(Dispatchers.IO) { @@ -115,7 +129,8 @@ internal class FileBrowserOperations(context: Context) { executionContext.ensureActive() if (item.cut) { copyState.value = checkNotNull(copyState.value).copy(finishing = true) - delete(item.path, item.environment, item.isDirectory) + // 剪切收尾仍属于移动任务,不弹出第二个删除进度窗口。 + deleteEntry(item.path, item.environment, item.isDirectory) } } if (item.cut) FileBrowserClipboard.clear(item) @@ -150,4 +165,4 @@ internal class FileBrowserOperations(context: Context) { context.startActivity(Intent.createChooser(intent, null).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt index 3253b38bcd..34265e85aa 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt @@ -1,35 +1,11 @@ package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer import android.text.format.Formatter -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.tween -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import androidx.compose.ui.window.DialogProperties import com.ai.assistance.operit.R import com.ai.assistance.operit.core.files.transfer.FileCopyPhase @@ -37,66 +13,38 @@ import com.ai.assistance.operit.core.files.transfer.FileCopyPhase internal fun WorkspaceCopyProgressDialog(progress: WorkspaceCopyProgress, cancelling: Boolean, onCancel: () -> Unit) { val context = LocalContext.current val detail = progress.detail - val fraction = detail?.fraction?.let { if (progress.moving || cancelling) it.coerceAtMost(0.999f) else it } - val animatedFraction by animateFloatAsState(fraction ?: 0f, tween(180), label = "workspaceCopyProgress") + val fraction = detail?.fraction?.let { if (progress.moving) it.coerceAtMost(0.999f) else it } val unknown = "—" fun size(bytes: Long): String = Formatter.formatFileSize(context, bytes) val currentFile = if (detail == null) progress.source.trimEnd('/').substringAfterLast('/') else detail.currentFile val status = when { - cancelling -> R.string.workspace_transfer_cancelling progress.finishing -> R.string.workspace_transfer_finishing detail?.phase == FileCopyPhase.SCANNING -> R.string.workspace_transfer_scanning detail == null -> R.string.workspace_transfer_processing progress.moving -> R.string.workspace_transfer_moving else -> R.string.workspace_transfer_copying } - Dialog(onDismissRequest = {}, properties = DialogProperties(dismissOnBackPress = false, dismissOnClickOutside = false)) { - Surface(shape = MaterialTheme.shapes.extraLarge, color = MaterialTheme.colorScheme.surface, tonalElevation = 6.dp) { - Column(Modifier.fillMaxWidth().verticalScroll(rememberScrollState()).padding(24.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) { - Text( - stringResource(if (progress.moving) R.string.workspace_transfer_moving else R.string.workspace_transfer_copying), - modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, - style = MaterialTheme.typography.titleLarge, - ) - if (progress.itemCount > 1) { - Text(stringResource(R.string.workspace_transfer_item, progress.itemIndex, progress.itemCount), - style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) - } - TransferDetail(stringResource(R.string.workspace_transfer_name), currentFile) - TransferDetail(stringResource(R.string.workspace_transfer_source), "${progress.sourceEnvironment}:${progress.source}") - TransferDetail(stringResource(R.string.workspace_transfer_destination), "${progress.destinationEnvironment}:${progress.destination}") - TransferDetail(stringResource(R.string.workspace_transfer_copied), - if (detail == null) unknown else "${size(detail.copiedBytes)} / ${detail.totalBytes?.let(::size) ?: unknown}") - TransferDetail(stringResource(R.string.workspace_transfer_remaining), detail?.remainingBytes?.let(::size) ?: unknown) - TransferDetail(stringResource(R.string.workspace_transfer_speed), detail?.bytesPerSecond?.let { "${size(it.toLong())}/s" } ?: unknown) - if (detail != null) { - Text(stringResource(R.string.workspace_transfer_files, detail.copiedFiles, detail.totalFiles), - style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) - } - Spacer(Modifier.height(2.dp)) - Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) { - Text(stringResource(status), Modifier.weight(1f), style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant) - if (fraction != null) Text(stringResource(R.string.workspace_transfer_percent, (fraction * 100).toInt()), - style = MaterialTheme.typography.labelLarge, color = MaterialTheme.colorScheme.primary) - } - val bar = Modifier.fillMaxWidth().height(6.dp).clip(RoundedCornerShape(3.dp)) - if (fraction == null) LinearProgressIndicator(modifier = bar) - else LinearProgressIndicator(progress = { animatedFraction }, modifier = bar) - TextButton(onClick = onCancel, enabled = !cancelling, modifier = Modifier.align(Alignment.End)) { - Text(stringResource(R.string.cancel)) - } - } + WorkspaceFileOperationDialog( + title = stringResource(if (progress.moving) R.string.workspace_transfer_moving else R.string.workspace_transfer_copying), + status = stringResource(status), + fraction = fraction, + cancelling = cancelling, + onCancel = onCancel, + ) { + if (progress.itemCount > 1) { + Text(stringResource(R.string.workspace_transfer_item, progress.itemIndex, progress.itemCount), + style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) + } + WorkspaceOperationDetail(stringResource(R.string.workspace_transfer_name), currentFile) + WorkspaceOperationDetail(stringResource(R.string.workspace_transfer_source), "${progress.sourceEnvironment}:${progress.source}") + WorkspaceOperationDetail(stringResource(R.string.workspace_transfer_destination), "${progress.destinationEnvironment}:${progress.destination}") + WorkspaceOperationDetail(stringResource(R.string.workspace_transfer_copied), + if (detail == null) unknown else "${size(detail.copiedBytes)} / ${detail.totalBytes?.let(::size) ?: unknown}") + WorkspaceOperationDetail(stringResource(R.string.workspace_transfer_remaining), detail?.remainingBytes?.let(::size) ?: unknown) + WorkspaceOperationDetail(stringResource(R.string.workspace_transfer_speed), detail?.bytesPerSecond?.let { "${size(it.toLong())}/s" } ?: unknown) + if (detail != null) { + Text(stringResource(R.string.workspace_transfer_files, detail.copiedFiles, detail.totalFiles), + style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) } } } - -@Composable -private fun TransferDetail(label: String, value: String) { - Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp)) { - Text(label, Modifier.weight(0.25f), style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant) - Text(value, Modifier.weight(0.75f), maxLines = 2, overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurface) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgress.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgress.kt new file mode 100644 index 0000000000..9d94c1ec07 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgress.kt @@ -0,0 +1,51 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer + +import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserClipboardItem +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +/** 只按所选项目统计,目录内部没有上报时不能把项目比例冒充文件或字节进度。 */ +internal data class WorkspaceDeleteProgress( + val target: FileBrowserClipboardItem, + val completedItems: Int, + val totalItems: Int, +) { + val fraction: Float? + get() = when { + completedItems == totalItems -> 1f + totalItems > 1 -> completedItems.toFloat() / totalItems + else -> null + } +} + +/** 删除动作由既有文件工具执行;这里只管理进度、逐项成功通知和停止后续项。 */ +internal class WorkspaceDeleteOperation( + private val deleteItem: suspend (FileBrowserClipboardItem) -> Unit, +) { + private val state = MutableStateFlow(null) + val progress = state.asStateFlow() + + suspend fun run( + targets: List, + onDeleted: suspend (FileBrowserClipboardItem) -> Unit = {}, + ) { + if (targets.isEmpty()) return + val executionContext = currentCoroutineContext() + try { + for ((index, target) in targets.withIndex()) { + executionContext.ensureActive() + val current = WorkspaceDeleteProgress(target, index, targets.size) + state.value = current + deleteItem(target) + state.value = current.copy(completedItems = index + 1) + // 当前工具返回成功才更新选择;失败不计入完成,也不开始下一个项目。 + onDeleted(target) + executionContext.ensureActive() + } + } finally { + state.value = null + } + } +} diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt new file mode 100644 index 0000000000..e9eb01a54e --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt @@ -0,0 +1,28 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer + +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.ai.assistance.operit.R + +@Composable +internal fun WorkspaceDeleteProgressDialog(progress: WorkspaceDeleteProgress, cancelling: Boolean, onCancel: () -> Unit) { + val target = progress.target + WorkspaceFileOperationDialog( + title = stringResource(R.string.workspace_transfer_deleting), + status = stringResource(R.string.workspace_transfer_deleting), + fraction = progress.fraction, + cancelling = cancelling, + onCancel = onCancel, + ) { + WorkspaceOperationDetail(stringResource(R.string.workspace_transfer_name), target.path.trimEnd('/').substringAfterLast('/')) + WorkspaceOperationDetail(stringResource(R.string.workspace_transfer_source), "${target.environment ?: "android"}:${target.path}") + Text(stringResource(R.string.workspace_transfer_deleted_items, progress.completedItems, progress.totalItems), + style = MaterialTheme.typography.bodyMedium) + Text(stringResource(R.string.workspace_transfer_delete_scope), + style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant) + Text(stringResource(R.string.workspace_transfer_delete_cancel_note), + style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant) + } +} diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceFileOperationDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceFileOperationDialog.kt new file mode 100644 index 0000000000..7558e364b3 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceFileOperationDialog.kt @@ -0,0 +1,79 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer + +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import com.ai.assistance.operit.R + +/** 复制、移动和删除共用外观;只有调用方提供真实比例时才显示百分比。 */ +@Composable +internal fun WorkspaceFileOperationDialog( + title: String, + status: String, + fraction: Float?, + cancelling: Boolean, + onCancel: () -> Unit, + content: @Composable ColumnScope.() -> Unit, +) { + val visibleFraction = fraction?.let { if (cancelling) it.coerceAtMost(0.999f) else it } + val animatedFraction by animateFloatAsState(visibleFraction ?: 0f, tween(180), label = "workspaceFileOperationProgress") + Dialog(onDismissRequest = {}, properties = DialogProperties(dismissOnBackPress = false, dismissOnClickOutside = false)) { + Surface(shape = MaterialTheme.shapes.extraLarge, color = MaterialTheme.colorScheme.surface, tonalElevation = 6.dp) { + Column(Modifier.fillMaxWidth().verticalScroll(rememberScrollState()).padding(24.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) { + Text(title, modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, + style = MaterialTheme.typography.titleLarge) + content() + Spacer(Modifier.height(2.dp)) + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) { + Text(if (cancelling) stringResource(R.string.workspace_transfer_cancelling) else status, + Modifier.weight(1f), style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant) + if (visibleFraction != null) Text(stringResource(R.string.workspace_transfer_percent, (visibleFraction * 100).toInt()), + style = MaterialTheme.typography.labelLarge, color = MaterialTheme.colorScheme.primary) + } + val bar = Modifier.fillMaxWidth().height(6.dp).clip(RoundedCornerShape(3.dp)) + if (visibleFraction == null) LinearProgressIndicator(modifier = bar) + else LinearProgressIndicator(progress = { animatedFraction }, modifier = bar) + TextButton(onClick = onCancel, enabled = !cancelling, modifier = Modifier.align(Alignment.End)) { + Text(stringResource(R.string.cancel)) + } + } + } + } +} + +@Composable +internal fun WorkspaceOperationDetail(label: String, value: String) { + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp)) { + Text(label, Modifier.weight(0.25f), style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant) + Text(value, Modifier.weight(0.75f), maxLines = 2, overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurface) + } +} diff --git a/app/src/main/res/values-en/strings_workspace_transfer.xml b/app/src/main/res/values-en/strings_workspace_transfer.xml index 7e798bc680..5c2bf61d9c 100644 --- a/app/src/main/res/values-en/strings_workspace_transfer.xml +++ b/app/src/main/res/values-en/strings_workspace_transfer.xml @@ -15,4 +15,8 @@ Files: %1$d / %2$d %1$d%% Cancelling... + Deleting... + Deleted %1$d / %2$d items + Progress counts selected items, not files inside each directory. + Cancel stops subsequent items after the current deletion returns. Deleted content is not restored. diff --git a/app/src/main/res/values-es/strings_workspace_transfer.xml b/app/src/main/res/values-es/strings_workspace_transfer.xml index 4065b7a347..7f793effe2 100644 --- a/app/src/main/res/values-es/strings_workspace_transfer.xml +++ b/app/src/main/res/values-es/strings_workspace_transfer.xml @@ -15,4 +15,8 @@ Archivos: %1$d / %2$d %1$d%% Cancelando... + Eliminando... + %1$d / %2$d elementos eliminados + El progreso cuenta los elementos seleccionados, no los archivos de cada carpeta. + Cancelar detiene los siguientes elementos al terminar la eliminación actual. El contenido eliminado no se restaura. diff --git a/app/src/main/res/values-id/strings_workspace_transfer.xml b/app/src/main/res/values-id/strings_workspace_transfer.xml index a9ff34ac8c..af2f292f31 100644 --- a/app/src/main/res/values-id/strings_workspace_transfer.xml +++ b/app/src/main/res/values-id/strings_workspace_transfer.xml @@ -15,4 +15,8 @@ File: %1$d / %2$d %1$d%% Membatalkan... + Menghapus... + %1$d / %2$d item dihapus + Progres menghitung item yang dipilih, bukan file di dalam setiap folder. + Pembatalan menghentikan item berikutnya setelah penghapusan saat ini selesai. Konten yang dihapus tidak dipulihkan. diff --git a/app/src/main/res/values-ja/strings_workspace_transfer.xml b/app/src/main/res/values-ja/strings_workspace_transfer.xml index d458f1ca1f..7775728275 100644 --- a/app/src/main/res/values-ja/strings_workspace_transfer.xml +++ b/app/src/main/res/values-ja/strings_workspace_transfer.xml @@ -15,4 +15,8 @@ ファイル:%1$d / %2$d %1$d%% キャンセル中... + 削除中... + %1$d / %2$d 項目を削除済み + 進捗は選択した項目数です。各フォルダー内の進捗は不明です。 + キャンセルすると現在の削除処理が戻った後に次の項目を停止します。削除済みの内容は復元されません。 diff --git a/app/src/main/res/values-ko/strings_workspace_transfer.xml b/app/src/main/res/values-ko/strings_workspace_transfer.xml index 15f9a2eac9..2fe0e21a47 100644 --- a/app/src/main/res/values-ko/strings_workspace_transfer.xml +++ b/app/src/main/res/values-ko/strings_workspace_transfer.xml @@ -15,4 +15,8 @@ 파일: %1$d / %2$d %1$d%% 취소 중... + 삭제 중... + %1$d / %2$d개 항목 삭제됨 + 진행률은 선택한 항목 기준이며 각 폴더 내부의 진행률은 알 수 없습니다. + 취소하면 현재 삭제가 반환된 후 다음 항목부터 중지합니다. 이미 삭제된 내용은 복원되지 않습니다. diff --git a/app/src/main/res/values-ms/strings_workspace_transfer.xml b/app/src/main/res/values-ms/strings_workspace_transfer.xml index 842b71f202..bcf1415ce8 100644 --- a/app/src/main/res/values-ms/strings_workspace_transfer.xml +++ b/app/src/main/res/values-ms/strings_workspace_transfer.xml @@ -15,4 +15,8 @@ Fail: %1$d / %2$d %1$d%% Membatalkan... + Memadam... + %1$d / %2$d item dipadam + Kemajuan mengira item yang dipilih, bukan fail dalam setiap folder. + Pembatalan menghentikan item seterusnya selepas pemadaman semasa selesai. Kandungan yang dipadam tidak dipulihkan. diff --git a/app/src/main/res/values-pt-rBR/strings_workspace_transfer.xml b/app/src/main/res/values-pt-rBR/strings_workspace_transfer.xml index 94ac601a6e..ea8dc5b9ba 100644 --- a/app/src/main/res/values-pt-rBR/strings_workspace_transfer.xml +++ b/app/src/main/res/values-pt-rBR/strings_workspace_transfer.xml @@ -15,4 +15,8 @@ Arquivos: %1$d / %2$d %1$d%% Cancelando... + Excluindo... + %1$d / %2$d itens excluídos + O progresso conta os itens selecionados, não os arquivos de cada pasta. + Cancelar interrompe os próximos itens após a exclusão atual retornar. O conteúdo excluído não é restaurado. diff --git a/app/src/main/res/values-ro/strings_workspace_transfer.xml b/app/src/main/res/values-ro/strings_workspace_transfer.xml index 096290f8da..684a77b435 100644 --- a/app/src/main/res/values-ro/strings_workspace_transfer.xml +++ b/app/src/main/res/values-ro/strings_workspace_transfer.xml @@ -15,4 +15,8 @@ Fișiere: %1$d / %2$d %1$d%% Se anulează... + Se șterge... + %1$d / %2$d elemente șterse + Progresul numără elementele selectate, nu fișierele din fiecare dosar. + Anularea oprește elementele următoare după încheierea ștergerii curente. Conținutul șters nu este restaurat. diff --git a/app/src/main/res/values/strings_workspace_transfer.xml b/app/src/main/res/values/strings_workspace_transfer.xml index 47aed9510d..aae17048c3 100644 --- a/app/src/main/res/values/strings_workspace_transfer.xml +++ b/app/src/main/res/values/strings_workspace_transfer.xml @@ -15,4 +15,8 @@ 文件:%1$d / %2$d %1$d%% 正在取消... + 正在删除... + 已删除 %1$d / %2$d 项 + 进度按所选项目计数,单个目录内部的进度未知。 + 取消将在当前删除返回后停止后续项目,已删除内容不会恢复。 diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt new file mode 100644 index 0000000000..339d586fb0 --- /dev/null +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt @@ -0,0 +1,141 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer + +import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserClipboardItem +import java.io.IOException +import kotlinx.coroutines.cancel +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue +import org.junit.Assert.fail +import org.junit.Test + +class WorkspaceDeleteOperationTest { + private fun item(name: String, environment: String? = null, directory: Boolean = false) = + FileBrowserClipboardItem("/selected/$name", environment, cut = false, isDirectory = directory) + + @Test fun singleDirectoryRemainsIndeterminateUntilItsToolReturnsSuccess() = runBlocking { + val target = item("folder", "linux", directory = true) + lateinit var operation: WorkspaceDeleteOperation + operation = WorkspaceDeleteOperation { + assertEquals(target, it) + val progress = checkNotNull(operation.progress.value) + assertEquals(target, progress.target) + assertEquals(0, progress.completedItems) + assertEquals(1, progress.totalItems) + assertNull(progress.fraction) + } + var notified = false + operation.run(listOf(target)) { + notified = true + val progress = checkNotNull(operation.progress.value) + assertEquals(1, progress.completedItems) + assertEquals(1f, checkNotNull(progress.fraction), 0f) + } + assertTrue(notified) + assertNull(operation.progress.value) + } + + @Test fun batchProgressCountsOnlySuccessfulSelectedItemsAcrossEnvironments() = runBlocking { + val targets = listOf(item("local"), item("ubuntu", "linux", true), item("document", "repo:docs")) + val before = mutableListOf() + val after = mutableListOf() + val deleted = mutableListOf() + lateinit var operation: WorkspaceDeleteOperation + operation = WorkspaceDeleteOperation { before += checkNotNull(operation.progress.value) } + operation.run(targets) { + deleted += it + after += checkNotNull(operation.progress.value) + } + assertEquals(targets, before.map { it.target }) + assertEquals(listOf(0, 1, 2), before.map { it.completedItems }) + assertEquals(listOf(1, 2, 3), after.map { it.completedItems }) + assertEquals(targets, deleted) + assertEquals(1f / 3f, checkNotNull(before[1].fraction), 0f) + assertTrue(before.all { checkNotNull(it.fraction) < 1f }) + assertEquals(1f, checkNotNull(after.last().fraction), 0f) + assertNull(operation.progress.value) + } + + @Test fun failureIsNotCountedAndRemainingItemsAreNotStarted() = runBlocking { + val targets = listOf(item("first"), item("failed"), item("remaining")) + val attempted = mutableListOf() + val deleted = mutableListOf() + val operation = WorkspaceDeleteOperation { + attempted += it + if (it == targets[1]) throw IOException("删除失败") + } + try { + operation.run(targets) { deleted += it } + fail("应传播工具删除错误") + } catch (e: IOException) { + assertEquals("删除失败", e.message) + } + assertEquals(targets.take(2), attempted) + assertEquals(targets.take(1), deleted) + assertNull(operation.progress.value) + } + + @Test fun cancellingWhileCurrentToolRunsStopsTheNextItemWithoutUndoingSuccess() = runBlocking { + val targets = listOf(item("current"), item("remaining")) + val attempted = mutableListOf() + val deleted = mutableListOf() + val operation = WorkspaceDeleteOperation { + attempted += it + // 模拟同步工具收到取消后仍返回成功:已删除项不能被视作撤销。 + currentCoroutineContext().cancel() + } + val task = launch { operation.run(targets) { deleted += it } } + task.join() + assertTrue(task.isCancelled) + assertEquals(targets.take(1), attempted) + assertEquals(targets.take(1), deleted) + assertNull(operation.progress.value) + } + + @Test fun alreadyCancelledOperationNeverStartsDeletion() = runBlocking { + var invoked = false + val operation = WorkspaceDeleteOperation { invoked = true } + val task = launch { + currentCoroutineContext().cancel() + operation.run(listOf(item("not-started"))) + } + task.join() + assertTrue(task.isCancelled) + assertFalse(invoked) + assertNull(operation.progress.value) + } + + @Test fun emptySelectionDoesNotOpenProgressOrInvokeTools() = runBlocking { + var invoked = false + var notified = false + val operation = WorkspaceDeleteOperation { invoked = true } + operation.run(emptyList()) { notified = true } + assertFalse(invoked) + assertFalse(notified) + assertNull(operation.progress.value) + } + + @Test fun nextOperationStartsWithFreshProgressAfterFailure() = runBlocking { + val failed = item("failed") + val next = item("next") + lateinit var operation: WorkspaceDeleteOperation + operation = WorkspaceDeleteOperation { + if (it == failed) throw IOException("删除失败") + assertEquals(next, checkNotNull(operation.progress.value).target) + assertEquals(0, checkNotNull(operation.progress.value).completedItems) + assertEquals(1, checkNotNull(operation.progress.value).totalItems) + } + try { + operation.run(listOf(failed, item("unprocessed"))) + fail("应传播工具删除错误") + } catch (e: IOException) { + assertNull(operation.progress.value) + } + operation.run(listOf(next)) + assertNull(operation.progress.value) + } +} diff --git a/docs/TODO/fix/README.md b/docs/TODO/fix/README.md index 17b32a4175..5d7d328ae5 100644 --- a/docs/TODO/fix/README.md +++ b/docs/TODO/fix/README.md @@ -6,7 +6,7 @@ ## 计划索引 -- [工作区复制内存与进度](workspace-copy-streaming-progress/index.md) +- [工作区复制内存与文件操作进度](workspace-copy-streaming-progress/index.md) - [流式气泡停更修复](streaming-bubble-freeze/index.md) - [提示、插件配置入口与 Waifu 首次展示](ux-stream-ui-followup/index.md) diff --git a/docs/TODO/fix/workspace-copy-streaming-progress/01-validation.md b/docs/TODO/fix/workspace-copy-streaming-progress/01-validation.md index c0bbd20ea4..cab32693cb 100644 --- a/docs/TODO/fix/workspace-copy-streaming-progress/01-validation.md +++ b/docs/TODO/fix/workspace-copy-streaming-progress/01-validation.md @@ -1,14 +1,15 @@ -# 工作区复制验证 +# 工作区复制与删除验证 ## 已完成的静态核对 - `git diff --check` 通过 -- 9 组新增语言资源 XML 均能解析,每组包含 15 个界面条目 +- 9 组新增语言资源 XML 均能解析,每组包含 19 个界面条目 - 核对复制入口继续经过既有文件工具及权限路由,本机传输复用终端挂载映射 - 核对传输缓冲区为任务级复用的 256 KiB,目录遍历不缓存完整文件清单 -- 核对界面通过单次调用令牌接收进度,结束、失败时均移除观察者并清空面板状态 +- 核对界面通过单次调用令牌接收复制进度,结束、失败时均移除观察者并清空面板状态 +- 核对单项和批量删除复用进度窗口,既有 `delete_file` 参数、权限路由和确认入口未变;剪切收尾不弹出删除窗口 -未执行本地编译、构建或测试。新增 10 条 JVM 回归用例由仓库 Android Tests 运行,远端结果以对应工作流为准;Android 实机内存峰值和 UI 尚未测量。 +未执行本地编译、构建或测试。共新增 17 条 JVM 回归用例,包含 10 条流式复制用例及 7 条删除状态用例。这些用例由仓库 Android Tests 运行,远端结果以对应工作流为准;Android 实机内存峰值和 UI 尚未测量。 ## 回归范围 @@ -24,6 +25,13 @@ | A8 | 在统计完成后增加来源文件 | 来源变更导致失败,不报告完整成功 | | A9 | 在统计完成后创建同名目标目录 | 不合并或覆盖刚出现的目标 | | A10 | 复制空目录并检查递归开关 | 关闭递归时拒绝;开启时以零字节完整完成 | +| D1 | 删除单个目录并观察工具返回前后的状态 | 执行期间不显示未知百分比,成功后才计入完成并清理窗口 | +| D2 | 删除不同来源环境的多个所选项目 | 逐项报告当前路径,完成数和比例只随成功返回推进 | +| D3 | 批量删除第二项失败 | 失败项不计完成,不开始后续项,已完成通知和错误均保留 | +| D4 | 当前删除调用期间取消 | 当前调用返回后停止后续项,不撤销已完成项,清理窗口 | +| D5 | 操作开始前已取消 | 不调用删除工具,不打开窗口 | +| D6 | 提交空删除列表 | 不调用工具或成功通知,不打开窗口 | +| D7 | 删除失败后重新开始操作 | 新任务从零开始,路径和总数不残留上次状态 | | M1 | 将 `/root/Operit` 从本机 Linux 复制到手机目录,再反向复制大文件 | 原始字节保持一致,不出现整文件字符串或字节数组累积 | | M2 | 在 Linux 使用 `~/`、`/sdcard` 和宿主挂载路径复制 | 映射与终端一致,同一实际位置仍被拒绝 | | M3 | 单选、全选、多选和跨目录粘贴 | 全批次预检重名;多项显示序号及当前项目进度 | @@ -32,9 +40,16 @@ | M6 | 使用远程 SSH 和 SAF 粘贴 | 使用既有提供方;未知总量不显示虚构字节数或百分比 | | M7 | 在深浅主题、大字体及横屏查看复制面板 | 标题居中、路径可辨认、百分比位于 6dp 进度条右上方;超高内容可滚动 | | M8 | 成功、失败、点击取消和离开文件浏览器 | 面板与观察者正确结束,错误仍显示在文件浏览器中 | +| M9 | 在文件菜单确认单个文件或目录删除 | 确认后显示居中删除标题、名称和来源路径;不显示复制目标、字节数或速度 | +| M10 | 多选并确认批量删除 | 全批次显示同一窗口,所选项目完成数和百分比正确;单个目录内进度保持未知 | +| M11 | 批量删除时制造权限错误,或点击取消 | 失败/取消后不开始后续项,列表刷新,未完成项不误清选择;已删除内容不恢复 | +| M12 | 在标准、管理员、Root、Linux 和 SAF 环境删除 | 沿用原删除工具、环境及递归参数;同一删除窗口不改变后端权限 | +| M13 | 跨环境剪切进入清理来源阶段 | 保持移动窗口,不叠加删除窗口;完成、失败与取消后状态正确清理 | 复制链接到不支持符号链接的目标存储会明确失败并保留来源。失败时已经写入的部分目标保留,不自动删除其他文件。扫描与复制期间持续修改来源不会构成目录快照。 +删除百分比仅按所选顶层项目计数,不代表目录内文件数或字节数。已有同步删除工具不能在调用中途保证停止,取消在当前调用返回后阻止后续项;不撤销已完成删除。 + ## 结果记录 自动用例尚未运行,实机项尚未验证。下表用于填写实际结果。 @@ -51,6 +66,13 @@ | A8 | | | A9 | | | A10 | | +| D1 | | +| D2 | | +| D3 | | +| D4 | | +| D5 | | +| D6 | | +| D7 | | | M1 | | | M2 | | | M3 | | @@ -58,4 +80,9 @@ | M5 | | | M6 | | | M7 | | -| M8 | | \ No newline at end of file +| M8 | | +| M9 | | +| M10 | | +| M11 | | +| M12 | | +| M13 | | diff --git a/docs/TODO/fix/workspace-copy-streaming-progress/index.md b/docs/TODO/fix/workspace-copy-streaming-progress/index.md index 4a7a37abf7..571ed2c568 100644 --- a/docs/TODO/fix/workspace-copy-streaming-progress/index.md +++ b/docs/TODO/fix/workspace-copy-streaming-progress/index.md @@ -3,11 +3,11 @@ fork: https://github.com/3316891527/Operit status: implemented-awaiting-ci --- -# 工作区复制内存与进度 +# 工作区复制内存与文件操作进度 工作区将内置 Ubuntu 文件复制到手机目录时,跨环境实现会完整读取文件、经过字符串转换,反向复制还会累积完整字节数组。目录递归会忽略子项失败,粘贴界面只显示旋转圆环。 -本批优化本机 Android 与内置 Ubuntu 的文件复制,保持公开工具参数、权限路由和覆盖规则。传输逻辑放入 `core/files/transfer/`,不修改终端子模块、应用身份或数据库。 +本批优化本机 Android 与内置 Ubuntu 的文件复制,并为单项和批量删除补齐共用进度窗口,保持公开工具参数、权限路由、覆盖规则及删除确认。传输逻辑放入 `core/files/transfer/`,不修改终端子模块、应用身份或数据库。 - [x] 使用固定缓冲区复制二进制,逐层遍历目录,不保留完整目录清单 - [x] 使用终端现有挂载映射处理 Ubuntu、手机共享目录及 `~` @@ -16,10 +16,15 @@ status: implemented-awaiting-ci - [x] 子项失败立即返回失败,剪切来源只在对应项完整成功后删除 - [x] 补充二进制大文件、隐藏文件、空目录、同路径、符号链接及失败/取消的 10 条 JVM 回归用例 - [x] 完成差异空白、XML 和调用关系的静态核对 +- [x] 为单项和批量删除复用进度窗口,显示真实的所选项目完成数,保留既有删除后端和确认提示 +- [x] 删除失败、取消时清理窗口状态,停止后续项目;跨环境剪切清理不另弹删除窗口 +- [x] 补充删除进度、部分失败及取消的 7 条回归用例,更新完整验证范围 - [ ] 远端构建与测试结果确认 远程 SSH、SAF 和独立 Shell 复制继续使用各自原有工具实现;只有后端提供真实字节进度时才显示字节百分比,否则显示当前项目和处理中状态。不会以经过时间推算百分比。 +删除仅按所选项目计数,单个目录内部的进度未知。取消将在当前删除调用返回后停止后续项目;已删除内容不恢复,错误继续显示在文件浏览器。跨环境剪切清理不另弹删除窗口。 + 完整范围和可填写结果见[验证记录](01-validation.md)。本地未编译、构建或执行测试;CI 与 PR 交付到独立工作分支,目标为 `dev`。 [DONE] 实现与静态核对,编译、测试和实机结果仍待验证。 From d4e90bd1c02e703240fbc15b27f71c5c1188a734 Mon Sep 17 00:00:00 2001 From: kong <135376906+3316891527@users.noreply.github.com> Date: Fri, 30 Oct 2026 03:02:31 +0000 Subject: [PATCH 7/7] =?UTF-8?q?refactor(chat):=20=E6=8C=89=E8=81=8C?= =?UTF-8?q?=E8=B4=A3=E6=95=B4=E7=90=86=E4=BC=9A=E8=AF=9D=E5=92=8C=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E5=8C=BA=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StreamingTimelineRefreshAndroidTest.kt | 2 +- .../editor/WorkspaceEditorCommentTest.kt | 2 +- .../editor/WorkspaceEditorInitialLineTest.kt | 2 +- .../core/application/OperitApplication.kt | 4 +- .../operit/core/chat/AIMessageManager.kt | 4 +- .../operit/core/config/SystemPromptConfig.kt | 2 +- .../core/tools/packTool/PackageManager.kt | 2 +- .../packTool/PackageManagerToolPkgFacade.kt | 2 +- .../toolpkg/ToolPkgChatInputHookBridge.kt | 12 +- .../toolpkg/ToolPkgCommonBridgePlugin.kt | 8 +- .../operit/services/ChatServiceCore.kt | 2 +- .../core/MessageProcessingDelegate.kt | 2 +- .../markdown/CanvasMonospaceCodeBlockBody.kt | 4 +- .../markdown/XmlRenderPluginRegistry.kt | 2 +- .../terminal}/ComputerScreen.kt | 4 +- .../chat/components/lazy/README.md | 16 - .../format}/TokenHitRateFormat.kt | 2 +- .../layout}/CompactDialogLayout.kt | 2 +- .../lazy/AwaitFirstLayoutModifier.kt | 4 +- .../lazy/CacheWindowLogic.kt | 4 +- .../lazy/IntervalList.kt | 2 +- .../lazy/LazyItemScope.kt | 2 +- .../lazy/LazyItemScopeImpl.kt | 4 +- .../lazy/LazyLayout.kt | 2 +- .../lazy/LazyLayoutBeyondBoundsInfo.kt | 2 +- .../LazyLayoutBeyondBoundsModifierLocal.kt | 4 +- .../lazy/LazyLayoutBeyondBoundsState.kt | 2 +- .../lazy/LazyLayoutCacheWindow.kt | 2 +- .../lazy/LazyLayoutIntervalContent.kt | 2 +- .../lazy/LazyLayoutItemAnimation.kt | 2 +- .../lazy/LazyLayoutItemAnimator.kt | 2 +- .../lazy/LazyLayoutItemContentFactory.kt | 2 +- .../lazy/LazyLayoutItemProvider.kt | 2 +- .../lazy/LazyLayoutKeyIndexMap.kt | 2 +- .../lazy/LazyLayoutMeasurePolicy.kt | 2 +- .../lazy/LazyLayoutMeasureScope.kt | 2 +- .../lazy/LazyLayoutMeasuredItem.kt | 2 +- .../lazy/LazyLayoutNearestRangeState.kt | 2 +- .../lazy/LazyLayoutPinnableItem.kt | 2 +- .../lazy/LazyLayoutPlatform.android.kt | 2 +- .../lazy/LazyLayoutPrefetchState.kt | 6 +- .../LazyLayoutScrollDeltaBetweenPasses.kt | 2 +- .../lazy/LazyLayoutScrollScope.kt | 2 +- .../lazy/LazyLayoutSemanticState.kt | 8 +- .../lazy/LazyLayoutSemantics.kt | 2 +- .../lazy/LazyLayoutStickyItems.kt | 2 +- .../lazy/LazyList.kt | 16 +- .../lazy/LazyListBeyondBoundsModifier.kt | 4 +- .../lazy/LazyListCacheWindowStrategy.kt | 14 +- .../lazy/LazyListIntervalContent.kt | 6 +- .../lazy/LazyListItemInfo.kt | 2 +- .../lazy/LazyListItemProvider.kt | 10 +- .../lazy/LazyListLayoutInfo.kt | 2 +- .../lazy/LazyListMeasure.kt | 12 +- .../lazy/LazyListMeasureResult.kt | 2 +- .../lazy/LazyListMeasuredItem.kt | 8 +- .../lazy/LazyListMeasuredItemProvider.kt | 8 +- .../lazy/LazyListPrefetchStrategy.kt | 10 +- .../lazy/LazyListScrollPosition.kt | 6 +- .../lazy/LazyListScrollScope.kt | 4 +- .../lazy/LazyListSemantics.kt | 4 +- .../lazy/LazyListState.kt | 24 +- .../lazy/LazySaveableStateHolder.kt | 2 +- .../lazy/LazyScopeMarker.kt | 2 +- .../lazy/ObservableScopeInvalidator.kt | 2 +- .../lazy/PrefetchScheduler.android.kt | 2 +- .../lazy/PrefetchScheduler.kt | 2 +- .../chat/foundation/lazy/README.md | 16 + .../lazy/RecyclerLazyColumn.kt | 2 +- .../list}/ChatMessageHeightMemory.kt | 2 +- .../list}/ChatScrollExtensions.kt | 4 +- .../mentions}/MentionTokenUtils.kt | 2 +- .../model/CharacterSelectorTarget.kt | 7 + .../chat/foundation/model/ChatBatchModels.kt | 10 + .../model/ChatHistoryDisplayMode.kt | 8 + .../chat/foundation/model/ChatStyle.kt | 7 + .../model/PendingQueueMessageItem.kt | 7 + .../foundation/model/TranslationUiState.kt | 9 + .../SimpleLinearProgressIndicator.kt | 2 +- .../stream}/RevisableTextStreamRemember.kt | 2 +- .../attachments}/AttachmentChip.kt | 6 +- .../attachments}/AttachmentPreview.kt | 3 +- .../attachments}/AttachmentSelector.kt | 4 +- .../attachments/AttachmentUtils.kt | 2 +- .../attachments/MediaFileGuard.kt | 2 +- .../attachments}/PastedTextAttachment.kt | 2 +- .../images/AttachmentImagePreviewDialog.kt | 8 +- .../images/ChatImagePickerDialog.kt | 2 +- .../images/ExpiredImageGroupTag.kt | 2 +- .../images/GalleryDragSelection.kt | 2 +- .../images/ImagePreviewTransform.kt | 2 +- .../images/MediaStoreImageRepository.kt | 2 +- .../attachments/images/SentImageGroup.kt | 8 +- .../attachments/images/SentImageSources.kt | 2 +- .../imports}/SharedFileTargetDialog.kt | 2 +- .../SharedPackageImportChoiceDialog.kt | 2 +- .../preview}/AttachmentViewerDialog.kt | 12 +- .../preview}/AudioAttachmentPlayer.kt | 2 +- .../preview}/VideoAttachmentPlayer.kt | 2 +- .../characters}/CharacterSelectorPanel.kt | 8 +- .../export}/ExportDialogs.kt | 9 +- .../export/htmlpackager/HtmlPackagerScreen.kt | 16 +- .../export/htmlpackager/PackagerResources.kt | 2 +- .../history}/ChatArchiveFilter.kt | 2 +- .../history}/ChatHistorySelector.kt | 10 +- .../history}/batch/ChatBatchControls.kt | 4 +- .../history}/batch/ChatBatchMoveDialog.kt | 2 +- .../history}/folders/ChatFolderTree.kt | 2 +- .../folders/FolderChatHistoryPanel.kt | 19 +- .../history}/folders/FolderHistoryDialogs.kt | 4 +- .../history}/folders/FolderTreeList.kt | 4 +- .../history}/folders/HistoryCreateCapsule.kt | 2 +- .../history}/folders/HistoryQuickScroller.kt | 2 +- .../history}/motion/DissolvingChatTitle.kt | 2 +- .../input}/FullscreenInputDialog.kt | 4 +- .../input/agent/AgentChatInputSection.kt | 34 +- .../input/classic/ClassicChatInputSection.kt | 16 +- .../input/classic/ClassicChatSettingsBar.kt | 22 +- ...terCardMemoryBindingSwitchConfirmDialog.kt | 2 +- ...cterCardModelBindingSwitchConfirmDialog.kt | 2 +- .../input/common/ChatInputHookRegistry.kt | 2 +- .../common/InputMenuTogglePluginRegistry.kt | 2 +- .../common/MentionVisualTransformation.kt | 4 +- .../input/common/PendingMessageQueuePanel.kt | 8 +- .../input/common/ThinkingQualitySlider.kt | 2 +- .../input/common/ToolPromptManagerDialog.kt | 2 +- .../memory}/MemoryFolderSelectionDialog.kt | 2 +- .../input/mentions/MentionSuggestionPanel.kt} | 4 +- .../messages}/ChatArea.kt | 37 +- .../actions}/WorkspaceChangeConfirmDialog.kt | 6 +- .../messages}/copy/MessageCopyTextField.kt | 2 +- .../details/MessageGenerationDetails.kt | 4 +- .../messages/details}/MessageInfoDialog.kt | 7 +- .../details/MessageStatsFormatting.kt | 2 +- .../messages/editor}/MessageEditor.kt | 2 +- .../messages/editor}/MessageEditorContent.kt | 2 +- .../messages/links}/LinkPreviewDialog.kt | 10 +- .../messages}/motion/NewChatIntro.kt | 2 +- .../navigation}/ChatScrollNavigator.kt | 5 +- .../navigation}/ScrollToBottomButton.kt | 5 +- .../messages/references}/ReferencesDisplay.kt | 2 +- .../messages/rendering}/ChatNodeVisibility.kt | 2 +- .../messages/rendering}/CustomXmlRenderer.kt | 8 +- .../messages/rendering}/DetailsTagRenderer.kt | 2 +- .../messages/rendering}/DialogComponents.kt | 6 +- .../messages/rendering}/FileDiffDisplay.kt | 2 +- .../messages/rendering}/FontTagRenderer.kt | 2 +- .../messages/rendering}/ParamVisualizer.kt | 2 +- .../rendering}/StatusCardHtmlDocument.kt | 2 +- .../messages/rendering}/ThinkToolsRows.kt | 6 +- .../rendering}/ThinkToolsXmlNodeGrouper.kt | 8 +- .../rendering}/ThinkingMarkdownStream.kt | 2 +- .../rendering}/ToolDisplayComponents.kt | 2 +- .../messages/rendering}/ToolResultDisplay.kt | 6 +- .../rendering}/XmlCanvasBlockComponents.kt | 2 +- .../rendering}/XmlCanvasSummaryComponents.kt | 2 +- .../rendering}/tooltiming/ToolTimingIndex.kt | 2 +- .../rendering}/tooltiming/ToolTimingTitle.kt | 2 +- .../style/bubble/BubbleAiMessageComposable.kt | 16 +- .../bubble/BubbleImageBackgroundSurface.kt | 4 +- .../style/bubble/BubbleImageLayout.kt | 2 +- .../style/bubble/BubbleImageTiling.kt | 2 +- .../style/bubble/BubbleStyleChatMessage.kt | 6 +- .../bubble/BubbleUserMessageComposable.kt | 20 +- .../HiddenUserMessagePlaceholderContent.kt | 2 +- .../style/cursor/AiMessageComposable.kt | 16 +- .../style/cursor/CursorStyleChatMessage.kt | 4 +- .../style/cursor/SummaryMessageComposable.kt | 2 +- .../style/cursor/UserMessageComposable.kt | 20 +- .../messages}/timeline/ChatTimelineEntries.kt | 20 +- .../translation}/MessageTranslationDialog.kt | 4 +- .../sharing}/MessageImageGenerator.kt | 8 +- .../sharing}/ShareImagePreviewDialog.kt | 2 +- .../sidebar/ChatSidebarContent.kt | 8 +- .../{ => modules}/sidebar/ChatSidebarState.kt | 4 +- .../{ => modules}/sidebar/MainChatControls.kt | 6 +- .../sidebar/SidebarButtonSurface.kt | 2 +- .../sidebar/SidebarPluginSection.kt | 2 +- .../usage}/ChatContextUsageDialog.kt | 2 +- .../usage}/ChatContextUsageEntry.kt | 2 +- .../usage}/ContextUsageFormat.kt | 2 +- .../usage}/ContextWindowUsageContent.kt | 2 +- .../usage}/CumulativeUsageContent.kt | 2 +- .../usage}/TokenInfoDialog.kt | 2 +- .../voice}/ExpiredVoiceMessageTag.kt | 2 +- .../voice}/VoiceMessagePlayer.kt | 6 +- .../voice}/VoiceMessageSession.kt | 2 +- .../voice}/VoiceMessageSheet.kt | 2 +- .../voice}/VoiceMessageSheetContent.kt | 2 +- .../voice}/VoiceMessageXmlPlugin.kt | 2 +- .../voice}/VoiceWaveform.kt | 2 +- .../conversation/chat/screens/AIChatScreen.kt | 73 +- .../{components => screens}/ChatHeader.kt | 2 +- .../ChatScreenContent.kt | 30 +- .../ChatScreenHeader.kt | 2 +- .../chat/viewmodel/ChatViewModel.kt | 59 +- .../viewmodel/PendingMessageQueueStore.kt | 2 +- .../history}/ChatBatchController.kt | 12 +- .../history}/ChatListMotionState.kt | 2 +- .../webview => }/workspace/FileManager.kt | 37 +- .../workspace/WorkspaceBackupManager.kt | 8 +- .../WorkspaceCommandExecutionState.kt | 2 +- .../webview => }/workspace/WorkspaceConfig.kt | 2 +- .../workspace/WorkspaceFileModels.kt | 2 +- .../workspace/WorkspaceManager.kt | 54 +- .../webview => }/workspace/WorkspaceScreen.kt | 4 +- .../webview => }/workspace/WorkspaceSetup.kt | 6 +- .../webview => workspace}/WorkspaceUtils.kt | 2 +- .../workspace/browser/FileBrowserClipboard.kt | 2 +- .../browser/FileBrowserSelectionBar.kt | 2 +- .../browser/WorkspaceBrowserDialogs.kt | 4 +- .../browser/WorkspaceBrowserOperations.kt | 8 +- .../browser/WorkspaceBrowserSupport.kt | 2 +- .../properties/WorkspacePropertiesDialog.kt | 2 +- .../WorkspacePropertiesRepository.kt | 2 +- .../properties/WorkspacePropertyAccess.kt | 2 +- .../properties/WorkspacePropertyProviders.kt | 4 +- .../browser/transfer/WorkspaceCopyProgress.kt | 2 +- .../transfer/WorkspaceCopyProgressDialog.kt | 2 +- .../transfer/WorkspaceDeleteProgress.kt | 4 +- .../transfer/WorkspaceDeleteProgressDialog.kt | 2 +- .../transfer/WorkspaceFileOperationDialog.kt | 2 +- .../workspace/editor/CanvasCodeEditorView.kt | 14 +- .../workspace/editor/CodeEditor.kt | 10 +- .../workspace/editor/CodeFormatter.kt | 2 +- .../workspace/editor/CommentSyntax.kt | 2 +- .../workspace/editor/EditorDocument.kt | 2 +- .../workspace/editor/EditorMetrics.kt | 2 +- .../editor/EditorSyntaxHighlighter.kt | 6 +- .../workspace/editor/LanguageDetector.kt | 2 +- .../editor/completion/CompletionPopup.kt | 6 +- .../editor/completion/CompletionProvider.kt | 2 +- .../completion/CompletionProviderFactory.kt | 2 +- .../completion/DartCompletionProvider.kt | 4 +- .../completion/DefaultCompletionProvider.kt | 2 +- .../completion/HtmlCompletionProvider.kt | 2 +- .../JavaScriptCompletionProvider.kt | 4 +- .../completion/KotlinCompletionProvider.kt | 4 +- .../editor/language/BaseLanguageSupport.kt | 2 +- .../workspace/editor/language/DartSupport.kt | 2 +- .../workspace/editor/language/HtmlSupport.kt | 2 +- .../editor/language/JavaScriptSupport.kt | 2 +- .../editor/language/KotlinSupport.kt | 2 +- .../editor/language/LanguageFactory.kt | 2 +- .../editor/language/LanguageSupport.kt | 2 +- .../language/LanguageSupportRegistry.kt | 2 +- .../workspace/editor/theme/EditorTheme.kt | 2 +- .../hub}/WorkspaceHubHome.kt | 2 +- .../hub}/WorkspaceHubOverlay.kt | 2 +- .../hub}/WorkspaceHubScreen.kt | 6 +- .../hub}/WorkspaceHubState.kt | 2 +- .../hub}/WorkspaceSessionTabs.kt | 2 +- .../workspace/links/WorkspaceFileLink.kt | 2 +- .../workspace/links/WorkspaceFileLinkHost.kt | 18 +- .../workspace/links/WorkspaceMarkdownLink.kt | 2 +- .../markdown/WorkspaceMarkdownPreview.kt | 10 +- .../preview}/LocalWebServer.kt | 4 +- .../preview}/WebViewHandler.kt | 2 +- .../preview}/WorkspaceFilePreviewSupport.kt | 4 +- .../preview}/WorkspaceImagePreview.kt | 2 +- .../preview}/WorkspacePreviewRefreshBus.kt | 2 +- .../WorkspaceReadOnlyDocumentPreview.kt | 3 +- .../process/DepthLimitedFileObserver.kt | 2 +- .../workspace/process/GitIgnoreFilter.kt | 2 +- .../process/WorkspaceAttachmentProcessor.kt | 2 +- .../process/WorkspaceChangeTracker.kt | 6 +- .../process/WorkspaceRuleFileReader.kt | 2 +- .../workspace/search/WorkspaceTextSearch.kt | 2 +- .../workspace/text/WorkspaceTextReadPolicy.kt | 2 +- .../theme/workbench/ThemePreviewSurfaces.kt | 4 +- .../ThemeWorkbenchMessageAppearance.kt | 2 +- .../sections/ThemeSettingsCoreSections.kt | 2 +- .../demo/markdown/StreamMarkdownDemo.kt | 2 +- .../fullscreen/components/MessageDisplay.kt | 4 +- .../ui/window/components/AttachmentPanel.kt | 2 +- .../ui/window/components/ChatMessages.kt | 2 +- .../FloatingChatWindowInputControls.kt | 2 +- .../window/screen/FloatingChatWindowScreen.kt | 10 +- .../ai/assistance/operit/ui/main/OperitApp.kt | 12 +- .../operit/ui/main/components/AppContent.kt | 6 +- .../ui/main/components/DrawerContent.kt | 10 +- .../operit/ui/main/screens/OperitScreens.kt | 6 +- .../assistance/operit/util/files/FileUtils.kt | 2 +- .../format}/TokenHitRateFormatTest.kt | 2 +- .../attachments}/PastedTextAttachmentTest.kt | 2 +- .../images/GalleryDragSelectionTest.kt | 2 +- .../images/ImagePreviewTransformTest.kt | 2 +- .../images/SentImageSourcesTest.kt | 2 +- .../folders/FolderChatHistoryTreeTest.kt | 2 +- .../messages}/ChatAreaTokenSpeedTest.kt | 4 +- .../messages}/MessageCopyTextTest.kt | 2 +- .../details/MessageStatsFormattingTest.kt | 2 +- .../editor}/MessageEditorContentTest.kt | 2 +- .../rendering}/StatusCardHtmlDocumentTest.kt | 2 +- .../messages/rendering}/ThinkToolsRowsTest.kt | 4 +- .../rendering}/ThinkingMarkdownStreamTest.kt | 2 +- .../tooltiming/ToolTimingIndexTest.kt | 2 +- .../style/bubble/BubbleImageLayoutTest.kt | 2 +- .../history}/ChatBatchControllerTest.kt | 6 +- .../history}/ChatListMotionStateTest.kt | 2 +- .../browser/FileBrowserClipboardTest.kt | 2 +- .../browser/WorkspaceBrowserSupportTest.kt | 2 +- .../transfer/WorkspaceDeleteOperationTest.kt | 4 +- .../editor/WorkspaceCommentSyntaxTest.kt | 2 +- .../workspace/links/WorkspaceFileLinkTest.kt | 2 +- .../links/WorkspaceMarkdownLinkTest.kt | 2 +- .../search/WorkspaceTextSearchTest.kt | 2 +- .../text/WorkspaceTextReadPolicyTest.kt | 2 +- docs/TODO/chore/README.md | 4 + .../01-validation.md | 116 + .../chat-responsibility-layout/files.json | 2038 +++++++++++++++++ .../chore/chat-responsibility-layout/index.md | 66 + .../01-validation.md | 52 + .../conversation-workspace-layout/files.json | 810 +++++++ .../conversation-workspace-layout/index.md | 26 + ...60\344\270\216\351\252\214\350\257\201.md" | 2 +- ...36\347\216\260\350\257\264\346\230\216.md" | 2 +- ...60\344\270\216\351\252\214\350\257\201.md" | 2 +- ...37\346\210\220\350\257\246\346\203\205.md" | 2 +- ...37\344\270\200\345\205\245\345\217\243.md" | 2 +- ...73\344\276\247\350\276\271\346\240\217.md" | 2 +- ...60\345\277\206\350\256\276\347\275\256.md" | 2 +- ...57\350\256\241\347\224\250\351\207\217.md" | 2 +- ...10\346\236\234\346\201\242\345\244\215.md" | 2 +- .../02-file-links-and-theme.md | 2 +- docs/TODO/feat/linux-file-preview/index.md | 2 +- .../feat/voice-messages/01-implementation.md | 2 +- ...32\345\212\250\345\256\236\347\216\260.md" | 2 +- ...15\344\270\216\344\277\256\345\244\215.md" | 2 +- 329 files changed, 3947 insertions(+), 776 deletions(-) rename app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/timeline/StreamingTimelineRefreshAndroidTest.kt (98%) rename app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/WorkspaceEditorCommentTest.kt (96%) rename app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/WorkspaceEditorInitialLineTest.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/{conversation/chat/webview/computer => automation/terminal}/ComputerScreen.kt (56%) delete mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/README.md rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation/format}/TokenHitRateFormat.kt (88%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation/layout}/CompactDialogLayout.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/AwaitFirstLayoutModifier.kt (93%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/CacheWindowLogic.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/IntervalList.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyItemScope.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyItemScopeImpl.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayout.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutBeyondBoundsInfo.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutBeyondBoundsModifierLocal.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutBeyondBoundsState.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutCacheWindow.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutIntervalContent.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutItemAnimation.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutItemAnimator.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutItemContentFactory.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutItemProvider.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutKeyIndexMap.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutMeasurePolicy.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutMeasureScope.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutMeasuredItem.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutNearestRangeState.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutPinnableItem.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutPlatform.android.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutPrefetchState.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutScrollDeltaBetweenPasses.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutScrollScope.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutSemanticState.kt (86%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutSemantics.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyLayoutStickyItems.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyList.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListBeyondBoundsModifier.kt (91%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListCacheWindowStrategy.kt (88%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListIntervalContent.kt (90%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListItemInfo.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListItemProvider.kt (88%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListLayoutInfo.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListMeasure.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListMeasureResult.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListMeasuredItem.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListMeasuredItemProvider.kt (87%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListPrefetchStrategy.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListScrollPosition.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListScrollScope.kt (93%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListSemantics.kt (84%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyListState.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazySaveableStateHolder.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/LazyScopeMarker.kt (90%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/ObservableScopeInvalidator.kt (93%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/PrefetchScheduler.android.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/PrefetchScheduler.kt (98%) create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/README.md rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation}/lazy/RecyclerLazyColumn.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation/list}/ChatMessageHeightMemory.kt (93%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation/list}/ChatScrollExtensions.kt (91%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{util => foundation/mentions}/MentionTokenUtils.kt (97%) create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/CharacterSelectorTarget.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatBatchModels.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatHistoryDisplayMode.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatStyle.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/PendingQueueMessageItem.kt create mode 100644 app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/TranslationUiState.kt rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation/progress}/SimpleLinearProgressIndicator.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation/stream}/RevisableTextStreamRemember.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/attachments}/AttachmentChip.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/attachments}/AttachmentPreview.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/attachments}/AttachmentSelector.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/AttachmentUtils.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/MediaFileGuard.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/attachments}/PastedTextAttachment.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/AttachmentImagePreviewDialog.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/ChatImagePickerDialog.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/ExpiredImageGroupTag.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/GalleryDragSelection.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/ImagePreviewTransform.kt (93%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/MediaStoreImageRepository.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/SentImageGroup.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/SentImageSources.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/attachments/imports}/SharedFileTargetDialog.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/attachments/imports}/SharedPackageImportChoiceDialog.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/attachments => modules/attachments/preview}/AttachmentViewerDialog.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/attachments => modules/attachments/preview}/AudioAttachmentPlayer.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/attachments => modules/attachments/preview}/VideoAttachmentPlayer.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/characters}/CharacterSelectorPanel.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/export}/ExportDialogs.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/export/htmlpackager/HtmlPackagerScreen.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/export/htmlpackager/PackagerResources.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{archive => modules/history}/ChatArchiveFilter.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/history}/ChatHistorySelector.kt (84%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/history}/batch/ChatBatchControls.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/history}/batch/ChatBatchMoveDialog.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/history}/folders/ChatFolderTree.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/history}/folders/FolderChatHistoryPanel.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/history}/folders/FolderHistoryDialogs.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/history}/folders/FolderTreeList.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/history}/folders/HistoryCreateCapsule.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/history}/folders/HistoryQuickScroller.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/history}/motion/DissolvingChatTitle.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/input}/FullscreenInputDialog.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/agent/AgentChatInputSection.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/classic/ClassicChatInputSection.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/classic/ClassicChatSettingsBar.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/common/CharacterCardMemoryBindingSwitchConfirmDialog.kt (91%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/common/CharacterCardModelBindingSwitchConfirmDialog.kt (91%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/common/ChatInputHookRegistry.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/common/InputMenuTogglePluginRegistry.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/common/MentionVisualTransformation.kt (92%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/common/PendingMessageQueuePanel.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/common/ThinkingQualitySlider.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/style => modules}/input/common/ToolPromptManagerDialog.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/input/memory}/MemoryFolderSelectionDialog.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{webview/WorkspaceFileSelector.kt => modules/input/mentions/MentionSuggestionPanel.kt} (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/ChatArea.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages/actions}/WorkspaceChangeConfirmDialog.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/messages}/copy/MessageCopyTextField.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/details/MessageGenerationDetails.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages/details}/MessageInfoDialog.kt (93%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/details/MessageStatsFormatting.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages/editor}/MessageEditor.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages/editor}/MessageEditorContent.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages/links}/LinkPreviewDialog.kt (92%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/messages}/motion/NewChatIntro.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages/navigation}/ChatScrollNavigator.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages/navigation}/ScrollToBottomButton.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages/references}/ReferencesDisplay.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/ChatNodeVisibility.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/CustomXmlRenderer.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/DetailsTagRenderer.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/DialogComponents.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/FileDiffDisplay.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/FontTagRenderer.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/ParamVisualizer.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/StatusCardHtmlDocument.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/ThinkToolsRows.kt (92%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/ThinkToolsXmlNodeGrouper.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/ThinkingMarkdownStream.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/ToolDisplayComponents.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/ToolResultDisplay.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/XmlCanvasBlockComponents.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/XmlCanvasSummaryComponents.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/tooltiming/ToolTimingIndex.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/tooltiming/ToolTimingTitle.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/bubble/BubbleAiMessageComposable.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/bubble/BubbleImageBackgroundSurface.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/bubble/BubbleImageLayout.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/bubble/BubbleImageTiling.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/bubble/BubbleStyleChatMessage.kt (92%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/bubble/BubbleUserMessageComposable.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/common/HiddenUserMessagePlaceholderContent.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/cursor/AiMessageComposable.kt (92%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/cursor/CursorStyleChatMessage.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/cursor/SummaryMessageComposable.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/cursor/UserMessageComposable.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/timeline/ChatTimelineEntries.kt (92%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages/translation}/MessageTranslationDialog.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{util => modules/sharing}/MessageImageGenerator.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/sharing}/ShareImagePreviewDialog.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/sidebar/ChatSidebarContent.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/sidebar/ChatSidebarState.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/sidebar/MainChatControls.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/sidebar/SidebarButtonSurface.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/sidebar/SidebarPluginSection.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/context => modules/usage}/ChatContextUsageDialog.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/context => modules/usage}/ChatContextUsageEntry.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/context => modules/usage}/ContextUsageFormat.kt (84%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/context => modules/usage}/ContextWindowUsageContent.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/context => modules/usage}/CumulativeUsageContent.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/config => modules/usage}/TokenInfoDialog.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{voicemessages => modules/voice}/ExpiredVoiceMessageTag.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{voicemessages => modules/voice}/VoiceMessagePlayer.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{voicemessages => modules/voice}/VoiceMessageSession.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{voicemessages => modules/voice}/VoiceMessageSheet.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{voicemessages => modules/voice}/VoiceMessageSheetContent.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{voicemessages => modules/voice}/VoiceMessageXmlPlugin.kt (92%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{voicemessages => modules/voice}/VoiceWaveform.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => screens}/ChatHeader.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => screens}/ChatScreenContent.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => screens}/ChatScreenHeader.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{batch => viewmodel/history}/ChatBatchController.kt (81%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/{motion => viewmodel/history}/ChatListMotionState.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/FileManager.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/WorkspaceBackupManager.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/WorkspaceCommandExecutionState.kt (87%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/WorkspaceConfig.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/WorkspaceFileModels.kt (85%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/WorkspaceManager.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/WorkspaceScreen.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/WorkspaceSetup.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => workspace}/WorkspaceUtils.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/FileBrowserClipboard.kt (90%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/FileBrowserSelectionBar.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/WorkspaceBrowserDialogs.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/WorkspaceBrowserOperations.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/WorkspaceBrowserSupport.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/properties/WorkspacePropertiesDialog.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/properties/WorkspacePropertiesRepository.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/properties/WorkspacePropertyAccess.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/properties/WorkspacePropertyProviders.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/transfer/WorkspaceCopyProgress.kt (83%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/transfer/WorkspaceDeleteProgress.kt (89%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt (93%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/transfer/WorkspaceFileOperationDialog.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/CanvasCodeEditorView.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/CodeEditor.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/CodeFormatter.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/CommentSyntax.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/EditorDocument.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/EditorMetrics.kt (91%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/EditorSyntaxHighlighter.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/LanguageDetector.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/completion/CompletionPopup.kt (93%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/completion/CompletionProvider.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/completion/CompletionProviderFactory.kt (85%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/completion/DartCompletionProvider.kt (94%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/completion/DefaultCompletionProvider.kt (93%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/completion/HtmlCompletionProvider.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/completion/JavaScriptCompletionProvider.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/completion/KotlinCompletionProvider.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/language/BaseLanguageSupport.kt (90%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/language/DartSupport.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/language/HtmlSupport.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/language/JavaScriptSupport.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/language/KotlinSupport.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/language/LanguageFactory.kt (91%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/language/LanguageSupport.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/language/LanguageSupportRegistry.kt (93%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/theme/EditorTheme.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/workspace => workspace/hub}/WorkspaceHubHome.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/workspace => workspace/hub}/WorkspaceHubOverlay.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/workspace => workspace/hub}/WorkspaceHubScreen.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/workspace => workspace/hub}/WorkspaceHubState.kt (86%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/workspace => workspace/hub}/WorkspaceSessionTabs.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/links/WorkspaceFileLink.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/links/WorkspaceFileLinkHost.kt (92%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/links/WorkspaceMarkdownLink.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/markdown/WorkspaceMarkdownPreview.kt (86%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => workspace/preview}/LocalWebServer.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => workspace/preview}/WebViewHandler.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview/workspace => workspace/preview}/WorkspaceFilePreviewSupport.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview/workspace => workspace/preview}/WorkspaceImagePreview.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview/workspace => workspace/preview}/WorkspacePreviewRefreshBus.kt (87%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview/workspace => workspace/preview}/WorkspaceReadOnlyDocumentPreview.kt (99%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/process/DepthLimitedFileObserver.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/process/GitIgnoreFilter.kt (98%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/process/WorkspaceAttachmentProcessor.kt (96%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/process/WorkspaceChangeTracker.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/process/WorkspaceRuleFileReader.kt (95%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/search/WorkspaceTextSearch.kt (97%) rename app/src/main/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/text/WorkspaceTextReadPolicy.kt (80%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => foundation/format}/TokenHitRateFormatTest.kt (93%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/attachments}/PastedTextAttachmentTest.kt (96%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/GalleryDragSelectionTest.kt (91%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/ImagePreviewTransformTest.kt (96%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules}/attachments/images/SentImageSourcesTest.kt (96%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{ => modules/history}/folders/FolderChatHistoryTreeTest.kt (98%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/ChatAreaTokenSpeedTest.kt (76%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/MessageCopyTextTest.kt (99%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/details/MessageStatsFormattingTest.kt (96%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages/editor}/MessageEditorContentTest.kt (99%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/StatusCardHtmlDocumentTest.kt (97%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/ThinkToolsRowsTest.kt (97%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/ThinkingMarkdownStreamTest.kt (98%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components/part => modules/messages/rendering}/tooltiming/ToolTimingIndexTest.kt (97%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{components => modules/messages}/style/bubble/BubbleImageLayoutTest.kt (98%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{batch => viewmodel/history}/ChatBatchControllerTest.kt (91%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/{motion => viewmodel/history}/ChatListMotionStateTest.kt (96%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/FileBrowserClipboardTest.kt (94%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/WorkspaceBrowserSupportTest.kt (96%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt (96%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/editor/WorkspaceCommentSyntaxTest.kt (92%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/links/WorkspaceFileLinkTest.kt (98%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/links/WorkspaceMarkdownLinkTest.kt (98%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/search/WorkspaceTextSearchTest.kt (90%) rename app/src/test/java/com/ai/assistance/operit/ui/features/conversation/{chat/webview => }/workspace/text/WorkspaceTextReadPolicyTest.kt (93%) create mode 100644 docs/TODO/chore/chat-responsibility-layout/01-validation.md create mode 100644 docs/TODO/chore/chat-responsibility-layout/files.json create mode 100644 docs/TODO/chore/chat-responsibility-layout/index.md create mode 100644 docs/TODO/chore/conversation-workspace-layout/01-validation.md create mode 100644 docs/TODO/chore/conversation-workspace-layout/files.json create mode 100644 docs/TODO/chore/conversation-workspace-layout/index.md diff --git a/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/components/timeline/StreamingTimelineRefreshAndroidTest.kt b/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/timeline/StreamingTimelineRefreshAndroidTest.kt similarity index 98% rename from app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/components/timeline/StreamingTimelineRefreshAndroidTest.kt rename to app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/timeline/StreamingTimelineRefreshAndroidTest.kt index 44b1e784d6..3331d4b817 100644 --- a/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/components/timeline/StreamingTimelineRefreshAndroidTest.kt +++ b/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/timeline/StreamingTimelineRefreshAndroidTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.timeline +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline import androidx.compose.foundation.layout.Column import androidx.compose.material3.MaterialTheme diff --git a/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceEditorCommentTest.kt b/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceEditorCommentTest.kt similarity index 96% rename from app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceEditorCommentTest.kt rename to app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceEditorCommentTest.kt index 0354432dcb..aff6af69eb 100644 --- a/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceEditorCommentTest.kt +++ b/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceEditorCommentTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Assert.* diff --git a/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceEditorInitialLineTest.kt b/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceEditorInitialLineTest.kt similarity index 97% rename from app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceEditorInitialLineTest.kt rename to app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceEditorInitialLineTest.kt index a95c2e7e65..8bf16ef5b9 100644 --- a/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceEditorInitialLineTest.kt +++ b/app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceEditorInitialLineTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor import android.view.inputmethod.EditorInfo import androidx.compose.material3.MaterialTheme diff --git a/app/src/main/java/com/ai/assistance/operit/core/application/OperitApplication.kt b/app/src/main/java/com/ai/assistance/operit/core/application/OperitApplication.kt index 72fd4c08d2..7b667ecc9c 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/application/OperitApplication.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/application/OperitApplication.kt @@ -43,8 +43,8 @@ import com.ai.assistance.operit.data.preferences.initUserPreferencesManager import com.ai.assistance.operit.data.preferences.preferencesManager import com.ai.assistance.operit.data.repository.CustomEmojiRepository import com.ai.assistance.operit.data.stats.TokenUsageRepository -import com.ai.assistance.operit.ui.features.conversation.chat.webview.LocalWebServer -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language.LanguageFactory +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.LocalWebServer +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.language.LanguageFactory import com.ai.assistance.operit.core.diagnostics.GlobalExceptionHandler import com.ai.assistance.operit.util.media.ImagePoolManager import com.ai.assistance.operit.util.android.LocaleUtils diff --git a/app/src/main/java/com/ai/assistance/operit/core/chat/AIMessageManager.kt b/app/src/main/java/com/ai/assistance/operit/core/chat/AIMessageManager.kt index d14c9c3012..9422a2b4f4 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/chat/AIMessageManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/chat/AIMessageManager.kt @@ -36,8 +36,8 @@ import com.ai.assistance.operit.data.model.ChatMessageTimestampAllocator import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.data.model.PromptFunctionType import com.ai.assistance.operit.data.preferences.ApiPreferences -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.WorkspaceAttachmentProcessor -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.WorkspaceChangeTracker +import com.ai.assistance.operit.ui.features.conversation.workspace.process.WorkspaceAttachmentProcessor +import com.ai.assistance.operit.ui.features.conversation.workspace.process.WorkspaceChangeTracker import com.ai.assistance.operit.util.media.ImagePoolManager import com.ai.assistance.operit.util.media.MediaPoolManager import com.ai.assistance.operit.core.chat.context.ChatUtils diff --git a/app/src/main/java/com/ai/assistance/operit/core/config/SystemPromptConfig.kt b/app/src/main/java/com/ai/assistance/operit/core/config/SystemPromptConfig.kt index 431fe5f31b..8b88edde4c 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/config/SystemPromptConfig.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/config/SystemPromptConfig.kt @@ -9,7 +9,7 @@ import com.ai.assistance.operit.core.tools.climode.ToolExposureMode import com.ai.assistance.operit.core.tools.packTool.PackageManager import com.ai.assistance.operit.data.preferences.ApiPreferences import com.ai.assistance.operit.data.skill.SkillRepository -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.WorkspaceRuleFileReader +import com.ai.assistance.operit.ui.features.conversation.workspace.process.WorkspaceRuleFileReader import com.ai.assistance.operit.util.android.LocaleUtils object SystemPromptConfig { diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManager.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManager.kt index 5df5c519d5..50325c9c0e 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManager.kt @@ -37,7 +37,7 @@ import com.ai.assistance.operit.data.preferences.androidPermissionPreferences import com.ai.assistance.operit.data.model.PackageToolPromptCategory import com.ai.assistance.operit.data.model.ToolPrompt import com.ai.assistance.operit.data.model.ToolResult -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceConfig +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceConfig import com.ai.assistance.operit.integrations.appwidget.ToolPkgDesktopWidgetHost import com.ai.assistance.operit.util.files.OperitPaths import com.ai.assistance.operit.util.ToolPkgWasmRuntime diff --git a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManagerToolPkgFacade.kt b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManagerToolPkgFacade.kt index 706d4a3a8d..6422ee9c55 100644 --- a/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManagerToolPkgFacade.kt +++ b/app/src/main/java/com/ai/assistance/operit/core/tools/packTool/PackageManagerToolPkgFacade.kt @@ -5,7 +5,7 @@ import com.ai.assistance.operit.core.chat.logMessageTiming import com.ai.assistance.operit.core.chat.messageTimingNow import com.ai.assistance.operit.data.model.Workflow import com.ai.assistance.operit.data.repository.WorkflowRepository -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceConfigReader +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceConfigReader import com.ai.assistance.operit.util.logging.AppLogger import java.io.File import java.nio.charset.StandardCharsets diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatInputHookBridge.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatInputHookBridge.kt index 3a91f93f67..cbdb5da755 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatInputHookBridge.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgChatInputHookBridge.kt @@ -4,12 +4,12 @@ import com.ai.assistance.operit.core.tools.packTool.PackageManager import com.ai.assistance.operit.core.tools.packTool.TOOLPKG_EVENT_CHAT_INPUT import com.ai.assistance.operit.core.tools.packTool.ToolPkgContainerRuntime import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputEvents -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputHook -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputHookContext -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputHookRegistry -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputHookResult -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputSubmitActions +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ChatInputEvents +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ChatInputHook +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ChatInputHookContext +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ChatInputHookRegistry +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ChatInputHookResult +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ChatInputSubmitActions import com.ai.assistance.operit.util.logging.AppLogger import java.util.concurrent.atomic.AtomicBoolean import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgCommonBridgePlugin.kt b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgCommonBridgePlugin.kt index 0be989b6df..6635097465 100644 --- a/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgCommonBridgePlugin.kt +++ b/app/src/main/java/com/ai/assistance/operit/plugins/toolpkg/ToolPkgCommonBridgePlugin.kt @@ -21,10 +21,10 @@ import com.ai.assistance.operit.plugins.OperitPlugin import com.ai.assistance.operit.ui.common.markdown.XmlRenderPlugin import com.ai.assistance.operit.ui.common.markdown.XmlRenderPluginRegistry import com.ai.assistance.operit.ui.common.markdown.XmlRenderResult -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuToggleDefinition -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuToggleHookParams -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuTogglePlugin -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuTogglePluginRegistry +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuToggleDefinition +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuToggleHookParams +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuTogglePlugin +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuTogglePluginRegistry import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.util.stream.Stream import com.ai.assistance.operit.core.tools.packTool.ToolPkgXmlRenderHookComposeDslResult diff --git a/app/src/main/java/com/ai/assistance/operit/services/ChatServiceCore.kt b/app/src/main/java/com/ai/assistance/operit/services/ChatServiceCore.kt index af44f95dbf..5000531bab 100644 --- a/app/src/main/java/com/ai/assistance/operit/services/ChatServiceCore.kt +++ b/app/src/main/java/com/ai/assistance/operit/services/ChatServiceCore.kt @@ -18,7 +18,7 @@ import com.ai.assistance.operit.services.core.MessageProcessingDelegate import com.ai.assistance.operit.services.core.TokenStatisticsDelegate import com.ai.assistance.operit.core.tools.AIToolHandler import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.UiStateDelegate -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.WorkspaceChangeTracker +import com.ai.assistance.operit.ui.features.conversation.workspace.process.WorkspaceChangeTracker import com.ai.assistance.operit.util.stream.SharedStream import kotlinx.coroutines.* import kotlinx.coroutines.flow.collect diff --git a/app/src/main/java/com/ai/assistance/operit/services/core/MessageProcessingDelegate.kt b/app/src/main/java/com/ai/assistance/operit/services/core/MessageProcessingDelegate.kt index a6ef2cafe7..b1732d5ae8 100644 --- a/app/src/main/java/com/ai/assistance/operit/services/core/MessageProcessingDelegate.kt +++ b/app/src/main/java/com/ai/assistance/operit/services/core/MessageProcessingDelegate.kt @@ -33,7 +33,7 @@ import com.ai.assistance.operit.data.preferences.WaifuPreferences import com.ai.assistance.operit.data.preferences.FunctionalConfigManager import com.ai.assistance.operit.data.preferences.ModelConfigManager import com.ai.assistance.operit.data.preferences.UserPreferencesManager -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceBackupManager +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceBackupManager import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/CanvasMonospaceCodeBlockBody.kt b/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/CanvasMonospaceCodeBlockBody.kt index b2e11aa75b..3610ed8175 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/CanvasMonospaceCodeBlockBody.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/CanvasMonospaceCodeBlockBody.kt @@ -47,8 +47,8 @@ import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.editorCellWidth -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.editorNextSymbolOffset +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.editorCellWidth +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.editorNextSymbolOffset import kotlinx.coroutines.launch import kotlin.math.abs import kotlin.math.ceil diff --git a/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/XmlRenderPluginRegistry.kt b/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/XmlRenderPluginRegistry.kt index 1fad1b4a23..c92ccf534e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/XmlRenderPluginRegistry.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/common/markdown/XmlRenderPluginRegistry.kt @@ -1,6 +1,6 @@ package com.ai.assistance.operit.ui.common.markdown -import com.ai.assistance.operit.ui.features.conversation.chat.voicemessages.VoiceMessageXmlPlugin +import com.ai.assistance.operit.ui.features.conversation.chat.modules.voice.VoiceMessageXmlPlugin import androidx.compose.material3.Text import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/computer/ComputerScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/terminal/ComputerScreen.kt similarity index 56% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/computer/ComputerScreen.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/automation/terminal/ComputerScreen.kt index 2e33bf5d5e..a23034d9e0 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/computer/ComputerScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/automation/terminal/ComputerScreen.kt @@ -1,10 +1,8 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.computer +package com.ai.assistance.operit.ui.features.automation.terminal import android.os.Build import androidx.annotation.RequiresApi import androidx.compose.runtime.Composable -import com.ai.assistance.operit.ui.features.automation.terminal.EmbeddedTerminalPage -import com.ai.assistance.operit.ui.features.automation.terminal.EmbeddedTerminalScreen @RequiresApi(Build.VERSION_CODES.O) @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/README.md b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/README.md deleted file mode 100644 index a5733e6aeb..0000000000 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/README.md +++ /dev/null @@ -1,16 +0,0 @@ -这里是从 Jetpack Compose Foundation 提取并本地化的 `LazyColumn` 相关源码。 - -- 来源版本:`androidx.compose.foundation:foundation-android:1.10.4` -- 入口文件:[RecyclerLazyColumn.kt](D:/Code/prog/assistance/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/RecyclerLazyColumn.kt) -- 核心布局:[LazyList.kt](D:/Code/prog/assistance/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyList.kt) -- 核心测量:[LazyListMeasure.kt](D:/Code/prog/assistance/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasure.kt) -- 状态管理:[LazyListState.kt](D:/Code/prog/assistance/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListState.kt) - -处理方式: - -- 已改为本地包名 `com.ai.assistance.operit.ui.features.conversation.chat.components.lazy` -- 文件全部平铺在当前目录下,不再保留上游多级目录 -- `LazyColumn` 入口已重命名为 `RecyclerLazyColumn` -- 仅保留 `LazyColumn/LazyList` 这条链路相关文件,没有带入 `grid` 和 `staggeredgrid` - -这批文件目前是为了后续魔改准备的本地副本,这次没有执行编译、构建或测试。 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/TokenHitRateFormat.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/format/TokenHitRateFormat.kt similarity index 88% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/TokenHitRateFormat.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/format/TokenHitRateFormat.kt index 56ae121a2b..9ef02204f1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/TokenHitRateFormat.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/format/TokenHitRateFormat.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.format import java.util.Locale import kotlin.math.floor diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/CompactDialogLayout.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/layout/CompactDialogLayout.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/CompactDialogLayout.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/layout/CompactDialogLayout.kt index 7cad522d53..cd770bb00b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/CompactDialogLayout.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/layout/CompactDialogLayout.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout import androidx.compose.foundation.ScrollState import androidx.compose.foundation.layout.heightIn diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/AwaitFirstLayoutModifier.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/AwaitFirstLayoutModifier.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/AwaitFirstLayoutModifier.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/AwaitFirstLayoutModifier.kt index f4b14b2d2a..c573c9fcc1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/AwaitFirstLayoutModifier.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/AwaitFirstLayoutModifier.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.AwaitFirstLayoutModifier.Node +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.AwaitFirstLayoutModifier.Node import androidx.compose.ui.Modifier import androidx.compose.ui.layout.registerOnLayoutRectChanged import androidx.compose.ui.node.DelegatableNode diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/CacheWindowLogic.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/CacheWindowLogic.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/CacheWindowLogic.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/CacheWindowLogic.kt index c422b3f28a..fdd17229f1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/CacheWindowLogic.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/CacheWindowLogic.kt @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.mutableIntObjectMapOf import androidx.collection.mutableIntSetOf import androidx.compose.foundation.ExperimentalFoundationApi -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutPrefetchState.PrefetchHandle +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutPrefetchState.PrefetchHandle import androidx.compose.ui.unit.Density import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.traceValue diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/IntervalList.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/IntervalList.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/IntervalList.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/IntervalList.kt index ffd810befd..1a2e2a6bad 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/IntervalList.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/IntervalList.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.internal.requirePrecondition import androidx.compose.foundation.internal.throwIndexOutOfBoundsException diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyItemScope.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyItemScope.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyItemScope.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyItemScope.kt index d8caf2d9d2..3b3da261fa 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyItemScope.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyItemScope.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.annotation.FloatRange import androidx.compose.animation.core.FiniteAnimationSpec diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyItemScopeImpl.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyItemScopeImpl.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyItemScopeImpl.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyItemScopeImpl.kt index 3c0abcb263..5c657dd691 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyItemScopeImpl.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyItemScopeImpl.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.animation.core.FiniteAnimationSpec -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutAnimateItemElement +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutAnimateItemElement import androidx.compose.runtime.State import androidx.compose.runtime.mutableIntStateOf import androidx.compose.ui.Modifier diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayout.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayout.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayout.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayout.kt index 3344ec3f65..105d1c2259 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayout.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayout.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.mutableObjectIntMapOf import androidx.compose.foundation.ExperimentalFoundationApi diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsInfo.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsInfo.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsInfo.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsInfo.kt index 478877ba44..843d66b35f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsInfo.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsInfo.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.internal.requirePrecondition import androidx.compose.runtime.collection.mutableVectorOf diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsModifierLocal.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsModifierLocal.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsModifierLocal.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsModifierLocal.kt index d1a20da84c..cb06374aaa 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsModifierLocal.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsModifierLocal.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.gestures.Orientation -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutBeyondBoundsInfo.Interval +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutBeyondBoundsInfo.Interval import androidx.compose.ui.Modifier import androidx.compose.ui.layout.BeyondBoundsLayout import androidx.compose.ui.layout.BeyondBoundsLayout.BeyondBoundsScope diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsState.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsState.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsState.kt index 23e239aa47..98f6ed7874 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsState.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.ui.util.fastForEach diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutCacheWindow.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutCacheWindow.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutCacheWindow.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutCacheWindow.kt index acaf89e590..85b49f1b1f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutCacheWindow.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutCacheWindow.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.annotation.FloatRange import androidx.compose.foundation.ExperimentalFoundationApi diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutIntervalContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutIntervalContent.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutIntervalContent.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutIntervalContent.kt index 3aefc1fc7f..b8c61cc29c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutIntervalContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutIntervalContent.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy /** * Common parts backing the interval-based content of lazy layout defined through `item` DSL. diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemAnimation.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemAnimation.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemAnimation.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemAnimation.kt index d30dd43809..198a9dbf33 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemAnimation.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemAnimation.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.FiniteAnimationSpec diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemAnimator.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemAnimator.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemAnimator.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemAnimator.kt index 555fb89bf2..d497e49635 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemAnimator.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemAnimator.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.mutableScatterMapOf import androidx.collection.mutableScatterSetOf diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemContentFactory.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemContentFactory.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemContentFactory.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemContentFactory.kt index 5bc163a3a0..007cda93d1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemContentFactory.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemContentFactory.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.mutableScatterMapOf import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemProvider.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemProvider.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemProvider.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemProvider.kt index b64b65c892..02d27e1dcf 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemProvider.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemProvider.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.annotation.IntRange import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutKeyIndexMap.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutKeyIndexMap.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutKeyIndexMap.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutKeyIndexMap.kt index 89bf173504..a752dbb3cd 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutKeyIndexMap.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutKeyIndexMap.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.MutableObjectIntMap import androidx.collection.ObjectIntMap diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasurePolicy.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasurePolicy.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasurePolicy.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasurePolicy.kt index 9a01033193..0c3f0c068d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasurePolicy.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasurePolicy.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.ui.layout.Measurable import androidx.compose.ui.layout.MeasureResult diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasureScope.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasureScope.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasureScope.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasureScope.kt index 0e93f79ac0..07c79613ec 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasureScope.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasureScope.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.annotation.IntRange as AndroidXIntRange import androidx.collection.mutableIntObjectMapOf diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasuredItem.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasuredItem.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasuredItem.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasuredItem.kt index 2a8a6feeba..9364f6e32f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasuredItem.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasuredItem.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.mutableIntObjectMapOf import androidx.compose.ui.layout.Placeable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutNearestRangeState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutNearestRangeState.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutNearestRangeState.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutNearestRangeState.kt index 6ba6cdce24..219168fbbb 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutNearestRangeState.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutNearestRangeState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.runtime.State import androidx.compose.runtime.getValue diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPinnableItem.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPinnableItem.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPinnableItem.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPinnableItem.kt index d945dcac0b..9224139a44 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPinnableItem.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPinnableItem.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.internal.checkPrecondition import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPlatform.android.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPlatform.android.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPlatform.android.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPlatform.android.kt index 9092d263ae..385966233d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPlatform.android.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPlatform.android.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import android.annotation.SuppressLint import android.os.Parcel diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPrefetchState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPrefetchState.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPrefetchState.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPrefetchState.kt index 4bffcd30e0..7c9b918819 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPrefetchState.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPrefetchState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.annotation.IntRange import androidx.annotation.VisibleForTesting @@ -24,8 +24,8 @@ import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.internal.checkPrecondition import androidx.compose.foundation.internal.requirePrecondition import androidx.compose.foundation.internal.requirePreconditionNotNull -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutPrefetchState.PrefetchHandle -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutPrefetchState.PrefetchResultScope +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutPrefetchState.PrefetchHandle +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutPrefetchState.PrefetchResultScope import androidx.compose.runtime.Stable import androidx.compose.ui.Modifier import androidx.compose.ui.layout.SubcomposeLayoutState diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutScrollDeltaBetweenPasses.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutScrollDeltaBetweenPasses.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutScrollDeltaBetweenPasses.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutScrollDeltaBetweenPasses.kt index dbe1e1f3ea..8400c4e6c8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutScrollDeltaBetweenPasses.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutScrollDeltaBetweenPasses.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.animation.core.AnimationState import androidx.compose.animation.core.AnimationVector1D diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutScrollScope.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutScrollScope.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutScrollScope.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutScrollScope.kt index 6c9b13cc56..9e985a0056 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutScrollScope.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutScrollScope.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.animation.core.AnimationState import androidx.compose.animation.core.AnimationVector1D diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutSemanticState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutSemanticState.kt similarity index 86% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutSemanticState.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutSemanticState.kt index 1e4c27022a..bec6f9752d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutSemanticState.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutSemanticState.kt @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.gestures.Orientation -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutSemanticState -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.estimatedLazyMaxScrollOffset -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.estimatedLazyScrollOffset +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutSemanticState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.estimatedLazyMaxScrollOffset +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.estimatedLazyScrollOffset import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.ui.semantics.CollectionInfo diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutSemantics.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutSemantics.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutSemantics.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutSemantics.kt index bc317c32b5..50826e8ee0 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutSemantics.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutSemantics.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.gestures.Orientation diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutStickyItems.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutStickyItems.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutStickyItems.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutStickyItems.kt index b7d037db5a..997643df05 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutStickyItems.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutStickyItems.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.IntList import androidx.collection.emptyIntList diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyList.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyList.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyList.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyList.kt index 739bf237a3..80ae7f270d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyList.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyList.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.OverscrollEffect @@ -26,13 +26,13 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.CacheWindowLogic -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayout -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutMeasurePolicy -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.StickyItemsPlacement -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.calculateLazyLayoutPinnedIndices -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.lazyLayoutBeyondBoundsModifier -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.lazyLayoutSemantics +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.CacheWindowLogic +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayout +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutMeasurePolicy +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.StickyItemsPlacement +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.calculateLazyLayoutPinnedIndices +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.lazyLayoutBeyondBoundsModifier +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.lazyLayoutSemantics import androidx.compose.foundation.scrollableArea import androidx.compose.runtime.Composable import androidx.compose.runtime.remember diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListBeyondBoundsModifier.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListBeyondBoundsModifier.kt similarity index 91% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListBeyondBoundsModifier.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListBeyondBoundsModifier.kt index a85eca87fb..639138d77f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListBeyondBoundsModifier.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListBeyondBoundsModifier.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutBeyondBoundsState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutBeyondBoundsState import androidx.compose.runtime.Composable import androidx.compose.runtime.remember diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListCacheWindowStrategy.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListCacheWindowStrategy.kt similarity index 88% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListCacheWindowStrategy.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListCacheWindowStrategy.kt index 23c8f619fa..fc45713b4b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListCacheWindowStrategy.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListCacheWindowStrategy.kt @@ -14,15 +14,15 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.ExperimentalFoundationApi -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.CacheWindowLogic -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.CacheWindowScope -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.InvalidIndex -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutCacheWindow -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutPrefetchState.PrefetchHandle -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.NestedPrefetchScope +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.CacheWindowLogic +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.CacheWindowScope +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.InvalidIndex +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutCacheWindow +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutPrefetchState.PrefetchHandle +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.NestedPrefetchScope import androidx.compose.ui.unit.Density import kotlin.math.absoluteValue diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListIntervalContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListIntervalContent.kt similarity index 90% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListIntervalContent.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListIntervalContent.kt index fdf3a31e3c..331f26e6b8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListIntervalContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListIntervalContent.kt @@ -14,14 +14,14 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.IntList import androidx.collection.MutableIntList import androidx.collection.emptyIntList import androidx.collection.mutableIntListOf -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutIntervalContent -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.MutableIntervalList +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutIntervalContent +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.MutableIntervalList import androidx.compose.runtime.Composable internal class LazyListIntervalContent(content: LazyListScope.() -> Unit) : diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListItemInfo.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListItemInfo.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListItemInfo.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListItemInfo.kt index 88574db555..3cbdaa1e45 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListItemInfo.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListItemInfo.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy /** * Contains useful information about an individual item in lazy lists like [LazyColumn] or diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListItemProvider.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListItemProvider.kt similarity index 88% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListItemProvider.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListItemProvider.kt index 53a568b7e6..af2e16831a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListItemProvider.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListItemProvider.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.IntList -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutItemProvider -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutKeyIndexMap -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutPinnableItem -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.NearestRangeKeyIndexMap +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutItemProvider +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutKeyIndexMap +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutPinnableItem +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.NearestRangeKeyIndexMap import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.referentialEqualityPolicy diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListLayoutInfo.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListLayoutInfo.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListLayoutInfo.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListLayoutInfo.kt index 715fea8cf6..d6646a34e0 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListLayoutInfo.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListLayoutInfo.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.gestures.Orientation import androidx.compose.ui.unit.IntSize diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasure.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasure.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasure.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasure.kt index 4197f03685..afad98e1ed 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasure.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasure.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.gestures.Orientation @@ -22,11 +22,11 @@ import androidx.compose.foundation.internal.checkPrecondition import androidx.compose.foundation.internal.requirePrecondition import androidx.compose.foundation.internal.requirePreconditionNotNull import androidx.compose.foundation.layout.Arrangement -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutItemAnimator -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.ObservableScopeInvalidator -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.StickyItemsPlacement -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.applyStickyItems -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.updatedVisibleItems +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutItemAnimator +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.ObservableScopeInvalidator +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.StickyItemsPlacement +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.applyStickyItems +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.updatedVisibleItems import androidx.compose.ui.graphics.GraphicsContext import androidx.compose.ui.layout.MeasureResult import androidx.compose.ui.layout.Placeable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasureResult.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasureResult.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasureResult.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasureResult.kt index 65c2b33777..33a32ca351 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasureResult.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasureResult.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.gestures.Orientation import androidx.compose.ui.layout.MeasureResult diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasuredItem.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasuredItem.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasuredItem.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasuredItem.kt index a8c6d48ebe..694664531a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasuredItem.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasuredItem.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.internal.requirePrecondition import androidx.compose.foundation.internal.requirePreconditionNotNull -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutItemAnimation.Companion.NotInitialized -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutItemAnimator -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutMeasuredItem +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutItemAnimation.Companion.NotInitialized +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutItemAnimator +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutMeasuredItem import androidx.compose.ui.Alignment import androidx.compose.ui.graphics.layer.GraphicsLayer import androidx.compose.ui.layout.Placeable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasuredItemProvider.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasuredItemProvider.kt similarity index 87% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasuredItemProvider.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasuredItemProvider.kt index 4009394f4d..4e33fe42a2 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasuredItemProvider.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasuredItemProvider.kt @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.IntList -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutKeyIndexMap -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutMeasureScope -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutMeasuredItemProvider +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutKeyIndexMap +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutMeasureScope +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutMeasuredItemProvider import androidx.compose.ui.layout.Placeable import androidx.compose.ui.unit.Constraints diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListPrefetchStrategy.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListPrefetchStrategy.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListPrefetchStrategy.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListPrefetchStrategy.kt index 0c9ed8c2f5..3d69741fc1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListPrefetchStrategy.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListPrefetchStrategy.kt @@ -16,13 +16,13 @@ @file:Suppress("DEPRECATION") // b/420551535 -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.ExperimentalFoundationApi -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutPrefetchState -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.NestedPrefetchScope -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.PrefetchScheduler -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.UnspecifiedNestedPrefetchCount +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutPrefetchState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.NestedPrefetchScope +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.PrefetchScheduler +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.UnspecifiedNestedPrefetchCount import androidx.compose.runtime.Stable /** diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListScrollPosition.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListScrollPosition.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListScrollPosition.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListScrollPosition.kt index a19733b7a2..948f2a7824 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListScrollPosition.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListScrollPosition.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.internal.checkPrecondition import androidx.compose.foundation.internal.requirePrecondition -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutNearestRangeState -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.findIndexByKey +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutNearestRangeState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.findIndexByKey import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.setValue diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListScrollScope.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListScrollScope.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListScrollScope.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListScrollScope.kt index a3561f5fa1..f815f3fdfc 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListScrollScope.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListScrollScope.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.gestures.ScrollScope -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutScrollScope +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutScrollScope import androidx.compose.ui.util.fastFirstOrNull /** diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListSemantics.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListSemantics.kt similarity index 84% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListSemantics.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListSemantics.kt index 85d1bff1d6..f0d3518ad1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListSemantics.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListSemantics.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutSemanticState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutSemanticState import androidx.compose.runtime.Composable import androidx.compose.runtime.remember diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListState.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListState.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListState.kt index 853fde36c5..9ad936ae46 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListState.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.annotation.IntRange as AndroidXIntRange import androidx.compose.foundation.ExperimentalFoundationApi @@ -26,17 +26,17 @@ import androidx.compose.foundation.gestures.ScrollableState import androidx.compose.foundation.interaction.InteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.internal.checkPrecondition -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyListState.Companion.Saver -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.AwaitFirstLayoutModifier -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.CacheWindowLogic -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutBeyondBoundsInfo -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutCacheWindow -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutItemAnimator -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutPinnedItemList -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutPrefetchState -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyLayoutScrollDeltaBetweenPasses -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.ObservableScopeInvalidator -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.animateScrollToItem +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyListState.Companion.Saver +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.AwaitFirstLayoutModifier +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.CacheWindowLogic +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutBeyondBoundsInfo +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutCacheWindow +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutItemAnimator +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutPinnedItemList +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutPrefetchState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyLayoutScrollDeltaBetweenPasses +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.ObservableScopeInvalidator +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.animateScrollToItem import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.annotation.FrequentlyChangingValue diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazySaveableStateHolder.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazySaveableStateHolder.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazySaveableStateHolder.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazySaveableStateHolder.kt index 9aa0bbef40..4e56c96fd7 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazySaveableStateHolder.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazySaveableStateHolder.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.collection.mutableScatterSetOf import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyScopeMarker.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyScopeMarker.kt similarity index 90% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyScopeMarker.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyScopeMarker.kt index 9bed10e636..d2e9c24e45 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyScopeMarker.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyScopeMarker.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy /** DSL marker used to distinguish between lazy layout scope and the item scope. */ @DslMarker annotation class LazyScopeMarker diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/ObservableScopeInvalidator.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/ObservableScopeInvalidator.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/ObservableScopeInvalidator.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/ObservableScopeInvalidator.kt index 09eae01b16..ac2c1ad7a2 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/ObservableScopeInvalidator.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/ObservableScopeInvalidator.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/PrefetchScheduler.android.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/PrefetchScheduler.android.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/PrefetchScheduler.android.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/PrefetchScheduler.android.kt index 604d33a071..cedd105ebc 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/PrefetchScheduler.android.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/PrefetchScheduler.android.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import android.os.Build import android.view.Choreographer diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/PrefetchScheduler.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/PrefetchScheduler.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/PrefetchScheduler.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/PrefetchScheduler.kt index 0d791320e6..746819cd1c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/PrefetchScheduler.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/PrefetchScheduler.kt @@ -16,7 +16,7 @@ @file:Suppress("DEPRECATION") // b/420551535 -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.ExperimentalFoundationApi diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/README.md b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/README.md new file mode 100644 index 0000000000..d571e8dca2 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/README.md @@ -0,0 +1,16 @@ +这里是从 Jetpack Compose Foundation 提取并本地化的 `LazyColumn` 相关源码。 + +- 来源版本:`androidx.compose.foundation:foundation-android:1.10.4` +- 入口文件:[RecyclerLazyColumn.kt](RecyclerLazyColumn.kt) +- 核心布局:[LazyList.kt](LazyList.kt) +- 核心测量:[LazyListMeasure.kt](LazyListMeasure.kt) +- 状态管理:[LazyListState.kt](LazyListState.kt) + +处理方式: + +- 已改为本地包名 `com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy` +- 文件全部平铺在当前目录下,不再保留上游多级目录 +- `LazyColumn` 入口已重命名为 `RecyclerLazyColumn` +- 仅保留 `LazyColumn/LazyList` 这条链路相关文件,没有带入 `grid` 和 `staggeredgrid` + +这批文件目前是为了后续魔改准备的本地副本,这次没有执行编译、构建或测试。 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/RecyclerLazyColumn.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/RecyclerLazyColumn.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/RecyclerLazyColumn.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/RecyclerLazyColumn.kt index 5ed8c910a7..d49b9abce8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/RecyclerLazyColumn.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/RecyclerLazyColumn.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.ai.assistance.operit.ui.features.conversation.chat.components.lazy +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy import androidx.compose.foundation.OverscrollEffect import androidx.compose.foundation.gestures.FlingBehavior diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatMessageHeightMemory.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/list/ChatMessageHeightMemory.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatMessageHeightMemory.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/list/ChatMessageHeightMemory.kt index 277ca85ffb..284b28c5ce 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatMessageHeightMemory.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/list/ChatMessageHeightMemory.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.list import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScrollExtensions.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/list/ChatScrollExtensions.kt similarity index 91% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScrollExtensions.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/list/ChatScrollExtensions.kt index c1519b0396..09102ef5e8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScrollExtensions.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/list/ChatScrollExtensions.kt @@ -1,8 +1,8 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.list import androidx.compose.foundation.gestures.animateScrollBy import androidx.compose.foundation.lazy.LazyListState as ComposeLazyListState -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyListState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyListState /** * Scrolls to the actual end of the list so the trailing edge of the final item stays aligned with diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/util/MentionTokenUtils.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/mentions/MentionTokenUtils.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/util/MentionTokenUtils.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/mentions/MentionTokenUtils.kt index d8625962ec..8473930eaa 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/util/MentionTokenUtils.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/mentions/MentionTokenUtils.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.util +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.mentions data class MentionTokenRange( val triggerChar: Char, diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/CharacterSelectorTarget.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/CharacterSelectorTarget.kt new file mode 100644 index 0000000000..45a660bd62 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/CharacterSelectorTarget.kt @@ -0,0 +1,7 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.model + +/** 聊天界面与状态管理共用的声明,独立归位以保持引用方向清晰。 */ +sealed interface CharacterSelectorTarget { + data class CharacterCardTarget(val id: String) : CharacterSelectorTarget + data class CharacterGroupTarget(val id: String) : CharacterSelectorTarget +} diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatBatchModels.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatBatchModels.kt new file mode 100644 index 0000000000..6b02d73536 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatBatchModels.kt @@ -0,0 +1,10 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.model + +/** 聊天界面与状态管理共用的声明,独立归位以保持引用方向清晰。 */ +enum class ChatBatchAction { SUMMARIZE_TITLES, ARCHIVE, UNARCHIVE, LOCK, UNLOCK, DELETE } + +enum class ChatBatchItemResult { SUCCEEDED, SKIPPED, FAILED } + +data class ChatBatchProgress(val action: ChatBatchAction, val completed: Int, val total: Int) + +data class ChatBatchSummary(val succeeded: Int, val skipped: Int, val failed: Int) diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatHistoryDisplayMode.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatHistoryDisplayMode.kt new file mode 100644 index 0000000000..4029a4c773 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatHistoryDisplayMode.kt @@ -0,0 +1,8 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.model + +/** 聊天界面与状态管理共用的声明,独立归位以保持引用方向清晰。 */ +enum class ChatHistoryDisplayMode { + BY_CHARACTER_CARD, + BY_FOLDER, + CURRENT_CHARACTER_ONLY +} diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatStyle.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatStyle.kt new file mode 100644 index 0000000000..76f06bca70 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatStyle.kt @@ -0,0 +1,7 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.model + +/** 聊天界面与状态管理共用的声明,独立归位以保持引用方向清晰。 */ +enum class ChatStyle { + CURSOR, + BUBBLE +} diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/PendingQueueMessageItem.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/PendingQueueMessageItem.kt new file mode 100644 index 0000000000..74006cfb40 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/PendingQueueMessageItem.kt @@ -0,0 +1,7 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.model + +/** 聊天界面与状态管理共用的声明,独立归位以保持引用方向清晰。 */ +data class PendingQueueMessageItem( + val id: Long, + val text: String +) diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/TranslationUiState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/TranslationUiState.kt new file mode 100644 index 0000000000..b470360b97 --- /dev/null +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/TranslationUiState.kt @@ -0,0 +1,9 @@ +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.model + +/** 聊天界面与状态管理共用的声明,独立归位以保持引用方向清晰。 */ +data class TranslationUiState( + val isLoading: Boolean = false, + val translatedText: String? = null, + val errorMessage: String? = null, + val isFromCache: Boolean = false, +) diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SimpleLinearProgressIndicator.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/progress/SimpleLinearProgressIndicator.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SimpleLinearProgressIndicator.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/progress/SimpleLinearProgressIndicator.kt index bbc3ca6320..897e3b3f0d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SimpleLinearProgressIndicator.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/progress/SimpleLinearProgressIndicator.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.progress import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/RevisableTextStreamRemember.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/stream/RevisableTextStreamRemember.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/RevisableTextStreamRemember.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/stream/RevisableTextStreamRemember.kt index ed85ffd126..5c9204e1d8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/RevisableTextStreamRemember.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/stream/RevisableTextStreamRemember.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.stream import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentChip.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentChip.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentChip.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentChip.kt index f611660e59..01df7bdb82 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentChip.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentChip.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments import android.net.Uri import androidx.compose.foundation.border @@ -39,8 +39,8 @@ import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import com.ai.assistance.operit.R import com.ai.assistance.operit.data.model.AttachmentInfo -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.images.AttachmentImagePreviewDialog -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.images.AttachmentPreviewImage +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images.AttachmentImagePreviewDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images.AttachmentPreviewImage import java.io.File @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentPreview.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentPreview.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentPreview.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentPreview.kt index a2b2125b0e..ea3d96b9ed 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentPreview.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentPreview.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -33,7 +33,6 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R import com.ai.assistance.operit.data.model.AttachmentInfo -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.AttachmentUtils /** A component that shows previews of attachments to be sent with a message */ @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentSelector.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentSelector.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentSelector.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentSelector.kt index 720d26bbf1..b60ee40400 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentSelector.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentSelector.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -78,7 +78,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import androidx.compose.ui.window.PopupProperties import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.images.ChatImagePickerDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images.ChatImagePickerDialog import com.ai.assistance.operit.core.tools.AIToolHandler import com.ai.assistance.operit.core.tools.packTool.PackageManager as ToolPackageManager import com.ai.assistance.operit.data.skill.SkillRepository diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/AttachmentUtils.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentUtils.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/AttachmentUtils.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentUtils.kt index 67158d6792..47a719633a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/AttachmentUtils.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentUtils.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments import com.ai.assistance.operit.data.model.AttachmentInfo diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/MediaFileGuard.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/MediaFileGuard.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/MediaFileGuard.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/MediaFileGuard.kt index 07bc82df55..067a83cb37 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/MediaFileGuard.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/MediaFileGuard.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments import android.content.Context import android.net.Uri diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/PastedTextAttachment.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/PastedTextAttachment.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/PastedTextAttachment.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/PastedTextAttachment.kt index 7505330136..6e0c81714e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/PastedTextAttachment.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/PastedTextAttachment.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments import androidx.compose.ui.text.input.TextFieldValue diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/AttachmentImagePreviewDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/AttachmentImagePreviewDialog.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/AttachmentImagePreviewDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/AttachmentImagePreviewDialog.kt index 329506cea7..b427ebf8a1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/AttachmentImagePreviewDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/AttachmentImagePreviewDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import android.net.Uri import androidx.compose.foundation.ExperimentalFoundationApi @@ -59,9 +59,9 @@ import androidx.compose.ui.window.DialogProperties import coil.compose.AsyncImage import coil.request.ImageRequest import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.MediaFileUnavailableTag -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.mediaPreviewUri -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.rememberMediaPreviewRevision +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.MediaFileUnavailableTag +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.mediaPreviewUri +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.rememberMediaPreviewRevision import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ChatImagePickerDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ChatImagePickerDialog.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ChatImagePickerDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ChatImagePickerDialog.kt index cca511e3cb..01640d6870 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ChatImagePickerDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ChatImagePickerDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import android.content.Intent import android.net.Uri diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ExpiredImageGroupTag.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ExpiredImageGroupTag.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ExpiredImageGroupTag.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ExpiredImageGroupTag.kt index 0f1304f986..523a990443 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ExpiredImageGroupTag.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ExpiredImageGroupTag.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/GalleryDragSelection.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/GalleryDragSelection.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/GalleryDragSelection.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/GalleryDragSelection.kt index ac1a9c5ff2..32483bf352 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/GalleryDragSelection.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/GalleryDragSelection.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import androidx.compose.foundation.gestures.awaitEachGesture import androidx.compose.foundation.gestures.awaitFirstDown diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ImagePreviewTransform.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ImagePreviewTransform.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ImagePreviewTransform.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ImagePreviewTransform.kt index 1621b3ceed..7fba2bdbb5 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ImagePreviewTransform.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ImagePreviewTransform.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/MediaStoreImageRepository.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/MediaStoreImageRepository.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/MediaStoreImageRepository.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/MediaStoreImageRepository.kt index 8ff3c69f0b..ab8e0973ed 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/MediaStoreImageRepository.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/MediaStoreImageRepository.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import android.Manifest import android.content.ContentUris diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageGroup.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageGroup.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageGroup.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageGroup.kt index 690ed43190..52175313db 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageGroup.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageGroup.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import android.net.Uri import androidx.compose.foundation.BorderStroke @@ -16,9 +16,9 @@ import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.common.oktoast.OKToast -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.MediaFileUnavailableTag -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.mediaPreviewUri -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.rememberMediaPreviewRevision +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.MediaFileUnavailableTag +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.mediaPreviewUri +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.rememberMediaPreviewRevision import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.util.media.ImagePoolManager import kotlinx.coroutines.CancellationException diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageSources.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageSources.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageSources.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageSources.kt index 75c86d3954..ec6700e370 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageSources.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageSources.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import com.ai.assistance.operit.core.chat.media.MediaLinkParser import com.ai.assistance.operit.core.chat.protocol.ChatMarkupRegex diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedFileTargetDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/imports/SharedFileTargetDialog.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedFileTargetDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/imports/SharedFileTargetDialog.kt index e60fff9eb1..bbd8ae478d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedFileTargetDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/imports/SharedFileTargetDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.imports import android.net.Uri import androidx.compose.foundation.layout.Arrangement diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedPackageImportChoiceDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/imports/SharedPackageImportChoiceDialog.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedPackageImportChoiceDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/imports/SharedPackageImportChoiceDialog.kt index 8ec578c70f..541edb480b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedPackageImportChoiceDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/imports/SharedPackageImportChoiceDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.imports import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/AttachmentViewerDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/AttachmentViewerDialog.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/AttachmentViewerDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/AttachmentViewerDialog.kt index cb7dcaa839..d75af47098 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/AttachmentViewerDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/AttachmentViewerDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.attachments +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -56,11 +56,11 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.core.content.FileProvider import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.MediaFileUnavailableTag -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.mediaPreviewUri -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.rememberMediaPreviewRevision -import com.ai.assistance.operit.ui.features.conversation.chat.components.compactDialogHeightWhenShort -import com.ai.assistance.operit.ui.features.conversation.chat.components.rememberCompactDialogMetrics +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.MediaFileUnavailableTag +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.mediaPreviewUri +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.rememberMediaPreviewRevision +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.compactDialogHeightWhenShort +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.rememberCompactDialogMetrics import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.util.media.ImageBitmapLimiter import com.ai.assistance.operit.util.media.MediaBase64Limiter diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/AudioAttachmentPlayer.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/AudioAttachmentPlayer.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/AudioAttachmentPlayer.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/AudioAttachmentPlayer.kt index d654ebd471..73f85955b0 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/AudioAttachmentPlayer.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/AudioAttachmentPlayer.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.attachments +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview import android.net.Uri import androidx.compose.runtime.DisposableEffect diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/VideoAttachmentPlayer.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/VideoAttachmentPlayer.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/VideoAttachmentPlayer.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/VideoAttachmentPlayer.kt index ce3839414f..f89233aea8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/VideoAttachmentPlayer.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/VideoAttachmentPlayer.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.attachments +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview import android.net.Uri import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/CharacterSelectorPanel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/characters/CharacterSelectorPanel.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/CharacterSelectorPanel.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/characters/CharacterSelectorPanel.kt index 8d7af364c2..fe208e3118 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/CharacterSelectorPanel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/characters/CharacterSelectorPanel.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.characters import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween @@ -42,6 +42,7 @@ import com.ai.assistance.operit.data.preferences.ActivePromptManager import com.ai.assistance.operit.data.model.ActivePrompt import com.ai.assistance.operit.data.preferences.UserPreferencesManager import com.ai.assistance.operit.ui.common.rememberLocal +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.CharacterSelectorTarget import android.net.Uri import androidx.compose.foundation.Image import androidx.compose.ui.layout.ContentScale @@ -54,11 +55,6 @@ private enum class CharacterSelectorSortOption { CREATED_DESC } -sealed interface CharacterSelectorTarget { - data class CharacterCardTarget(val id: String) : CharacterSelectorTarget - data class CharacterGroupTarget(val id: String) : CharacterSelectorTarget -} - private fun applyCharacterSelectorSort( cards: List, sortOptionName: String diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ExportDialogs.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/ExportDialogs.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ExportDialogs.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/ExportDialogs.kt index f5d95c1810..641ae848e8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ExportDialogs.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/ExportDialogs.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.export import android.content.Context import android.graphics.BitmapFactory @@ -34,16 +34,19 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.ai.assistance.operit.data.resources.OfflineResources -import com.ai.assistance.operit.ui.features.conversation.chat.export.htmlpackager.PackagerPlatformDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.htmlpackager.PackagerPlatformDialog import com.ai.assistance.operit.core.subpack.ApkEditor import com.ai.assistance.operit.core.subpack.ExeEditor import com.ai.assistance.operit.core.subpack.KeyStoreHelper import com.ai.assistance.operit.ui.common.rememberLocal import com.ai.assistance.operit.data.serialization.UriSerializer +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.compactDialogHeightOrWrapContent +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.rememberCompactDialogMetrics +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.rememberCompactDialogScrollState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.verticalScrollWhenShort import java.io.File import java.io.FileInputStream import java.io.FileOutputStream diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/HtmlPackagerScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/htmlpackager/HtmlPackagerScreen.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/HtmlPackagerScreen.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/htmlpackager/HtmlPackagerScreen.kt index fae329ef8a..8e6aee1175 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/HtmlPackagerScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/htmlpackager/HtmlPackagerScreen.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.export.htmlpackager +package com.ai.assistance.operit.ui.features.conversation.chat.modules.export.htmlpackager import android.content.Context import android.net.Uri @@ -26,13 +26,13 @@ import com.ai.assistance.operit.core.tools.AIToolHandler import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.ui.components.CustomScaffold -import com.ai.assistance.operit.ui.features.conversation.chat.components.AndroidExportDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.ExportCompleteDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.ExportPlatformDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.ExportProgressDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.WindowsExportDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.exportAndroidApp -import com.ai.assistance.operit.ui.features.conversation.chat.components.exportWindowsApp +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.AndroidExportDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.ExportCompleteDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.ExportPlatformDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.ExportProgressDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.WindowsExportDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.exportAndroidApp +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.exportWindowsApp import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/PackagerResources.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/htmlpackager/PackagerResources.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/PackagerResources.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/htmlpackager/PackagerResources.kt index c49fd426b5..ce0e4fd4e4 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/PackagerResources.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/htmlpackager/PackagerResources.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.export.htmlpackager +package com.ai.assistance.operit.ui.features.conversation.chat.modules.export.htmlpackager import android.content.Context import android.content.Intent diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/archive/ChatArchiveFilter.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/ChatArchiveFilter.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/archive/ChatArchiveFilter.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/ChatArchiveFilter.kt index 7740bc7252..6821ea4cf0 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/archive/ChatArchiveFilter.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/ChatArchiveFilter.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.archive +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatHistorySelector.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/ChatHistorySelector.kt similarity index 84% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatHistorySelector.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/ChatHistorySelector.kt index 6dedd3bae0..17def88129 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatHistorySelector.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/ChatHistorySelector.kt @@ -1,14 +1,14 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history import androidx.compose.foundation.lazy.LazyListState import androidx.compose.runtime.Composable -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchAction -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchProgress +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchAction +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchProgress import androidx.compose.ui.Modifier import com.ai.assistance.operit.data.model.ActivePrompt import com.ai.assistance.operit.data.model.ChatHistory -import com.ai.assistance.operit.ui.features.conversation.chat.folders.FolderChatHistoryPanel -import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatHistoryDisplayMode +import com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders.FolderChatHistoryPanel +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatHistoryDisplayMode /** 保留聊天页现有面板入口,目录布局与行为由独立组件维护。 */ @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchControls.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/batch/ChatBatchControls.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchControls.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/batch/ChatBatchControls.kt index 4265cb7366..c7b7398dc8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchControls.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/batch/ChatBatchControls.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.batch +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history.batch import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape @@ -22,6 +22,8 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R import com.ai.assistance.operit.data.model.ChatHistory +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchAction +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchProgress @Composable internal fun ChatBatchSelectionHeader( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchMoveDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/batch/ChatBatchMoveDialog.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchMoveDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/batch/ChatBatchMoveDialog.kt index eb8dd426ef..62076d2efb 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchMoveDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/batch/ChatBatchMoveDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.batch +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history.batch import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/ChatFolderTree.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/ChatFolderTree.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/ChatFolderTree.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/ChatFolderTree.kt index 06688af78d..d298a7b156 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/ChatFolderTree.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/ChatFolderTree.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.folders +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders import com.ai.assistance.operit.data.chat.folders.ChatFolder import com.ai.assistance.operit.data.chat.folders.ChatFolderBinding diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderChatHistoryPanel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderChatHistoryPanel.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderChatHistoryPanel.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderChatHistoryPanel.kt index 050765255e..00a2e9dba5 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderChatHistoryPanel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderChatHistoryPanel.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.folders +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn @@ -7,7 +7,6 @@ import androidx.compose.animation.expandVertically import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.layout.* import androidx.compose.material.icons.outlined.Checklist -import com.ai.assistance.operit.ui.features.conversation.chat.batch.* import androidx.compose.foundation.border import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.shape.RoundedCornerShape @@ -19,7 +18,7 @@ import androidx.compose.material.icons.filled.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable -import com.ai.assistance.operit.ui.features.conversation.chat.archive.ChatArchiveFilter +import com.ai.assistance.operit.ui.features.conversation.chat.modules.history.ChatArchiveFilter import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -42,7 +41,7 @@ import com.ai.assistance.operit.data.preferences.CharacterGroupCardManager import com.ai.assistance.operit.data.repository.ChatHistoryManager import com.ai.assistance.operit.ui.common.rememberLocal import com.ai.assistance.operit.ui.common.oktoast.OKToast -import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatHistoryDisplayMode +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatHistoryDisplayMode import com.ai.assistance.operit.util.logging.AppLogger import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers @@ -51,12 +50,12 @@ import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchAction -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchActionBar -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchDeleteDialog -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchMoveDialog -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchProgress -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchSelectionHeader +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchAction +import com.ai.assistance.operit.ui.features.conversation.chat.modules.history.batch.ChatBatchActionBar +import com.ai.assistance.operit.ui.features.conversation.chat.modules.history.batch.ChatBatchDeleteDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.history.batch.ChatBatchMoveDialog +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchProgress +import com.ai.assistance.operit.ui.features.conversation.chat.modules.history.batch.ChatBatchSelectionHeader private data class FolderEditRequest( val folder: ChatFolder? = null, val parentId: String? = null, diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderHistoryDialogs.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderHistoryDialogs.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderHistoryDialogs.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderHistoryDialogs.kt index 02ae2e5ee9..3eb5c6d512 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderHistoryDialogs.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderHistoryDialogs.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.folders +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -23,7 +23,7 @@ import com.ai.assistance.operit.data.chat.folders.ChatFolderNode import com.ai.assistance.operit.data.chat.folders.canMoveFolder import com.ai.assistance.operit.data.chat.folders.folderAncestors import com.ai.assistance.operit.data.model.ChatHistory -import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatHistoryDisplayMode +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatHistoryDisplayMode internal data class HistoryAction(val label: String, val icon: ImageVector, val enabled: Boolean = true, val action: () -> Unit) internal data class HistoryBindingOption(val label: String, val binding: ChatFolderBinding) diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderTreeList.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderTreeList.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderTreeList.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderTreeList.kt index 009ddb4c95..f8f34d0fb5 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderTreeList.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderTreeList.kt @@ -1,10 +1,10 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.folders +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders import com.ai.assistance.operit.data.preferences.glass.GlassRegion import com.ai.assistance.operit.ui.theme.glass.rememberGlassAppearance import com.ai.assistance.operit.ui.theme.liquidGlass -import com.ai.assistance.operit.ui.features.conversation.chat.motion.DissolvingChatTitle +import com.ai.assistance.operit.ui.features.conversation.chat.modules.history.motion.DissolvingChatTitle import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.selection.toggleable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/HistoryCreateCapsule.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/HistoryCreateCapsule.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/HistoryCreateCapsule.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/HistoryCreateCapsule.kt index 3f58ff51f9..c251db4d4a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/HistoryCreateCapsule.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/HistoryCreateCapsule.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.folders +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/HistoryQuickScroller.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/HistoryQuickScroller.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/HistoryQuickScroller.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/HistoryQuickScroller.kt index adf0502d0d..6b872f4ab2 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/HistoryQuickScroller.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/HistoryQuickScroller.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.folders +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders import androidx.compose.foundation.background import androidx.compose.foundation.gestures.awaitEachGesture diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/DissolvingChatTitle.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/motion/DissolvingChatTitle.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/DissolvingChatTitle.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/motion/DissolvingChatTitle.kt index 39a41b38e5..c2731b646a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/DissolvingChatTitle.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/motion/DissolvingChatTitle.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.motion +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history.motion import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/FullscreenInputDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/FullscreenInputDialog.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/FullscreenInputDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/FullscreenInputDialog.kt index 46697844a7..8bab712fab 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/FullscreenInputDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/FullscreenInputDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons @@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.rememberMentionVisualTransformation +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.rememberMentionVisualTransformation @Composable fun FullscreenInputDialog( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/agent/AgentChatInputSection.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/agent/AgentChatInputSection.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/agent/AgentChatInputSection.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/agent/AgentChatInputSection.kt index 4a89bbcdae..f68e525e2a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/agent/AgentChatInputSection.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/agent/AgentChatInputSection.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.agent +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.agent import androidx.compose.material.icons.filled.Mic @@ -8,8 +8,8 @@ import com.ai.assistance.operit.data.preferences.glass.GlassRegion import com.ai.assistance.operit.ui.common.oktoast.OKToast import androidx.compose.material3.HorizontalDivider -import com.ai.assistance.operit.ui.features.conversation.chat.components.context.ChatContextUsageEntry -import com.ai.assistance.operit.ui.features.conversation.chat.components.context.ChatContextUsageDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.usage.ChatContextUsageEntry +import com.ai.assistance.operit.ui.features.conversation.chat.modules.usage.ChatContextUsageDialog import android.net.Uri import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts @@ -139,20 +139,20 @@ import com.ai.assistance.operit.data.preferences.UserPreferencesManager import com.ai.assistance.operit.data.repository.MemoryAutoSaveCandidateRepository import com.ai.assistance.operit.ui.common.icons.MaterialIconNameResolver import com.ai.assistance.operit.ui.common.animations.SimpleAnimatedVisibility -import com.ai.assistance.operit.ui.features.conversation.chat.components.AttachmentChip -import com.ai.assistance.operit.ui.features.conversation.chat.components.AttachmentSelectorPopupPanel -import com.ai.assistance.operit.ui.features.conversation.chat.components.FullscreenInputDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.CharacterCardMemoryBindingSwitchConfirmDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.CharacterCardModelBindingSwitchConfirmDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuToggleHookParams -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuToggleDefinition -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuTogglePluginRegistry -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuToggleSlots -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.PendingMessageQueuePanel -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ThinkingQualitySlider -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.PendingQueueMessageItem -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ToolPromptManagerDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.rememberMentionVisualTransformation +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.AttachmentChip +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.AttachmentSelectorPopupPanel +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.FullscreenInputDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.CharacterCardMemoryBindingSwitchConfirmDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.CharacterCardModelBindingSwitchConfirmDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuToggleHookParams +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuToggleDefinition +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuTogglePluginRegistry +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuToggleSlots +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.PendingMessageQueuePanel +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ThinkingQualitySlider +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.PendingQueueMessageItem +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ToolPromptManagerDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.rememberMentionVisualTransformation import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel import com.ai.assistance.operit.ui.floating.FloatingMode import com.ai.assistance.operit.ui.permissions.PermissionLevel diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatInputSection.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/classic/ClassicChatInputSection.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatInputSection.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/classic/ClassicChatInputSection.kt index 8dadbeedd7..46a7496ceb 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatInputSection.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/classic/ClassicChatInputSection.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.classic +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.classic import androidx.compose.material.icons.filled.Mic @@ -66,13 +66,13 @@ import com.ai.assistance.operit.data.model.InputProcessingState import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.core.tools.ToolProgressBus import com.ai.assistance.operit.ui.common.animations.SimpleAnimatedVisibility -import com.ai.assistance.operit.ui.features.conversation.chat.components.AttachmentChip -import com.ai.assistance.operit.ui.features.conversation.chat.components.AttachmentSelectorPanel -import com.ai.assistance.operit.ui.features.conversation.chat.components.FullscreenInputDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.rememberMentionVisualTransformation -import com.ai.assistance.operit.ui.features.conversation.chat.components.SimpleLinearProgressIndicator -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.PendingMessageQueuePanel -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.PendingQueueMessageItem +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.AttachmentChip +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.AttachmentSelectorPanel +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.FullscreenInputDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.rememberMentionVisualTransformation +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.progress.SimpleLinearProgressIndicator +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.PendingMessageQueuePanel +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.PendingQueueMessageItem import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel import com.ai.assistance.operit.ui.floating.FloatingMode import com.ai.assistance.operit.ui.theme.isLiquidGlassSupported diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatSettingsBar.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/classic/ClassicChatSettingsBar.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatSettingsBar.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/classic/ClassicChatSettingsBar.kt index 560d99eb9d..81e2fb2c17 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatSettingsBar.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/classic/ClassicChatSettingsBar.kt @@ -1,9 +1,9 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.classic +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.classic import com.ai.assistance.operit.ui.common.oktoast.OKToast -import com.ai.assistance.operit.ui.features.conversation.chat.components.context.ChatContextUsageEntry -import com.ai.assistance.operit.ui.features.conversation.chat.components.context.ChatContextUsageDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.usage.ChatContextUsageEntry +import com.ai.assistance.operit.ui.features.conversation.chat.modules.usage.ChatContextUsageDialog import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState @@ -74,14 +74,14 @@ import com.ai.assistance.operit.data.repository.MemoryAutoSaveCandidateRepositor import com.ai.assistance.operit.ui.common.icons.MaterialIconNameResolver import com.ai.assistance.operit.ui.common.icons.providerLogoColorFilter import com.ai.assistance.operit.ui.common.icons.rememberProviderLogoPainter -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuToggleHookParams -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuToggleDefinition -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuTogglePluginRegistry -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.InputMenuToggleSlots -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.CharacterCardMemoryBindingSwitchConfirmDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.CharacterCardModelBindingSwitchConfirmDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ToolPromptManagerDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ThinkingQualitySlider +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuToggleHookParams +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuToggleDefinition +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuTogglePluginRegistry +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.InputMenuToggleSlots +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.CharacterCardMemoryBindingSwitchConfirmDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.CharacterCardModelBindingSwitchConfirmDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ToolPromptManagerDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ThinkingQualitySlider import com.ai.assistance.operit.ui.permissions.PermissionLevel import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/CharacterCardMemoryBindingSwitchConfirmDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/CharacterCardMemoryBindingSwitchConfirmDialog.kt similarity index 91% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/CharacterCardMemoryBindingSwitchConfirmDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/CharacterCardMemoryBindingSwitchConfirmDialog.kt index 56d5663578..1890b9ad29 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/CharacterCardMemoryBindingSwitchConfirmDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/CharacterCardMemoryBindingSwitchConfirmDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common import androidx.compose.material3.AlertDialog import androidx.compose.material3.Text diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/CharacterCardModelBindingSwitchConfirmDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/CharacterCardModelBindingSwitchConfirmDialog.kt similarity index 91% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/CharacterCardModelBindingSwitchConfirmDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/CharacterCardModelBindingSwitchConfirmDialog.kt index 6a4b47f031..d6a2cd8535 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/CharacterCardModelBindingSwitchConfirmDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/CharacterCardModelBindingSwitchConfirmDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common import androidx.compose.material3.AlertDialog import androidx.compose.material3.Text diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ChatInputHookRegistry.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ChatInputHookRegistry.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ChatInputHookRegistry.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ChatInputHookRegistry.kt index 5f5221af11..8ef1fd3db2 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ChatInputHookRegistry.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ChatInputHookRegistry.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/InputMenuTogglePluginRegistry.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/InputMenuTogglePluginRegistry.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/InputMenuTogglePluginRegistry.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/InputMenuTogglePluginRegistry.kt index 9916cf95d4..cfe702f04d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/InputMenuTogglePluginRegistry.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/InputMenuTogglePluginRegistry.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common import androidx.annotation.StringRes import java.util.concurrent.CopyOnWriteArrayList diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/MentionVisualTransformation.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/MentionVisualTransformation.kt similarity index 92% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/MentionVisualTransformation.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/MentionVisualTransformation.kt index dde0875f78..4f335dd345 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/MentionVisualTransformation.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/MentionVisualTransformation.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable @@ -15,7 +15,7 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.isUnspecified import androidx.compose.ui.unit.sp -import com.ai.assistance.operit.ui.features.conversation.chat.util.findCommittedMentionTokens +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.mentions.findCommittedMentionTokens @Composable fun rememberMentionVisualTransformation(textStyle: TextStyle): VisualTransformation { diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/PendingMessageQueuePanel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/PendingMessageQueuePanel.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/PendingMessageQueuePanel.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/PendingMessageQueuePanel.kt index dbca2e893a..129d0fcd18 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/PendingMessageQueuePanel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/PendingMessageQueuePanel.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -33,11 +33,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R - -data class PendingQueueMessageItem( - val id: Long, - val text: String -) +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.PendingQueueMessageItem @Composable fun PendingMessageQueuePanel( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ThinkingQualitySlider.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ThinkingQualitySlider.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ThinkingQualitySlider.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ThinkingQualitySlider.kt index b77ef2715a..c8870a8b71 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ThinkingQualitySlider.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ThinkingQualitySlider.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.LinearEasing diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ToolPromptManagerDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ToolPromptManagerDialog.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ToolPromptManagerDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ToolPromptManagerDialog.kt index b04eae21fa..8e622aecfd 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ToolPromptManagerDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ToolPromptManagerDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common import androidx.compose.animation.core.spring import androidx.compose.foundation.clickable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MemoryFolderSelectionDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/memory/MemoryFolderSelectionDialog.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MemoryFolderSelectionDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/memory/MemoryFolderSelectionDialog.kt index e9ef21b8b1..33d67ab2dd 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MemoryFolderSelectionDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/memory/MemoryFolderSelectionDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.memory import android.content.Context import com.ai.assistance.operit.util.logging.AppLogger diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceFileSelector.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/mentions/MentionSuggestionPanel.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceFileSelector.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/mentions/MentionSuggestionPanel.kt index b1d4325073..bef42b2e75 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceFileSelector.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/mentions/MentionSuggestionPanel.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview +package com.ai.assistance.operit.ui.features.conversation.chat.modules.input.mentions import com.ai.assistance.operit.data.preferences.glass.GlassRegion import android.content.Context @@ -45,7 +45,7 @@ import com.ai.assistance.operit.core.tools.AIToolHandler import com.ai.assistance.operit.core.tools.packTool.PackageManager as ToolPackageManager import com.ai.assistance.operit.data.skill.SkillRepository import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.GitIgnoreFilter +import com.ai.assistance.operit.ui.features.conversation.workspace.process.GitIgnoreFilter import com.ai.assistance.operit.ui.theme.isLiquidGlassSupported import com.ai.assistance.operit.ui.theme.isWaterGlassSupported import com.ai.assistance.operit.ui.theme.liquidGlass diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatArea.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/ChatArea.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatArea.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/ChatArea.kt index 10b5242783..dc036ffca3 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatArea.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/ChatArea.kt @@ -1,9 +1,9 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages import com.ai.assistance.operit.ui.common.oktoast.OKToast import androidx.compose.material.icons.filled.Translate -import com.ai.assistance.operit.ui.features.conversation.chat.components.timeline.ChatMessageSlice +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline.ChatMessageSlice import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items @@ -13,8 +13,8 @@ import androidx.compose.runtime.collectAsState import com.ai.assistance.operit.data.preferences.DisplayPreferencesManager import com.ai.assistance.operit.data.preferences.ToolCollapseMode import com.ai.assistance.operit.ui.common.markdown.lazy.LocalMarkdownRenderFragment -import com.ai.assistance.operit.ui.features.conversation.chat.components.timeline.LocalChatMessageSlice -import com.ai.assistance.operit.ui.features.conversation.chat.components.timeline.rememberChatTimelineEntries +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline.LocalChatMessageSlice +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline.rememberChatTimelineEntries import androidx.compose.animation.core.RepeatMode import androidx.compose.animation.core.StartOffset import androidx.compose.animation.core.animateFloat @@ -67,7 +67,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.saveable.rememberSaveableStateHolder -import com.ai.assistance.operit.ui.features.conversation.chat.copy.MessageCopyTextField +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.copy.MessageCopyTextField import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -100,12 +100,12 @@ import androidx.compose.ui.unit.sp import com.ai.assistance.operit.R import com.ai.assistance.operit.data.model.AiReference import com.ai.assistance.operit.data.model.ChatMessage -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.MessageGenerationDetails -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.formatMessageCompletionTime -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.hasDisplayableMessageTimestamp -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.hasDisplayableTimingStats -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.hasDisplayableTokenSpeedStats -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.hasDisplayableTokenStats +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details.MessageGenerationDetails +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details.formatMessageCompletionTime +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details.hasDisplayableMessageTimestamp +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details.hasDisplayableTimingStats +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details.hasDisplayableTokenSpeedStats +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details.hasDisplayableTokenStats import com.ai.assistance.operit.data.model.MessageSectionCodec import com.ai.assistance.operit.data.model.MessageSection import com.ai.assistance.operit.data.model.ChatMessageDisplayMode @@ -130,13 +130,17 @@ import com.ai.assistance.operit.plugins.chatmessage.ChatMessageMenuItemRegistry import com.ai.assistance.operit.ui.common.composedsl.ToolPkgComposeDslDialogHost import com.ai.assistance.operit.ui.common.icons.MaterialIconNameResolver import com.ai.assistance.operit.ui.common.markdown.markdownToPlainTextForCopy -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor.CursorStyleChatMessage -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble.BubbleImageStyleConfig -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble.BubbleStyleChatMessage +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor.CursorStyleChatMessage +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble.BubbleImageStyleConfig +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble.BubbleStyleChatMessage import com.ai.assistance.operit.ui.theme.LocalThemePreferenceSnapshot import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.core.chat.protocol.ChatMarkupRegex import com.ai.assistance.operit.util.markdown.LatexMathMlConverter +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.animateScrollToEnd +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatStyle +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details.MessageInfoDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.navigation.ChatScrollNavigator import kotlin.math.roundToInt import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -197,11 +201,6 @@ private fun isHiddenUserPlaceholder(message: ChatMessage): Boolean { message.displayMode == ChatMessageDisplayMode.HIDDEN_PLACEHOLDER } -enum class ChatStyle { - CURSOR, - BUBBLE -} - @Composable fun ChatArea( chatHistory: List, diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/WorkspaceChangeConfirmDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/actions/WorkspaceChangeConfirmDialog.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/WorkspaceChangeConfirmDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/actions/WorkspaceChangeConfirmDialog.kt index 4b4048a9d3..2095553a4a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/WorkspaceChangeConfirmDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/actions/WorkspaceChangeConfirmDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.actions import androidx.compose.foundation.background import androidx.compose.foundation.layout.* @@ -27,7 +27,9 @@ import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import androidx.compose.material3.Icon import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceBackupManager +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceBackupManager +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.compactDialogHeightOrWrapContent +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.rememberCompactDialogMetrics enum class WorkspaceChangeConfirmMode { ROLLBACK, diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/copy/MessageCopyTextField.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/copy/MessageCopyTextField.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/copy/MessageCopyTextField.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/copy/MessageCopyTextField.kt index bd8798ba70..fc214b9b5f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/copy/MessageCopyTextField.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/copy/MessageCopyTextField.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.copy +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.copy import androidx.compose.foundation.ScrollState import androidx.compose.foundation.text.BasicTextField diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageGenerationDetails.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageGenerationDetails.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageGenerationDetails.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageGenerationDetails.kt index acc1023cf8..efcf6f9f77 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageGenerationDetails.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageGenerationDetails.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.details +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -30,7 +30,7 @@ import androidx.compose.ui.semantics.stateDescription import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R import com.ai.assistance.operit.data.model.ChatMessage -import com.ai.assistance.operit.ui.features.conversation.chat.components.formatCacheHitRate +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.format.formatCacheHitRate internal fun hasDisplayableTokenStats(message: ChatMessage): Boolean { return message.inputTokens > 0L || message.cachedInputTokens > 0L || message.outputTokens > 0L diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageInfoDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageInfoDialog.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageInfoDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageInfoDialog.kt index 7fe5e2c9eb..804de7fabc 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageInfoDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageInfoDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -21,11 +21,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R import com.ai.assistance.operit.data.model.ChatMessage -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.calculateMessageTokenSpeed -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.formatMessageDuration -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.formatMessageNumber -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.formatMessageTokenSpeed -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.messageTokenBreakdownText import java.text.SimpleDateFormat import java.util.Date import java.util.Locale diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageStatsFormatting.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageStatsFormatting.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageStatsFormatting.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageStatsFormatting.kt index d6b51afbd9..a70719c83e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageStatsFormatting.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageStatsFormatting.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.details +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details import java.text.SimpleDateFormat import java.util.Date diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditor.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditor.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditor.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditor.kt index 81c10c19d9..576ab4910d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditor.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditor.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.editor import androidx.annotation.StringRes import androidx.compose.animation.AnimatedVisibility diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditorContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditorContent.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditorContent.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditorContent.kt index c5ee1d1f7f..6bfedd0978 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditorContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditorContent.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.editor import com.ai.assistance.operit.core.chat.protocol.ThinkingMarkup diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/LinkPreviewDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/links/LinkPreviewDialog.kt similarity index 92% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/LinkPreviewDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/links/LinkPreviewDialog.kt index 13f99f2ea8..4f7401ae72 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/LinkPreviewDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/links/LinkPreviewDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.links import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -22,8 +22,12 @@ import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.common.markdown.links.openMarkdownLink -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links.LocalWorkspaceFileLinkOpener -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links.parseWorkspaceFileLink +import com.ai.assistance.operit.ui.features.conversation.workspace.links.LocalWorkspaceFileLinkOpener +import com.ai.assistance.operit.ui.features.conversation.workspace.links.parseWorkspaceFileLink +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.compactDialogHeight +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.rememberCompactDialogMetrics +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.rememberCompactDialogScrollState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.verticalScrollWhenCompact /** * 链接预览弹窗组件 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/NewChatIntro.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/motion/NewChatIntro.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/NewChatIntro.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/motion/NewChatIntro.kt index 41da15a5f3..0e0945aab6 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/NewChatIntro.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/motion/NewChatIntro.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.motion +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.motion import android.animation.ValueAnimator import android.graphics.Bitmap diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScrollNavigator.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/navigation/ChatScrollNavigator.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScrollNavigator.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/navigation/ChatScrollNavigator.kt index d762fb690f..f0739ce4c7 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScrollNavigator.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/navigation/ChatScrollNavigator.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.navigation import androidx.compose.foundation.lazy.LazyListState as ComposeLazyListState import androidx.compose.animation.AnimatedVisibility @@ -67,8 +67,9 @@ import com.ai.assistance.operit.R import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.data.model.ChatMessageDisplayMode import com.ai.assistance.operit.data.model.ChatMessageLocatorPreview -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyListState as ChatLazyListState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyListState as ChatLazyListState import com.ai.assistance.operit.util.logging.AppLogger +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.animateScrollToEnd import kotlinx.coroutines.delay import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.collectLatest diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ScrollToBottomButton.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/navigation/ScrollToBottomButton.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ScrollToBottomButton.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/navigation/ScrollToBottomButton.kt index b9ea7ee8f0..5f23dece79 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ScrollToBottomButton.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/navigation/ScrollToBottomButton.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.navigation import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn @@ -23,7 +23,8 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.ai.assistance.operit.ui.features.conversation.chat.components.lazy.LazyListState as ChatLazyListState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy.LazyListState as ChatLazyListState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.animateScrollToEnd import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ReferencesDisplay.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/references/ReferencesDisplay.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ReferencesDisplay.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/references/ReferencesDisplay.kt index 07444b56bf..311cdc211b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ReferencesDisplay.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/references/ReferencesDisplay.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.references // import androidx.compose.animation.AnimatedVisibility // import androidx.compose.animation.fadeIn diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ChatNodeVisibility.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ChatNodeVisibility.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ChatNodeVisibility.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ChatNodeVisibility.kt index 226816b1a9..a71f399698 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ChatNodeVisibility.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ChatNodeVisibility.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import com.ai.assistance.operit.core.chat.protocol.ChatMarkupRegex import com.ai.assistance.operit.util.markdown.MarkdownNodeStable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/CustomXmlRenderer.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/CustomXmlRenderer.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/CustomXmlRenderer.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/CustomXmlRenderer.kt index c3965fef02..7a8467e2e7 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/CustomXmlRenderer.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/CustomXmlRenderer.kt @@ -1,10 +1,10 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import com.ai.assistance.operit.util.toolmarkup.ToolResultMarkup import com.ai.assistance.operit.ui.common.markdown.lazy.LocalMarkdownCardNodeIndex -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.LocalToolTimingIndex -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.LocalInsideToolGroup -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.toolTimingTitle +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.LocalToolTimingIndex +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.LocalInsideToolGroup +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.toolTimingTitle import com.ai.assistance.operit.ui.common.markdown.lazy.rememberMarkdownCardValue import android.webkit.WebView import android.webkit.WebSettings diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/DetailsTagRenderer.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/DetailsTagRenderer.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/DetailsTagRenderer.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/DetailsTagRenderer.kt index d15cdc94c7..bb55030bf4 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/DetailsTagRenderer.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/DetailsTagRenderer.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import com.ai.assistance.operit.ui.common.markdown.lazy.rememberMarkdownCardValue import androidx.compose.animation.AnimatedVisibility diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/DialogComponents.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/DialogComponents.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/DialogComponents.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/DialogComponents.kt index 576c7cd81c..d00fe84ba7 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/DialogComponents.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/DialogComponents.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import androidx.compose.foundation.background import androidx.compose.foundation.layout.* @@ -25,8 +25,8 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.window.Dialog import com.ai.assistance.operit.R import androidx.compose.ui.window.DialogProperties -import com.ai.assistance.operit.ui.features.conversation.chat.components.compactDialogHeightWhenShort -import com.ai.assistance.operit.ui.features.conversation.chat.components.rememberCompactDialogMetrics +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.compactDialogHeightWhenShort +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.rememberCompactDialogMetrics /** * 通用的内容详情弹窗 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/FileDiffDisplay.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/FileDiffDisplay.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/FileDiffDisplay.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/FileDiffDisplay.kt index 9ef1204320..f002e26a4e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/FileDiffDisplay.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/FileDiffDisplay.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/FontTagRenderer.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/FontTagRenderer.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/FontTagRenderer.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/FontTagRenderer.kt index abebfab88d..fd167fb19a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/FontTagRenderer.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/FontTagRenderer.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ParamVisualizer.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ParamVisualizer.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ParamVisualizer.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ParamVisualizer.kt index 62bd05c250..0e2cbedc28 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ParamVisualizer.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ParamVisualizer.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import androidx.compose.foundation.background import androidx.compose.foundation.layout.* diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/StatusCardHtmlDocument.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/StatusCardHtmlDocument.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/StatusCardHtmlDocument.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/StatusCardHtmlDocument.kt index d7444947ac..ccdd1c7de2 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/StatusCardHtmlDocument.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/StatusCardHtmlDocument.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import android.content.Context import android.util.Base64 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsRows.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsRows.kt similarity index 92% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsRows.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsRows.kt index 9f97aa9862..a838632182 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsRows.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsRows.kt @@ -1,8 +1,8 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import androidx.compose.runtime.Composable -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.ToolTimingSummary -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.toolTimingTitle +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.ToolTimingSummary +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.toolTimingTitle import androidx.compose.ui.res.stringResource import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.common.markdown.MarkdownGroupedItem diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsXmlNodeGrouper.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsXmlNodeGrouper.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsXmlNodeGrouper.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsXmlNodeGrouper.kt index 062b001259..575ab656a2 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsXmlNodeGrouper.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsXmlNodeGrouper.kt @@ -1,9 +1,9 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import androidx.compose.runtime.CompositionLocalProvider -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.ToolTimingIndex -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.LocalToolTimingIndex -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.LocalInsideToolGroup +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.ToolTimingIndex +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.LocalToolTimingIndex +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.LocalInsideToolGroup import com.ai.assistance.operit.ui.common.markdown.lazy.LocalMarkdownCardNodeIndex import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkingMarkdownStream.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkingMarkdownStream.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkingMarkdownStream.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkingMarkdownStream.kt index 1f03d6cc3f..e650aff93f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkingMarkdownStream.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkingMarkdownStream.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import com.ai.assistance.operit.core.chat.protocol.ThinkingMarkup import com.ai.assistance.operit.util.stream.Stream diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ToolDisplayComponents.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ToolDisplayComponents.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ToolDisplayComponents.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ToolDisplayComponents.kt index 704e75720e..e1a4723a03 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ToolDisplayComponents.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ToolDisplayComponents.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ToolResultDisplay.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ToolResultDisplay.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ToolResultDisplay.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ToolResultDisplay.kt index 90026ca6da..5563ba680f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ToolResultDisplay.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ToolResultDisplay.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -25,8 +25,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.components.compactDialogHeightWhenShort -import com.ai.assistance.operit.ui.features.conversation.chat.components.rememberCompactDialogMetrics +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.compactDialogHeightWhenShort +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.rememberCompactDialogMetrics /** 工具执行结果显示组件 简洁风格,显示工具执行结果,无边框,与CompactToolDisplay风格一致 通过缩进和特殊图标区分工具调用和执行结果 支持点击查看详细内容 */ @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/XmlCanvasBlockComponents.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/XmlCanvasBlockComponents.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/XmlCanvasBlockComponents.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/XmlCanvasBlockComponents.kt index c68ca1016d..991adaab42 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/XmlCanvasBlockComponents.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/XmlCanvasBlockComponents.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import androidx.compose.foundation.Canvas import androidx.compose.foundation.clickable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/XmlCanvasSummaryComponents.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/XmlCanvasSummaryComponents.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/XmlCanvasSummaryComponents.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/XmlCanvasSummaryComponents.kt index d869e24163..7da47307da 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/XmlCanvasSummaryComponents.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/XmlCanvasSummaryComponents.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import androidx.compose.foundation.Canvas import androidx.compose.foundation.clickable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingIndex.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingIndex.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingIndex.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingIndex.kt index c2ae2eefa6..12e85d618b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingIndex.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingIndex.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming import com.ai.assistance.operit.core.chat.protocol.ChatMarkupRegex import com.ai.assistance.operit.core.chat.tools.timing.ToolExecutionTiming diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingTitle.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingTitle.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingTitle.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingTitle.kt index 4843dc5b4e..5bbf385f9e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingTitle.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingTitle.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming import android.os.SystemClock import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleAiMessageComposable.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleAiMessageComposable.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleAiMessageComposable.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleAiMessageComposable.kt index 0e8f603ded..8f744a4636 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleAiMessageComposable.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleAiMessageComposable.kt @@ -1,9 +1,9 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble import com.ai.assistance.operit.data.preferences.glass.GlassRegion import com.ai.assistance.operit.data.preferences.transparency.ThemeTransparencyPreferences -import com.ai.assistance.operit.ui.features.conversation.chat.components.timeline.LocalChatMessageSlice -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.rememberMessageToolExecutions +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline.LocalChatMessageSlice +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.rememberMessageToolExecutions import com.ai.assistance.operit.ui.common.markdown.rememberDisplayMessageSections import com.ai.assistance.operit.ui.common.markdown.lazy.LocalMarkdownRenderFragment import android.annotation.SuppressLint @@ -38,11 +38,11 @@ import androidx.compose.ui.unit.dp import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.ui.common.markdown.StreamMarkdownRenderer import com.ai.assistance.operit.ui.common.markdown.StreamMarkdownRendererState -import com.ai.assistance.operit.ui.features.conversation.chat.components.ChatMessageHeightMemory -import com.ai.assistance.operit.ui.features.conversation.chat.components.rememberRevisableTextStream -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.CustomXmlRenderer -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.ThinkToolsXmlNodeGrouper -import com.ai.assistance.operit.ui.features.conversation.chat.components.LinkPreviewDialog +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.ChatMessageHeightMemory +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.stream.rememberRevisableTextStream +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.CustomXmlRenderer +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.ThinkToolsXmlNodeGrouper +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.links.LinkPreviewDialog import com.ai.assistance.operit.util.markdown.toCharStream import com.ai.assistance.operit.data.preferences.UserPreferencesManager import com.ai.assistance.operit.data.preferences.DisplayPreferencesManager diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageBackgroundSurface.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageBackgroundSurface.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageBackgroundSurface.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageBackgroundSurface.kt index a9d88c9b8f..3bf8668e43 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageBackgroundSurface.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageBackgroundSurface.kt @@ -1,10 +1,10 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.Paint import androidx.collection.LruCache -import com.ai.assistance.operit.ui.features.conversation.chat.components.timeline.LocalChatMessageSlice +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline.LocalChatMessageSlice import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageLayout.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageLayout.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageLayout.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageLayout.kt index 0b8591930b..38c899fab7 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageLayout.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageLayout.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble import kotlin.math.max import kotlin.math.roundToInt diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageTiling.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageTiling.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageTiling.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageTiling.kt index 054bd9cae5..756a8ae36b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageTiling.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageTiling.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble import android.graphics.Bitmap import android.graphics.BitmapShader diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleStyleChatMessage.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleStyleChatMessage.kt similarity index 92% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleStyleChatMessage.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleStyleChatMessage.kt index 822e4c0f99..598abf73d1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleStyleChatMessage.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleStyleChatMessage.kt @@ -1,11 +1,11 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import com.ai.assistance.operit.data.model.ChatMessage -import com.ai.assistance.operit.ui.features.conversation.chat.components.ChatMessageHeightMemory -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor.SummaryMessageComposable +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.ChatMessageHeightMemory +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor.SummaryMessageComposable import com.ai.assistance.operit.util.stream.Stream /** diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleUserMessageComposable.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleUserMessageComposable.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleUserMessageComposable.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleUserMessageComposable.kt index 10a74d3bd6..a719cc7538 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleUserMessageComposable.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleUserMessageComposable.kt @@ -1,13 +1,13 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble import com.ai.assistance.operit.core.chat.voice.VoiceMessageMarkup import com.ai.assistance.operit.core.chat.media.unescapeMediaAttribute -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.MediaFileGuard -import com.ai.assistance.operit.ui.features.conversation.chat.voicemessages.VoiceMessagePlayer -import com.ai.assistance.operit.ui.features.conversation.chat.voicemessages.ExpiredVoiceMessageTag -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.rememberMediaFileMissing +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.MediaFileGuard +import com.ai.assistance.operit.ui.features.conversation.chat.modules.voice.VoiceMessagePlayer +import com.ai.assistance.operit.ui.features.conversation.chat.modules.voice.ExpiredVoiceMessageTag +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.rememberMediaFileMissing import com.ai.assistance.operit.data.preferences.glass.GlassRegion -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.images.SentImageGroup -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.images.sentImageSources +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images.SentImageGroup +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images.sentImageSources import com.ai.assistance.operit.data.preferences.transparency.ThemeTransparencyPreferences import android.annotation.SuppressLint @@ -59,9 +59,9 @@ import com.ai.assistance.operit.data.model.ChatMessageDisplayMode import com.ai.assistance.operit.data.preferences.CharacterCardManager import com.ai.assistance.operit.data.preferences.DisplayPreferencesManager import com.ai.assistance.operit.data.preferences.UserPreferencesManager -import com.ai.assistance.operit.ui.features.conversation.chat.components.attachments.AttachmentViewerDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.attachments.ChatAttachment -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.common.HiddenUserMessagePlaceholderContent +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview.AttachmentViewerDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview.ChatAttachment +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.common.HiddenUserMessagePlaceholderContent import com.ai.assistance.operit.core.chat.media.MediaLinkParser import com.ai.assistance.operit.core.chat.protocol.ChatMarkupRegex import com.ai.assistance.operit.ui.theme.applyFontFamilyToTypography diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/common/HiddenUserMessagePlaceholderContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/common/HiddenUserMessagePlaceholderContent.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/common/HiddenUserMessagePlaceholderContent.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/common/HiddenUserMessagePlaceholderContent.kt index 076958c1e9..da03c919c7 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/common/HiddenUserMessagePlaceholderContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/common/HiddenUserMessagePlaceholderContent.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.common +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.common import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/AiMessageComposable.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/AiMessageComposable.kt similarity index 92% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/AiMessageComposable.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/AiMessageComposable.kt index 0454d19ace..718da88287 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/AiMessageComposable.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/AiMessageComposable.kt @@ -1,10 +1,10 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.background import com.ai.assistance.operit.data.preferences.transparency.ThemeTransparencyPreferences -import com.ai.assistance.operit.ui.features.conversation.chat.components.timeline.LocalChatMessageSlice -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.rememberMessageToolExecutions +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline.LocalChatMessageSlice +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.rememberMessageToolExecutions import com.ai.assistance.operit.ui.common.markdown.rememberDisplayMessageSections import com.ai.assistance.operit.ui.common.markdown.lazy.LocalMarkdownRenderFragment import android.content.Intent @@ -25,11 +25,11 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.ui.common.markdown.StreamMarkdownRenderer -import com.ai.assistance.operit.ui.features.conversation.chat.components.ChatMessageHeightMemory -import com.ai.assistance.operit.ui.features.conversation.chat.components.rememberRevisableTextStream -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.CustomXmlRenderer -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.ThinkToolsXmlNodeGrouper -import com.ai.assistance.operit.ui.features.conversation.chat.components.LinkPreviewDialog +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.ChatMessageHeightMemory +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.stream.rememberRevisableTextStream +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.CustomXmlRenderer +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.ThinkToolsXmlNodeGrouper +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.links.LinkPreviewDialog import com.ai.assistance.operit.util.markdown.toCharStream import com.ai.assistance.operit.util.stream.Stream import com.ai.assistance.operit.data.preferences.DisplayPreferencesManager diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/CursorStyleChatMessage.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/CursorStyleChatMessage.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/CursorStyleChatMessage.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/CursorStyleChatMessage.kt index 783bdcd9b6..df770c7927 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/CursorStyleChatMessage.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/CursorStyleChatMessage.kt @@ -1,9 +1,9 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import com.ai.assistance.operit.data.model.ChatMessage -import com.ai.assistance.operit.ui.features.conversation.chat.components.ChatMessageHeightMemory +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.ChatMessageHeightMemory import com.ai.assistance.operit.util.stream.Stream /** diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/SummaryMessageComposable.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/SummaryMessageComposable.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/SummaryMessageComposable.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/SummaryMessageComposable.kt index 0e790e263e..2387a6e7af 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/SummaryMessageComposable.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/SummaryMessageComposable.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor import androidx.compose.foundation.background import androidx.compose.foundation.clickable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/UserMessageComposable.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/UserMessageComposable.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/UserMessageComposable.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/UserMessageComposable.kt index d81f662726..7fda519e82 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/UserMessageComposable.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/UserMessageComposable.kt @@ -1,13 +1,13 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor import com.ai.assistance.operit.core.chat.voice.VoiceMessageMarkup import com.ai.assistance.operit.core.chat.media.unescapeMediaAttribute -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.MediaFileGuard -import com.ai.assistance.operit.ui.features.conversation.chat.voicemessages.VoiceMessagePlayer -import com.ai.assistance.operit.ui.features.conversation.chat.voicemessages.ExpiredVoiceMessageTag -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.rememberMediaFileMissing +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.MediaFileGuard +import com.ai.assistance.operit.ui.features.conversation.chat.modules.voice.VoiceMessagePlayer +import com.ai.assistance.operit.ui.features.conversation.chat.modules.voice.ExpiredVoiceMessageTag +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.rememberMediaFileMissing import com.ai.assistance.operit.data.preferences.glass.GlassRegion -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.images.SentImageGroup -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.images.sentImageSources +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images.SentImageGroup +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images.sentImageSources import com.ai.assistance.operit.ui.theme.LocalThemePreferenceSnapshot import com.ai.assistance.operit.data.preferences.transparency.ThemeTransparencyPreferences @@ -72,9 +72,9 @@ import androidx.compose.ui.window.Dialog import com.ai.assistance.operit.R import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.data.model.ChatMessageDisplayMode -import com.ai.assistance.operit.ui.features.conversation.chat.components.attachments.AttachmentViewerDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.attachments.ChatAttachment -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.common.HiddenUserMessagePlaceholderContent +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview.AttachmentViewerDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview.ChatAttachment +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.common.HiddenUserMessagePlaceholderContent import com.ai.assistance.operit.core.chat.media.MediaLinkParser import com.ai.assistance.operit.ui.theme.isLiquidGlassSupported import com.ai.assistance.operit.ui.theme.isWaterGlassSupported diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/timeline/ChatTimelineEntries.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/timeline/ChatTimelineEntries.kt similarity index 92% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/timeline/ChatTimelineEntries.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/timeline/ChatTimelineEntries.kt index 533e193633..557e94bccd 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/timeline/ChatTimelineEntries.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/timeline/ChatTimelineEntries.kt @@ -1,9 +1,9 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.timeline +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline import com.ai.assistance.operit.ui.common.markdown.lazy.LocalMarkdownCardStateStore -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.rememberMessageToolExecutions +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.rememberMessageToolExecutions import com.ai.assistance.operit.ui.common.markdown.messageSectionsForRendering -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming.LocalInsideToolGroup +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming.LocalInsideToolGroup import com.ai.assistance.operit.ui.common.markdown.lazy.MarkdownCardStateStore import com.ai.assistance.operit.ui.common.markdown.lazy.markdownNodeIdentityKeys import androidx.compose.animation.core.animateFloatAsState @@ -41,13 +41,13 @@ import com.ai.assistance.operit.ui.common.markdown.StreamMarkdownRendererState import com.ai.assistance.operit.ui.common.markdown.UnifiedMarkdownCanvas import com.ai.assistance.operit.ui.common.markdown.XmlContentRenderer import com.ai.assistance.operit.ui.common.markdown.lazy.MarkdownRenderFragment -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.CanvasExpandableHeaderRow -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.ThinkToolsRow -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.ThinkToolsXmlNodeGrouper -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.buildThinkToolsRows -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.isVisibleChatMarkdownNode -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.thinkToolsGroupTitle -import com.ai.assistance.operit.ui.features.conversation.chat.components.rememberRevisableTextStream +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.CanvasExpandableHeaderRow +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.ThinkToolsRow +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.ThinkToolsXmlNodeGrouper +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.buildThinkToolsRows +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.isVisibleChatMarkdownNode +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.thinkToolsGroupTitle +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.stream.rememberRevisableTextStream import com.ai.assistance.operit.util.markdown.MarkdownNodeStable import com.ai.assistance.operit.util.markdown.toCharStream import kotlinx.coroutines.flow.Flow diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageTranslationDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/translation/MessageTranslationDialog.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageTranslationDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/translation/MessageTranslationDialog.kt index 382c67974c..d786a4e4c3 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageTranslationDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/translation/MessageTranslationDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.translation import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -50,7 +50,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.TranslationUiState +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.TranslationUiState import com.ai.assistance.operit.util.android.LocaleUtils private data class TranslationLanguage( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/util/MessageImageGenerator.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sharing/MessageImageGenerator.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/util/MessageImageGenerator.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sharing/MessageImageGenerator.kt index fc58412675..e219ea48f3 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/util/MessageImageGenerator.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sharing/MessageImageGenerator.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.util +package com.ai.assistance.operit.ui.features.conversation.chat.modules.sharing import android.app.Activity import android.content.Context @@ -38,9 +38,9 @@ import coil.compose.LocalImageLoader import coil.request.CachePolicy import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.data.preferences.ActivePromptManager -import com.ai.assistance.operit.ui.features.conversation.chat.components.ChatStyle -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble.BubbleStyleChatMessage -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor.CursorStyleChatMessage +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatStyle +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble.BubbleStyleChatMessage +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor.CursorStyleChatMessage import com.ai.assistance.operit.ui.theme.AppBackgroundLayer import com.ai.assistance.operit.ui.theme.LocalThemePreferenceSnapshot diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ShareImagePreviewDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sharing/ShareImagePreviewDialog.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ShareImagePreviewDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sharing/ShareImagePreviewDialog.kt index df29349f01..ff914c556c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ShareImagePreviewDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sharing/ShareImagePreviewDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.sharing import android.content.ContentValues import android.net.Uri diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/ChatSidebarContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/ChatSidebarContent.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/ChatSidebarContent.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/ChatSidebarContent.kt index add7b45dc0..734ac18179 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/ChatSidebarContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/ChatSidebarContent.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.sidebar +package com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar import androidx.compose.foundation.Image import androidx.compose.foundation.clickable @@ -29,9 +29,9 @@ import com.ai.assistance.operit.R import com.ai.assistance.operit.data.model.ActivePrompt import com.ai.assistance.operit.data.preferences.UserPreferencesManager import com.ai.assistance.operit.ui.common.NavItem -import com.ai.assistance.operit.ui.features.conversation.chat.components.CharacterSelectorPanel -import com.ai.assistance.operit.ui.features.conversation.chat.components.CharacterSelectorTarget -import com.ai.assistance.operit.ui.features.conversation.chat.folders.FolderChatHistoryPanel +import com.ai.assistance.operit.ui.features.conversation.chat.modules.characters.CharacterSelectorPanel +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.CharacterSelectorTarget +import com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders.FolderChatHistoryPanel import com.ai.assistance.operit.ui.main.components.NavigationDrawerAppearance import com.ai.assistance.operit.ui.main.navigation.NavigationEntrySpec import com.ai.assistance.operit.ui.main.screens.GestureStateHolder diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/ChatSidebarState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/ChatSidebarState.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/ChatSidebarState.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/ChatSidebarState.kt index ed71087d15..f533c8e444 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/ChatSidebarState.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/ChatSidebarState.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.sidebar +package com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar import androidx.compose.runtime.* import androidx.compose.ui.platform.LocalContext @@ -10,7 +10,7 @@ import com.ai.assistance.operit.data.preferences.ActivePromptManager import com.ai.assistance.operit.data.preferences.CharacterCardManager import com.ai.assistance.operit.data.preferences.CharacterGroupCardManager import com.ai.assistance.operit.ui.common.rememberLocal -import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatHistoryDisplayMode +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatHistoryDisplayMode import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel import kotlinx.coroutines.flow.flowOf diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/MainChatControls.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/MainChatControls.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/MainChatControls.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/MainChatControls.kt index 6c599dae90..271e7f9f20 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/MainChatControls.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/MainChatControls.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.sidebar +package com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar import androidx.compose.foundation.background import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -23,8 +23,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.components.useFloatingWindowLauncher -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceHubPage +import com.ai.assistance.operit.ui.features.conversation.chat.screens.useFloatingWindowLauncher +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceHubPage import com.ai.assistance.operit.ui.theme.getTextColorForBackground /** 主聊天页保留一行透明操作区,标题与入口共用菜单按钮的高度。 */ diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/SidebarButtonSurface.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/SidebarButtonSurface.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/SidebarButtonSurface.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/SidebarButtonSurface.kt index 336e41dcdd..a04036162b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/SidebarButtonSurface.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/SidebarButtonSurface.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.sidebar +package com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar import com.ai.assistance.operit.data.preferences.glass.GlassRegion import androidx.compose.foundation.BorderStroke diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/SidebarPluginSection.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/SidebarPluginSection.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/SidebarPluginSection.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/SidebarPluginSection.kt index b50e2248ef..b5a27fe19e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/SidebarPluginSection.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/SidebarPluginSection.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.sidebar +package com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.clickable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ChatContextUsageDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ChatContextUsageDialog.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ChatContextUsageDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ChatContextUsageDialog.kt index a21203a853..1020cadeac 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ChatContextUsageDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ChatContextUsageDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.context +package com.ai.assistance.operit.ui.features.conversation.chat.modules.usage import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ChatContextUsageEntry.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ChatContextUsageEntry.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ChatContextUsageEntry.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ChatContextUsageEntry.kt index 8cdf9ef663..87a3ec9255 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ChatContextUsageEntry.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ChatContextUsageEntry.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.context +package com.ai.assistance.operit.ui.features.conversation.chat.modules.usage import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ContextUsageFormat.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ContextUsageFormat.kt similarity index 84% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ContextUsageFormat.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ContextUsageFormat.kt index 049207b6db..441f943ce2 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ContextUsageFormat.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ContextUsageFormat.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.context +package com.ai.assistance.operit.ui.features.conversation.chat.modules.usage import java.text.NumberFormat import java.util.Locale diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ContextWindowUsageContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ContextWindowUsageContent.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ContextWindowUsageContent.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ContextWindowUsageContent.kt index fdd7c690f4..7e3b380fff 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ContextWindowUsageContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ContextWindowUsageContent.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.context +package com.ai.assistance.operit.ui.features.conversation.chat.modules.usage import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/CumulativeUsageContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/CumulativeUsageContent.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/CumulativeUsageContent.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/CumulativeUsageContent.kt index 169f41e7d5..d6c14f017a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/CumulativeUsageContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/CumulativeUsageContent.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.context +package com.ai.assistance.operit.ui.features.conversation.chat.modules.usage import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/config/TokenInfoDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/TokenInfoDialog.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/config/TokenInfoDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/TokenInfoDialog.kt index 37835c774d..af3d7ceefb 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/config/TokenInfoDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/TokenInfoDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.config +package com.ai.assistance.operit.ui.features.conversation.chat.modules.usage import androidx.compose.foundation.layout.* import androidx.compose.material3.* diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/ExpiredVoiceMessageTag.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/ExpiredVoiceMessageTag.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/ExpiredVoiceMessageTag.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/ExpiredVoiceMessageTag.kt index 00f69369ae..d61623e8d8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/ExpiredVoiceMessageTag.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/ExpiredVoiceMessageTag.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.voicemessages +package com.ai.assistance.operit.ui.features.conversation.chat.modules.voice import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.padding diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessagePlayer.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessagePlayer.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessagePlayer.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessagePlayer.kt index 7392b4462f..4b0f33651f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessagePlayer.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessagePlayer.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.voicemessages +package com.ai.assistance.operit.ui.features.conversation.chat.modules.voice import android.net.Uri import androidx.compose.animation.animateContentSize @@ -24,8 +24,8 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.compose.LocalLifecycleOwner import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.MediaFileGuard -import com.ai.assistance.operit.ui.features.conversation.chat.attachments.rememberMediaFileMissing +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.MediaFileGuard +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.rememberMediaFileMissing import com.ai.assistance.operit.util.logging.AppLogger import com.google.android.exoplayer2.audio.AudioAttributes import com.google.android.exoplayer2.C diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSession.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSession.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSession.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSession.kt index 6f11a7b40b..a6258107b6 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSession.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSession.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.voicemessages +package com.ai.assistance.operit.ui.features.conversation.chat.modules.voice import android.content.Context import com.ai.assistance.operit.R diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSheet.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSheet.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSheet.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSheet.kt index 36d811fb34..9889c19a0c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSheet.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSheet.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.voicemessages +package com.ai.assistance.operit.ui.features.conversation.chat.modules.voice import android.Manifest import android.content.pm.PackageManager diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSheetContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSheetContent.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSheetContent.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSheetContent.kt index dbc0f4d722..9aa268bedc 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSheetContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSheetContent.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.voicemessages +package com.ai.assistance.operit.ui.features.conversation.chat.modules.voice import androidx.compose.animation.core.RepeatMode import androidx.compose.animation.core.animateFloat diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageXmlPlugin.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageXmlPlugin.kt similarity index 92% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageXmlPlugin.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageXmlPlugin.kt index cf8f4db6e6..81971c345d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageXmlPlugin.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageXmlPlugin.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.voicemessages +package com.ai.assistance.operit.ui.features.conversation.chat.modules.voice import android.content.Context import androidx.compose.ui.graphics.Color diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceWaveform.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceWaveform.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceWaveform.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceWaveform.kt index 4d98f703f1..6061d2570d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceWaveform.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceWaveform.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.voicemessages +package com.ai.assistance.operit.ui.features.conversation.chat.modules.voice import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/AIChatScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/AIChatScreen.kt index 9401c1322f..56be31c71a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/AIChatScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/AIChatScreen.kt @@ -1,12 +1,12 @@ package com.ai.assistance.operit.ui.features.conversation.chat.screens -import com.ai.assistance.operit.ui.features.conversation.chat.voicemessages.VoiceMessageSheet +import com.ai.assistance.operit.ui.features.conversation.chat.modules.voice.VoiceMessageSheet import com.ai.assistance.operit.core.chat.voice.canStartVoiceMessage import com.ai.assistance.operit.ui.common.oktoast.OKToast import com.ai.assistance.operit.data.preferences.transparency.ThemeTransparencyPreferences -import com.ai.assistance.operit.ui.features.conversation.chat.components.animateScrollToEnd +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.animateScrollToEnd import android.content.ClipboardManager import android.os.Build import android.provider.Settings @@ -56,28 +56,27 @@ import com.ai.assistance.operit.data.preferences.DisplayPreferencesManager import com.ai.assistance.operit.data.preferences.UserPreferencesManager import com.ai.assistance.operit.data.preferences.WaifuPreferences import com.ai.assistance.operit.ui.components.ErrorDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.* -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.agent.AgentChatInputSection -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.classic.ClassicChatInputSection -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputEvents -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputHookContext -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputHookRegistry -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.ChatInputSubmitActions -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.classic.ClassicChatSettingsBar -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.PendingQueueMessageItem -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble.BubbleImageStyleConfig -import com.ai.assistance.operit.ui.features.conversation.chat.components.AndroidExportDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.ExportCompleteDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.ExportPlatformDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.ExportProgressDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.WindowsExportDialog -import com.ai.assistance.operit.ui.features.conversation.chat.webview.MentionSuggestionPanelStyle -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceHubScreen -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceHubOverlay -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceHubPage +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.agent.AgentChatInputSection +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.classic.ClassicChatInputSection +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ChatInputEvents +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ChatInputHookContext +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ChatInputHookRegistry +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common.ChatInputSubmitActions +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.classic.ClassicChatSettingsBar +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.PendingQueueMessageItem +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble.BubbleImageStyleConfig +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.AndroidExportDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.ExportCompleteDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.ExportPlatformDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.ExportProgressDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.WindowsExportDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.mentions.MentionSuggestionPanelStyle +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceHubScreen +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceHubOverlay +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceHubPage import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import com.ai.assistance.operit.ui.features.conversation.chat.webview.MentionSuggestionPanel -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.* +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.mentions.MentionSuggestionPanel +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.* import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel import com.ai.assistance.operit.ui.main.LocalTopBarActions import com.ai.assistance.operit.ui.main.PendingChatDraftHandler @@ -104,20 +103,18 @@ import com.ai.assistance.operit.plugins.chatview.ChatViewEvent import com.ai.assistance.operit.plugins.chatview.ChatViewHookParams import com.ai.assistance.operit.plugins.chatview.ChatViewHookPluginRegistry import java.util.UUID -import com.ai.assistance.operit.ui.features.conversation.chat.components.CharacterSelectorPanel -import com.ai.assistance.operit.ui.features.conversation.chat.components.CharacterSelectorTarget -import com.ai.assistance.operit.ui.features.conversation.chat.components.ChatHistorySelectorPanel -import com.ai.assistance.operit.ui.features.conversation.chat.components.ChatScreenContent -import com.ai.assistance.operit.ui.features.conversation.chat.components.ChatStyle -import com.ai.assistance.operit.ui.features.conversation.chat.components.MemoryFolderSelectionDialog -import com.ai.assistance.operit.ui.features.conversation.chat.components.SharedIncomingContentHandler -import com.ai.assistance.operit.ui.features.conversation.chat.components.exportAndroidApp -import com.ai.assistance.operit.ui.features.conversation.chat.components.exportWindowsApp -import com.ai.assistance.operit.ui.features.conversation.chat.components.extractClipboardPastedText -import com.ai.assistance.operit.ui.features.conversation.chat.components.extractInsertedText -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalMainChatSidebarState -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalOpenMainChatSidebar -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.rememberChatSidebarState +import com.ai.assistance.operit.ui.features.conversation.chat.modules.characters.CharacterSelectorPanel +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.CharacterSelectorTarget +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatStyle +import com.ai.assistance.operit.ui.features.conversation.chat.modules.input.memory.MemoryFolderSelectionDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.imports.SharedIncomingContentHandler +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.exportAndroidApp +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.exportWindowsApp +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.extractClipboardPastedText +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.extractInsertedText +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalMainChatSidebarState +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalOpenMainChatSidebar +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.rememberChatSidebarState @RequiresApi(Build.VERSION_CODES.O) @@ -1229,7 +1226,7 @@ val actualViewModel: ChatViewModel = viewModel ?: viewModel { ChatViewModel(cont ) } - com.ai.assistance.operit.ui.features.conversation.chat.motion.NewChatIntro( + com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.motion.NewChatIntro( requestId = newChatIntroId, currentChatId = currentChatId, ready = loadedChatId == currentChatId && currentChatId != null && !isLoading && !isLoadingDisplayWindow && !showChatHistorySelector, empty = chatHistory.isEmpty(), hasDraft = introDraft.text.isNotEmpty(), onConsumed = actualViewModel.chatListMotion::consumeIntro, diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatHeader.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatHeader.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatHeader.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatHeader.kt index d582b8fe43..44b201d6c1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatHeader.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatHeader.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.screens import androidx.compose.foundation.background import androidx.compose.foundation.clickable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScreenContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatScreenContent.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScreenContent.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatScreenContent.kt index cbad0bcdf6..c2a96d4b63 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScreenContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatScreenContent.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.screens import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -41,10 +41,10 @@ import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.data.model.ActivePrompt import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links.WorkspaceFileLinkHost -import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatHistoryDisplayMode -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble.BubbleImageStyleConfig -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceBackupManager +import com.ai.assistance.operit.ui.features.conversation.workspace.links.WorkspaceFileLinkHost +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatHistoryDisplayMode +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble.BubbleImageStyleConfig +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceBackupManager import java.io.File import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope @@ -67,10 +67,26 @@ import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.common.markdown.markdownToPlainTextForCopy -import com.ai.assistance.operit.ui.features.conversation.chat.components.MessageEditor -import com.ai.assistance.operit.ui.features.conversation.chat.components.MessageTranslationDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.editor.MessageEditor +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.translation.MessageTranslationDialog import com.ai.assistance.operit.ui.main.screens.GestureStateHolder import com.ai.assistance.operit.util.markdown.LatexMathMlConverter +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.CharacterSelectorTarget +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatStyle +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.AndroidExportDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.ExportCompleteDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.ExportPlatformDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.ExportProgressDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.WindowsExportDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.exportAndroidApp +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.exportWindowsApp +import com.ai.assistance.operit.ui.features.conversation.chat.modules.history.ChatHistorySelector +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.ChatArea +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.actions.WorkspaceChangeConfirmDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.actions.WorkspaceChangeConfirmMode +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.buildSelectedMessagesPlainText +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sharing.ShareImagePreviewDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sharing.saveShareImageToGallery import kotlin.math.roundToInt import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScreenHeader.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatScreenHeader.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScreenHeader.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatScreenHeader.kt index 40604f2f94..775d994274 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScreenHeader.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatScreenHeader.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.screens import com.ai.assistance.operit.ui.common.oktoast.OKToast diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt index 59dcc4a5f9..7d5fbee0c3 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue.Companion import androidx.core.content.FileProvider -import com.ai.assistance.operit.ui.features.conversation.chat.components.ChatStyle +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatStyle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.ai.assistance.operit.core.chat.runtime.ChatRuntimeHolder @@ -45,7 +45,7 @@ import com.ai.assistance.operit.data.repository.MessageTranslationRepository import com.ai.assistance.operit.data.model.PromptFunctionType import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.webview.LocalWebServer +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.LocalWebServer import com.ai.assistance.operit.ui.floating.FloatingMode import com.ai.assistance.operit.ui.permissions.PermissionLevel import com.ai.assistance.operit.ui.permissions.ToolPermissionSystem @@ -72,9 +72,9 @@ import kotlinx.coroutines.withTimeout import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.flow.filterNotNull import com.ai.assistance.operit.ui.features.automation.terminal.EmbeddedTerminalPage -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceHubPage -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceEntryAction -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceEntryRequest +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceHubPage +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceEntryAction +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceEntryRequest import com.ai.assistance.operit.util.text.XmlTagCleaner import com.ai.assistance.operit.api.speech.tts.TtsService import com.ai.assistance.operit.api.speech.tts.prefetch.PrefetchingTtsService @@ -88,28 +88,28 @@ import com.ai.assistance.operit.data.preferences.ActivePromptManager import com.ai.assistance.operit.data.preferences.CharacterCardManager import com.ai.assistance.operit.data.model.ActivePrompt import com.ai.assistance.operit.util.WaifuMessageProcessor -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceBackupManager -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.CommandConfig -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceCommandExecutionState -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceConfigReader -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspacePreviewRefreshBus -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspacePreviewRefreshEvent -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.toWorkspaceCommandOutputEntries +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceBackupManager +import com.ai.assistance.operit.ui.features.conversation.workspace.CommandConfig +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceCommandExecutionState +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceConfigReader +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.WorkspacePreviewRefreshBus +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.WorkspacePreviewRefreshEvent +import com.ai.assistance.operit.ui.features.conversation.workspace.toWorkspaceCommandOutputEntries import com.ai.assistance.operit.core.tools.system.Terminal import com.ai.assistance.operit.core.speech.text.TtsCleaner import com.ai.assistance.operit.core.speech.text.TtsSegmenter -import com.ai.assistance.operit.ui.features.conversation.chat.util.findMentionTokens -import com.ai.assistance.operit.ui.features.conversation.chat.util.findMentionTokenEndingAtCursor -import com.ai.assistance.operit.ui.features.conversation.chat.util.isMentionContinuation +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.mentions.findMentionTokens +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.mentions.findMentionTokenEndingAtCursor +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.mentions.isMentionContinuation import android.net.Uri import android.os.Build import androidx.annotation.RequiresApi import java.io.File // 使用 services/core 的 Delegate 类 import com.ai.assistance.operit.services.core.MessageProcessingDelegate -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchAction -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchController -import com.ai.assistance.operit.ui.features.conversation.chat.batch.ChatBatchItemResult +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchAction +import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.history.ChatBatchController +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchItemResult import com.ai.assistance.operit.services.core.ChatHistoryDelegate import com.ai.assistance.operit.services.core.ApiConfigDelegate import com.ai.assistance.operit.services.core.TokenStatisticsDelegate @@ -120,22 +120,11 @@ import com.ai.assistance.operit.data.model.WorkspaceRenameResult import com.ai.assistance.operit.services.ChatServiceCore import com.ai.assistance.operit.services.ChatServiceUiBridge import com.ai.assistance.operit.services.EmptyChatServiceUiBridge -import com.ai.assistance.operit.ui.features.conversation.chat.util.MessageImageGenerator -import com.ai.assistance.operit.ui.features.conversation.chat.components.CharacterSelectorTarget -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.PendingQueueMessageItem -enum class ChatHistoryDisplayMode { - BY_CHARACTER_CARD, - BY_FOLDER, - CURRENT_CHARACTER_ONLY -} - -data class TranslationUiState( - val isLoading: Boolean = false, - val translatedText: String? = null, - val errorMessage: String? = null, - val isFromCache: Boolean = false, -) - +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sharing.MessageImageGenerator +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.CharacterSelectorTarget +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.PendingQueueMessageItem +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatHistoryDisplayMode +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.TranslationUiState class ChatViewModel(context: Context) : ViewModel() { private val context: Context = LocaleUtils.getLocalizedContext(context.applicationContext) @@ -791,7 +780,7 @@ class ChatViewModel(context: Context) : ViewModel() { } // 聊天历史相关方法 - val chatListMotion = com.ai.assistance.operit.ui.features.conversation.chat.motion.ChatListMotionState() + val chatListMotion = com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.history.ChatListMotionState() fun createNewChat( characterCardName: String? = null, characterGroupId: String? = null, diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/PendingMessageQueueStore.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/PendingMessageQueueStore.kt index 17ee35f1d5..24cd4e6203 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/PendingMessageQueueStore.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/PendingMessageQueueStore.kt @@ -1,6 +1,6 @@ package com.ai.assistance.operit.ui.features.conversation.chat.viewmodel -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common.PendingQueueMessageItem +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.PendingQueueMessageItem import java.util.concurrent.atomic.AtomicLong import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchController.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatBatchController.kt similarity index 81% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchController.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatBatchController.kt index 2ad381f7ee..e0348306fa 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchController.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatBatchController.kt @@ -1,16 +1,14 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.batch +package com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.history import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch - -enum class ChatBatchAction { SUMMARIZE_TITLES, ARCHIVE, UNARCHIVE, LOCK, UNLOCK, DELETE } -enum class ChatBatchItemResult { SUCCEEDED, SKIPPED, FAILED } - -data class ChatBatchProgress(val action: ChatBatchAction, val completed: Int, val total: Int) -data class ChatBatchSummary(val succeeded: Int, val skipped: Int, val failed: Int) +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchAction +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchItemResult +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchProgress +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchSummary /** 批量任务随聊天模型存活,逐条等待结果;收起面板不会重复执行或中断已确认的操作。 */ internal class ChatBatchController( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/ChatListMotionState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatListMotionState.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/ChatListMotionState.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatListMotionState.kt index 58b5521534..4c273b1127 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/ChatListMotionState.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatListMotionState.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.motion +package com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.history import androidx.compose.animation.core.LinearOutSlowInEasing import androidx.compose.animation.core.animate diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/FileManager.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/FileManager.kt index d7965608b7..ad59fd32fe 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/FileManager.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace import android.content.Intent import android.net.Uri @@ -61,25 +61,24 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.foundation.lazy.rememberLazyListState import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.OpenFileInfo -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.workspaceMimeTypeForPath -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.workspaceShouldOpenAsDirectPreview -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.text.WORKSPACE_TEXT_PREVIEW_LIMIT_BYTES -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.text.readWorkspaceTextWithinLimit +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.workspaceMimeTypeForPath +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.workspaceShouldOpenAsDirectPreview +import com.ai.assistance.operit.ui.features.conversation.workspace.text.WORKSPACE_TEXT_PREVIEW_LIMIT_BYTES +import com.ai.assistance.operit.ui.features.conversation.workspace.text.readWorkspaceTextWithinLimit import com.ai.assistance.operit.util.files.FileUtils -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.* -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer.WorkspaceCopyProgressDialog -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer.WorkspaceDeleteProgressDialog -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserClipboard -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserClipboardItem -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserContextMenu -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserOperations -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.properties.WorkspacePropertiesTarget -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.properties.WorkspacePropertiesDialog -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserSelectionBar -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserSortDialog -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.isValidWorkspaceEntryName -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.sortDirectoryEntries +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.* +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer.WorkspaceCopyProgressDialog +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer.WorkspaceDeleteProgressDialog +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.FileBrowserClipboard +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.FileBrowserClipboardItem +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.FileBrowserContextMenu +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.FileBrowserOperations +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.properties.WorkspacePropertiesTarget +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.properties.WorkspacePropertiesDialog +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.FileBrowserSelectionBar +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.FileBrowserSortDialog +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.isValidWorkspaceEntryName +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.sortDirectoryEntries // 目录条目数据类 data class DirectoryEntry( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceBackupManager.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceBackupManager.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceBackupManager.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceBackupManager.kt index 572512822d..63a6909c8e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceBackupManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceBackupManager.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace import android.content.Context import android.util.Base64 @@ -17,7 +17,7 @@ import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import java.security.MessageDigest -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.GitIgnoreFilter +import com.ai.assistance.operit.ui.features.conversation.workspace.process.GitIgnoreFilter import com.ai.assistance.operit.util.files.FileUtils import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter @@ -28,7 +28,9 @@ import kotlinx.coroutines.withContext import java.text.SimpleDateFormat import java.util.Locale import java.util.concurrent.atomic.AtomicBoolean -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.WorkspaceChangeTracker +import com.ai.assistance.operit.ui.features.conversation.workspace.process.WorkspaceChangeTracker +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.WorkspacePreviewRefreshBus +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.WorkspacePreviewRefreshEvent @Serializable data class FileStat( diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceCommandExecutionState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceCommandExecutionState.kt similarity index 87% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceCommandExecutionState.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceCommandExecutionState.kt index d7a3adb281..de21f00628 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceCommandExecutionState.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceCommandExecutionState.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace data class WorkspaceCommandExecutionState( val workspacePath: String, diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceConfig.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceConfig.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceConfig.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceConfig.kt index 48ba4c6b37..30feb45ea4 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceConfig.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceConfig.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace import android.content.Context import com.ai.assistance.operit.R diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceFileModels.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceFileModels.kt similarity index 85% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceFileModels.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceFileModels.kt index c845e23d1e..45f0641530 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceFileModels.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceFileModels.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace import java.io.File import kotlinx.serialization.Serializable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceManager.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceManager.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceManager.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceManager.kt index 8b062c89eb..8f7c4bc710 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceManager.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceManager.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -49,24 +49,24 @@ import androidx.compose.ui.window.DialogProperties import kotlin.math.roundToInt import androidx.compose.ui.zIndex import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceEntryAction -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceEntryRequest +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceEntryAction +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceEntryRequest import com.ai.assistance.operit.core.tools.AIToolHandler import com.ai.assistance.operit.core.tools.FileContentData import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ChatHistory import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.ui.common.rememberLocal -import com.ai.assistance.operit.ui.features.conversation.chat.components.rememberCompactDialogMetrics -import com.ai.assistance.operit.ui.features.conversation.chat.components.attachments.AudioAttachmentPlayer -import com.ai.assistance.operit.ui.features.conversation.chat.components.attachments.VideoAttachmentPlayer -import com.ai.assistance.operit.ui.features.conversation.chat.webview.LocalWebServer +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout.rememberCompactDialogMetrics +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview.AudioAttachmentPlayer +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview.VideoAttachmentPlayer +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.LocalWebServer import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel -import com.ai.assistance.operit.ui.features.conversation.chat.webview.WebViewHandler -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.CodeEditor -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.CodeFormatter -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.EditorKeyCommand -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.LanguageDetector +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.WebViewHandler +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.CodeEditor +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.CodeFormatter +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.EditorKeyCommand +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.LanguageDetector import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -74,14 +74,26 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File import androidx.compose.runtime.saveable.rememberSaveableStateHolder -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.search.* -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links.WorkspaceFileLink -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links.WorkspaceFileLinkDialog -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links.findWorkspaceMarkdownAnchorLine -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.markdown.WorkspaceMarkdownPreview -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.search.FileSearchBar -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.search.activeSearchMatchAfterUpdate -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.search.findTextMatches +import com.ai.assistance.operit.ui.features.conversation.workspace.search.* +import com.ai.assistance.operit.ui.features.conversation.workspace.links.WorkspaceFileLink +import com.ai.assistance.operit.ui.features.conversation.workspace.links.WorkspaceFileLinkDialog +import com.ai.assistance.operit.ui.features.conversation.workspace.links.findWorkspaceMarkdownAnchorLine +import com.ai.assistance.operit.ui.features.conversation.workspace.markdown.WorkspaceMarkdownPreview +import com.ai.assistance.operit.ui.features.conversation.workspace.search.FileSearchBar +import com.ai.assistance.operit.ui.features.conversation.workspace.search.activeSearchMatchAfterUpdate +import com.ai.assistance.operit.ui.features.conversation.workspace.search.findTextMatches +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.WorkspaceImagePreview +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.WorkspacePreviewRefreshBus +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.WorkspaceReadOnlyDocumentPreview +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.isAudio +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.isHtml +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.isImage +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.isMarkdown +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.isReadOnlyDocumentPreviewable +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.isReadOnlyPreview +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.isVideo +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.rememberWorkspacePreviewFileState +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.workspacePreviewUriFromFile private fun WebView.installWorkspaceTouchInterceptor() { setOnTouchListener { view, event -> @@ -329,7 +341,7 @@ fun WorkspaceManager( var fileToCloseIndex by remember { mutableStateOf(-1) } // 当前活动的编辑器引用 - var activeEditor by remember { mutableStateOf(null) } + var activeEditor by remember { mutableStateOf(null) } val searchableFile = openFiles.getOrNull(currentFileIndex)?.takeUnless { it.isReadOnlyPreview } LaunchedEffect(searchableFile?.key, searchableFile?.content, searchQuery, searchVisible) { val nextContext = searchableFile?.key to searchQuery diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceScreen.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceScreen.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceScreen.kt index bc38ccf645..5c88577ce0 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceScreen.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace import androidx.compose.foundation.background import androidx.compose.foundation.layout.* @@ -15,7 +15,7 @@ import com.ai.assistance.operit.R import com.ai.assistance.operit.data.model.ChatHistory import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel import java.io.File -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceEntryRequest +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceEntryRequest import androidx.compose.runtime.saveable.rememberSaveableStateHolder /** diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceSetup.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceSetup.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceSetup.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceSetup.kt index cff79dd443..55af784d62 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceSetup.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceSetup.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -13,14 +13,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceEntryAction -import com.ai.assistance.operit.ui.features.conversation.chat.webview.createAndGetDefaultWorkspace +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceEntryAction import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import com.ai.assistance.operit.core.tools.AIToolHandler import com.ai.assistance.operit.core.tools.packTool.PackageManager -import com.ai.assistance.operit.ui.features.conversation.chat.webview.createAndResetWorkspaceDirectory import kotlinx.coroutines.* /** diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceUtils.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceUtils.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceUtils.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceUtils.kt index b90b98b9ed..bf2b56d240 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceUtils.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceUtils.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview +package com.ai.assistance.operit.ui.features.conversation.workspace import android.content.Context import com.ai.assistance.operit.R diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserClipboard.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserClipboard.kt similarity index 90% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserClipboard.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserClipboard.kt index f858288316..e5cae29f25 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserClipboard.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserClipboard.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser +package com.ai.assistance.operit.ui.features.conversation.workspace.browser import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserSelectionBar.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserSelectionBar.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserSelectionBar.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserSelectionBar.kt index 2fc8860ddd..61500b44ce 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserSelectionBar.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserSelectionBar.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser +package com.ai.assistance.operit.ui.features.conversation.workspace.browser import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserDialogs.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserDialogs.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserDialogs.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserDialogs.kt index 171fa00944..0b5a3affeb 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserDialogs.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserDialogs.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser +package com.ai.assistance.operit.ui.features.conversation.workspace.browser import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -13,7 +13,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.DirectoryEntry +import com.ai.assistance.operit.ui.features.conversation.workspace.DirectoryEntry internal fun sortDirectoryEntries(entries: List, mode: Int, descending: Boolean, ignoreCase: Boolean, foldersFirst: Boolean): List { diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserOperations.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserOperations.kt index 0dad1cdc14..0aaba4b079 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserOperations.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser +package com.ai.assistance.operit.ui.features.conversation.workspace.browser import android.content.Context import android.content.Intent @@ -7,8 +7,8 @@ import androidx.core.content.FileProvider import com.ai.assistance.operit.R import com.ai.assistance.operit.core.files.transfer.FileCopyObserver import com.ai.assistance.operit.core.files.transfer.FileCopyObservers -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer.WorkspaceCopyProgress -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer.WorkspaceDeleteOperation +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer.WorkspaceCopyProgress +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer.WorkspaceDeleteOperation import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.MutableStateFlow @@ -18,7 +18,7 @@ import com.ai.assistance.operit.core.tools.BinaryFileContentData import com.ai.assistance.operit.core.tools.FileExistsData import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.workspaceMimeTypeForPath +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.workspaceMimeTypeForPath import java.io.File import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserSupport.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserSupport.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserSupport.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserSupport.kt index 2ad5711010..221a672d0b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser +package com.ai.assistance.operit.ui.features.conversation.workspace.browser import java.io.File import java.time.LocalDateTime diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertiesDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertiesDialog.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertiesDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertiesDialog.kt index 75e4508f3e..22e548b0b4 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertiesDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertiesDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.properties +package com.ai.assistance.operit.ui.features.conversation.workspace.browser.properties import android.content.ClipData import android.content.ClipboardManager diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertiesRepository.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertiesRepository.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertiesRepository.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertiesRepository.kt index 955a213370..a184874e48 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertiesRepository.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertiesRepository.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.properties +package com.ai.assistance.operit.ui.features.conversation.workspace.browser.properties import android.content.Context import com.ai.assistance.operit.R diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertyAccess.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertyAccess.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertyAccess.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertyAccess.kt index cf41105d31..9255037c76 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertyAccess.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertyAccess.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.properties +package com.ai.assistance.operit.ui.features.conversation.workspace.browser.properties import android.Manifest import android.content.Context diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertyProviders.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertyProviders.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertyProviders.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertyProviders.kt index 9fd88597f2..679022e7af 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertyProviders.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertyProviders.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.properties +package com.ai.assistance.operit.ui.features.conversation.workspace.browser.properties import android.content.Context import android.net.Uri @@ -6,7 +6,7 @@ import android.provider.DocumentsContract import com.ai.assistance.operit.R import com.ai.assistance.operit.data.preferences.ApiPreferences import com.ai.assistance.operit.terminal.provider.filesystem.FileSystemProvider -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.directoryModifiedTime +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.directoryModifiedTime import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.first diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgress.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceCopyProgress.kt similarity index 83% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgress.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceCopyProgress.kt index d8b0c6b0ba..5ba6c09d5c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgress.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceCopyProgress.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer +package com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer import com.ai.assistance.operit.core.files.transfer.FileCopyProgress diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt index 34265e85aa..6767c28c9e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer +package com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer import android.text.format.Formatter import androidx.compose.material3.MaterialTheme diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgress.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteProgress.kt similarity index 89% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgress.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteProgress.kt index 9d94c1ec07..6b32eeac92 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgress.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteProgress.kt @@ -1,6 +1,6 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer +package com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserClipboardItem +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.FileBrowserClipboardItem import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.MutableStateFlow diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt index e9eb01a54e..7b5e3e936c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer +package com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceFileOperationDialog.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceFileOperationDialog.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceFileOperationDialog.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceFileOperationDialog.kt index 7558e364b3..85619f01f5 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceFileOperationDialog.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceFileOperationDialog.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer +package com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CanvasCodeEditorView.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CanvasCodeEditorView.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CanvasCodeEditorView.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CanvasCodeEditorView.kt index d5e480bb30..cdc1e5d663 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CanvasCodeEditorView.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CanvasCodeEditorView.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor import android.content.ClipData import android.content.ClipboardManager @@ -33,12 +33,12 @@ import android.view.inputmethod.InputConnection import android.view.inputmethod.InputMethodManager import android.widget.OverScroller import androidx.compose.ui.graphics.toArgb -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion.CompletionItem -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion.CompletionProvider -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion.CompletionProviderFactory -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language.LanguageSupport -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.theme.EditorTheme -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.theme.getThemeForLanguage +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion.CompletionItem +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion.CompletionProvider +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion.CompletionProviderFactory +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.language.LanguageSupport +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.theme.EditorTheme +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.theme.getThemeForLanguage import kotlin.math.abs import kotlin.math.ceil import kotlin.math.hypot diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CodeEditor.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CodeEditor.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CodeEditor.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CodeEditor.kt index c68905aac7..d1e1384a4e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CodeEditor.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CodeEditor.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor import android.content.Context import android.graphics.Point @@ -41,10 +41,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.viewinterop.AndroidView import com.ai.assistance.operit.ui.components.CustomScaffold -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion.CompletionItem -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion.CompletionPopup -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.theme.EditorTheme -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.theme.getThemeForLanguage +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion.CompletionItem +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion.CompletionPopup +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.theme.EditorTheme +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.theme.getThemeForLanguage import kotlin.math.roundToInt @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CodeFormatter.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CodeFormatter.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CodeFormatter.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CodeFormatter.kt index bf6a02f211..810ee8316f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CodeFormatter.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CodeFormatter.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor import com.ai.assistance.operit.util.logging.AppLogger diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CommentSyntax.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CommentSyntax.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CommentSyntax.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CommentSyntax.kt index 15b57a61c4..7f35b8d7ac 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CommentSyntax.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CommentSyntax.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor /** * 文件格式的注释规则。 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorDocument.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorDocument.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorDocument.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorDocument.kt index 25b8e3ef25..563fe4ae8f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorDocument.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorDocument.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor import android.text.SpannableStringBuilder import kotlin.math.max diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorMetrics.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorMetrics.kt similarity index 91% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorMetrics.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorMetrics.kt index be75d47e30..6b36a3f277 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorMetrics.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorMetrics.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor import android.graphics.Paint import android.graphics.Typeface diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorSyntaxHighlighter.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorSyntaxHighlighter.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorSyntaxHighlighter.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorSyntaxHighlighter.kt index bc18486918..21250ff49c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorSyntaxHighlighter.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorSyntaxHighlighter.kt @@ -1,10 +1,10 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor import android.graphics.Color import android.os.Handler import android.os.Looper -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language.LanguageFactory -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language.LanguageSupport +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.language.LanguageFactory +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.language.LanguageSupport import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.RejectedExecutionException diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/LanguageDetector.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/LanguageDetector.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/LanguageDetector.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/LanguageDetector.kt index b26961f6b5..606b87e768 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/LanguageDetector.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/LanguageDetector.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor /** * 根据文件名检测编程语言。 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionPopup.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionPopup.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionPopup.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionPopup.kt index 9718e12597..48eeb603f9 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionPopup.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionPopup.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.clickable @@ -20,8 +20,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Popup import androidx.compose.ui.window.PopupProperties -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language.LanguageSupport -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.theme.EditorTheme +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.language.LanguageSupport +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.theme.EditorTheme /** * 代码补全弹出组件 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionProvider.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionProvider.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionProvider.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionProvider.kt index 0116067924..2869ce0e55 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionProvider.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionProvider.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion import android.text.Editable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionProviderFactory.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionProviderFactory.kt similarity index 85% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionProviderFactory.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionProviderFactory.kt index 5aa86054ad..7855756792 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionProviderFactory.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionProviderFactory.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion /** * 补全提供器工厂 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/DartCompletionProvider.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/DartCompletionProvider.kt similarity index 94% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/DartCompletionProvider.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/DartCompletionProvider.kt index b68815cc7c..106d9cb122 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/DartCompletionProvider.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/DartCompletionProvider.kt @@ -1,6 +1,6 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language.LanguageFactory +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.language.LanguageFactory /** * Dart 补全提供器 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/DefaultCompletionProvider.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/DefaultCompletionProvider.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/DefaultCompletionProvider.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/DefaultCompletionProvider.kt index a5734cec7c..4c33ab1d7c 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/DefaultCompletionProvider.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/DefaultCompletionProvider.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion /** * 默认补全提供器 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/HtmlCompletionProvider.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/HtmlCompletionProvider.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/HtmlCompletionProvider.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/HtmlCompletionProvider.kt index 5507479f68..e1b71c7cf4 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/HtmlCompletionProvider.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/HtmlCompletionProvider.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion /** * HTML补全提供器 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/JavaScriptCompletionProvider.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/JavaScriptCompletionProvider.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/JavaScriptCompletionProvider.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/JavaScriptCompletionProvider.kt index 8e8198771d..680d4f1ff0 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/JavaScriptCompletionProvider.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/JavaScriptCompletionProvider.kt @@ -1,6 +1,6 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language.LanguageFactory +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.language.LanguageFactory /** * JavaScript补全提供器 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/KotlinCompletionProvider.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/KotlinCompletionProvider.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/KotlinCompletionProvider.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/KotlinCompletionProvider.kt index b40350f199..45594970c6 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/KotlinCompletionProvider.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/KotlinCompletionProvider.kt @@ -1,6 +1,6 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language.LanguageFactory +import com.ai.assistance.operit.ui.features.conversation.workspace.editor.language.LanguageFactory /** * Kotlin补全提供器 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/BaseLanguageSupport.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/BaseLanguageSupport.kt similarity index 90% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/BaseLanguageSupport.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/BaseLanguageSupport.kt index 11c6303d9e..d6a87dd059 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/BaseLanguageSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/BaseLanguageSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.language /** * 基础语言支持抽象类,提供通用实现 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/DartSupport.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/DartSupport.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/DartSupport.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/DartSupport.kt index 87af6f4310..19057c5685 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/DartSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/DartSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.language /** * Dart 语言支持 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/HtmlSupport.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/HtmlSupport.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/HtmlSupport.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/HtmlSupport.kt index ee466dfd3c..0e832c3764 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/HtmlSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/HtmlSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.language /** * HTML语言支持 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/JavaScriptSupport.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/JavaScriptSupport.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/JavaScriptSupport.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/JavaScriptSupport.kt index 447ebabf7c..401acc3ee0 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/JavaScriptSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/JavaScriptSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.language /** * JavaScript语言支持 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/KotlinSupport.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/KotlinSupport.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/KotlinSupport.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/KotlinSupport.kt index e6711851fc..886241aa58 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/KotlinSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/KotlinSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.language /** * Kotlin语言支持 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageFactory.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageFactory.kt similarity index 91% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageFactory.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageFactory.kt index 5141b07890..5c1879511d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageFactory.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageFactory.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.language /** * 语言工厂类,用于初始化和获取所有语言支持 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageSupport.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageSupport.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageSupport.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageSupport.kt index 3e17ecd71c..8919462833 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageSupport.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.language import android.graphics.Color diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageSupportRegistry.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageSupportRegistry.kt similarity index 93% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageSupportRegistry.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageSupportRegistry.kt index 83d5a8461a..9808137886 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageSupportRegistry.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageSupportRegistry.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.language /** * 语言支持注册表,用于管理所有支持的语言 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/theme/EditorTheme.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/theme/EditorTheme.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/theme/EditorTheme.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/theme/EditorTheme.kt index 8dd073d397..b84521923b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/theme/EditorTheme.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/theme/EditorTheme.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.theme +package com.ai.assistance.operit.ui.features.conversation.workspace.editor.theme import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.TextUnit diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubHome.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubHome.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubHome.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubHome.kt index 25e57f0bef..7d2d06a8d3 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubHome.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubHome.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace.hub import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.clickable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubOverlay.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubOverlay.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubOverlay.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubOverlay.kt index 299e2ff6f3..38826b7ad4 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubOverlay.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubOverlay.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace.hub import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.animateFloat diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubScreen.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubScreen.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubScreen.kt index ffe1010bc5..f615dee255 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubScreen.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace.hub import android.content.Intent import android.os.Build @@ -39,8 +39,8 @@ import com.ai.assistance.operit.data.resources.OfflineResources import com.ai.assistance.operit.ui.features.management.resources.OfflineResourcesActivity import com.ai.assistance.operit.terminal.TerminalManager import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel -import com.ai.assistance.operit.ui.features.conversation.chat.webview.computer.ComputerScreen -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceScreen +import com.ai.assistance.operit.ui.features.automation.terminal.ComputerScreen +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceScreen import java.io.File import androidx.compose.material3.AlertDialog import androidx.compose.material3.TextButton diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubState.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubState.kt similarity index 86% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubState.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubState.kt index 2f215853b3..c83ac7d50d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubState.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubState.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace.hub /** 工作区入口和子页面共用一份导航状态,避免终端与工作区同时显示。 */ enum class WorkspaceHubPage { diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceSessionTabs.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceSessionTabs.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceSessionTabs.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceSessionTabs.kt index 505bbb79c1..1a542930df 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceSessionTabs.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceSessionTabs.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace.hub import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.horizontalScroll diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLink.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLink.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLink.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLink.kt index ae55f0817c..51c8829d0f 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLink.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLink.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links +package com.ai.assistance.operit.ui.features.conversation.workspace.links import java.net.URI import java.net.URISyntaxException diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkHost.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLinkHost.kt similarity index 92% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkHost.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLinkHost.kt index 29976bfb2b..53d1d0fb34 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkHost.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLinkHost.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links +package com.ai.assistance.operit.ui.features.conversation.workspace.links import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.* @@ -24,14 +24,14 @@ import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ChatHistory import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.FileBrowser -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.OpenFileInfo -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceManager -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserOperations -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.workspaceMimeTypeForPath -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.workspaceShouldOpenAsDirectPreview -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.text.WORKSPACE_TEXT_PREVIEW_LIMIT_BYTES -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.text.readWorkspaceTextWithinLimit +import com.ai.assistance.operit.ui.features.conversation.workspace.FileBrowser +import com.ai.assistance.operit.ui.features.conversation.workspace.OpenFileInfo +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceManager +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.FileBrowserOperations +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.workspaceMimeTypeForPath +import com.ai.assistance.operit.ui.features.conversation.workspace.preview.workspaceShouldOpenAsDirectPreview +import com.ai.assistance.operit.ui.features.conversation.workspace.text.WORKSPACE_TEXT_PREVIEW_LIMIT_BYTES +import com.ai.assistance.operit.ui.features.conversation.workspace.text.readWorkspaceTextWithinLimit import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.util.files.FileUtils import java.io.File diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceMarkdownLink.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceMarkdownLink.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceMarkdownLink.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceMarkdownLink.kt index 33d5581c71..025e59d429 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceMarkdownLink.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceMarkdownLink.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links +package com.ai.assistance.operit.ui.features.conversation.workspace.links import java.net.URI import java.net.URISyntaxException diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/markdown/WorkspaceMarkdownPreview.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/markdown/WorkspaceMarkdownPreview.kt similarity index 86% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/markdown/WorkspaceMarkdownPreview.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/markdown/WorkspaceMarkdownPreview.kt index 4ec870efc1..bed5ee70d8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/markdown/WorkspaceMarkdownPreview.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/markdown/WorkspaceMarkdownPreview.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.markdown +package com.ai.assistance.operit.ui.features.conversation.workspace.markdown import com.ai.assistance.operit.ui.common.oktoast.OKToast @@ -17,10 +17,10 @@ import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.common.markdown.StreamMarkdownRenderer import com.ai.assistance.operit.ui.common.markdown.links.openMarkdownLink -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.OpenFileInfo -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links.WorkspaceFileLink -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links.WorkspaceMarkdownLink -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links.resolveWorkspaceMarkdownLink +import com.ai.assistance.operit.ui.features.conversation.workspace.OpenFileInfo +import com.ai.assistance.operit.ui.features.conversation.workspace.links.WorkspaceFileLink +import com.ai.assistance.operit.ui.features.conversation.workspace.links.WorkspaceMarkdownLink +import com.ai.assistance.operit.ui.features.conversation.workspace.links.resolveWorkspaceMarkdownLink import com.ai.assistance.operit.util.logging.AppLogger import kotlinx.coroutines.CancellationException diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/LocalWebServer.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/LocalWebServer.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/LocalWebServer.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/LocalWebServer.kt index fbc4526202..bb97570587 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/LocalWebServer.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/LocalWebServer.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview +package com.ai.assistance.operit.ui.features.conversation.workspace.preview import android.content.Context import android.os.Environment @@ -12,8 +12,8 @@ import com.ai.assistance.operit.core.tools.BinaryFileContentData import com.ai.assistance.operit.core.tools.DirectoryListingData import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.workspaceMimeTypeForPath import com.ai.assistance.operit.util.logging.AppLogger +import com.ai.assistance.operit.ui.features.conversation.workspace.ensureWorkspaceDirExists import fi.iki.elonen.NanoHTTPD import java.io.ByteArrayInputStream import java.io.File diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WebViewHandler.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WebViewHandler.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WebViewHandler.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WebViewHandler.kt index 5a83743ae9..91b2210d4b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WebViewHandler.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WebViewHandler.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview +package com.ai.assistance.operit.ui.features.conversation.workspace.preview import com.ai.assistance.operit.ui.common.oktoast.OKToast diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceFilePreviewSupport.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceFilePreviewSupport.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceFilePreviewSupport.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceFilePreviewSupport.kt index f2862a7354..157d76233a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceFilePreviewSupport.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceFilePreviewSupport.kt @@ -1,10 +1,10 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace.preview import android.net.Uri import android.webkit.MimeTypeMap -import com.ai.assistance.operit.ui.features.conversation.chat.webview.LocalWebServer import java.io.File import java.util.Locale +import com.ai.assistance.operit.ui.features.conversation.workspace.OpenFileInfo private const val LOCAL_WORKSPACE_HOST = "127.0.0.1" diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceImagePreview.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceImagePreview.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceImagePreview.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceImagePreview.kt index f54003b87f..acf4b891d1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceImagePreview.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceImagePreview.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace.preview import android.net.Uri import androidx.compose.animation.AnimatedVisibility diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspacePreviewRefreshBus.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspacePreviewRefreshBus.kt similarity index 87% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspacePreviewRefreshBus.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspacePreviewRefreshBus.kt index aae5e6551b..fe23e9989e 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspacePreviewRefreshBus.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspacePreviewRefreshBus.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace.preview import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceReadOnlyDocumentPreview.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceReadOnlyDocumentPreview.kt similarity index 99% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceReadOnlyDocumentPreview.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceReadOnlyDocumentPreview.kt index e1cf314baa..90f169c6e8 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceReadOnlyDocumentPreview.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceReadOnlyDocumentPreview.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace +package com.ai.assistance.operit.ui.features.conversation.workspace.preview import android.graphics.Bitmap import android.graphics.pdf.PdfRenderer @@ -41,6 +41,7 @@ import com.ai.assistance.operit.data.model.AITool import com.ai.assistance.operit.data.model.ToolParameter import com.ai.assistance.operit.util.logging.AppLogger import com.ai.assistance.operit.util.document.DocumentConversionUtil +import com.ai.assistance.operit.ui.features.conversation.workspace.OpenFileInfo import java.io.File import java.io.FileOutputStream import java.util.Locale diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/DepthLimitedFileObserver.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/DepthLimitedFileObserver.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/DepthLimitedFileObserver.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/DepthLimitedFileObserver.kt index 696619bacd..bb4ce41769 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/DepthLimitedFileObserver.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/DepthLimitedFileObserver.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process +package com.ai.assistance.operit.ui.features.conversation.workspace.process import android.os.FileObserver import com.ai.assistance.operit.util.logging.AppLogger diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/GitIgnoreFilter.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/GitIgnoreFilter.kt similarity index 98% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/GitIgnoreFilter.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/GitIgnoreFilter.kt index e7a2c831cb..4efd9c89e1 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/GitIgnoreFilter.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/GitIgnoreFilter.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process +package com.ai.assistance.operit.ui.features.conversation.workspace.process import com.ai.assistance.operit.util.logging.AppLogger import java.io.File diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceAttachmentProcessor.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceAttachmentProcessor.kt similarity index 96% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceAttachmentProcessor.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceAttachmentProcessor.kt index 050f7f663c..6073694c06 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceAttachmentProcessor.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceAttachmentProcessor.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process +package com.ai.assistance.operit.ui.features.conversation.workspace.process import android.content.Context import com.ai.assistance.operit.R diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceChangeTracker.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceChangeTracker.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceChangeTracker.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceChangeTracker.kt index 1292eaaa6f..3cdd5fae9d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceChangeTracker.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceChangeTracker.kt @@ -1,8 +1,8 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process +package com.ai.assistance.operit.ui.features.conversation.workspace.process import android.content.Context -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WatchConfig -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.WorkspaceConfigReader +import com.ai.assistance.operit.ui.features.conversation.workspace.WatchConfig +import com.ai.assistance.operit.ui.features.conversation.workspace.WorkspaceConfigReader import com.ai.assistance.operit.util.logging.AppLogger import java.io.File diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceRuleFileReader.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceRuleFileReader.kt similarity index 95% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceRuleFileReader.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceRuleFileReader.kt index 65cbfcf5ea..9df57abd46 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceRuleFileReader.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceRuleFileReader.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process +package com.ai.assistance.operit.ui.features.conversation.workspace.process import android.content.Context import com.ai.assistance.operit.core.tools.AIToolHandler diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/search/WorkspaceTextSearch.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/search/WorkspaceTextSearch.kt similarity index 97% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/search/WorkspaceTextSearch.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/search/WorkspaceTextSearch.kt index cc72d873c2..7a7ab1cc0b 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/search/WorkspaceTextSearch.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/search/WorkspaceTextSearch.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.search +package com.ai.assistance.operit.ui.features.conversation.workspace.search import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardActions diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/text/WorkspaceTextReadPolicy.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/text/WorkspaceTextReadPolicy.kt similarity index 80% rename from app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/text/WorkspaceTextReadPolicy.kt rename to app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/text/WorkspaceTextReadPolicy.kt index fbe72ee1ce..f91a5238f4 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/text/WorkspaceTextReadPolicy.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/text/WorkspaceTextReadPolicy.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.text +package com.ai.assistance.operit.ui.features.conversation.workspace.text internal const val WORKSPACE_TEXT_PREVIEW_LIMIT_BYTES = 10L * 1024 * 1024 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/screens/theme/workbench/ThemePreviewSurfaces.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/screens/theme/workbench/ThemePreviewSurfaces.kt index 36e390a1fb..8baa7d30b0 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/screens/theme/workbench/ThemePreviewSurfaces.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/screens/theme/workbench/ThemePreviewSurfaces.kt @@ -27,8 +27,8 @@ import com.ai.assistance.operit.data.preferences.ThemePreferenceValues import com.ai.assistance.operit.data.preferences.UserPreferencesManager import com.ai.assistance.operit.data.preferences.glass.GlassRegion import com.ai.assistance.operit.data.preferences.transparency.ThemeTransparencyPreferences -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble.BubbleImageBackgroundSurface -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble.BubbleImageStyleConfig +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble.BubbleImageBackgroundSurface +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble.BubbleImageStyleConfig import com.ai.assistance.operit.ui.theme.* @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/screens/theme/workbench/ThemeWorkbenchMessageAppearance.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/screens/theme/workbench/ThemeWorkbenchMessageAppearance.kt index 9cf0a72eea..c23a0798fa 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/screens/theme/workbench/ThemeWorkbenchMessageAppearance.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/screens/theme/workbench/ThemeWorkbenchMessageAppearance.kt @@ -18,7 +18,7 @@ import com.ai.assistance.operit.R import com.ai.assistance.operit.data.preferences.UserPreferencesManager import com.ai.assistance.operit.data.preferences.glass.GlassRegion import com.ai.assistance.operit.data.preferences.transparency.ThemeTransparencyPreferences -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble.BubbleImageStyleConfig +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble.BubbleImageStyleConfig import com.ai.assistance.operit.ui.features.management.settings.components.ChatStyleOption import com.ai.assistance.operit.ui.features.management.settings.components.bubble.BubbleImageStyleEditor import com.ai.assistance.operit.ui.features.management.settings.components.transparency.BackgroundTransparencySlider diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/sections/ThemeSettingsCoreSections.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/sections/ThemeSettingsCoreSections.kt index 657c058e17..decd60e0ac 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/sections/ThemeSettingsCoreSections.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/management/settings/sections/ThemeSettingsCoreSections.kt @@ -34,7 +34,7 @@ import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R import com.ai.assistance.operit.data.preferences.UserPreferencesManager -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble.BubbleImageStyleConfig +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble.BubbleImageStyleConfig import com.ai.assistance.operit.ui.features.management.settings.screens.theme.ThemeEditorSession import com.ai.assistance.operit.ui.features.management.settings.screens.theme.workbench.* import kotlin.math.max diff --git a/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/markdown/StreamMarkdownDemo.kt b/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/markdown/StreamMarkdownDemo.kt index 97989a261f..e027e6656d 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/markdown/StreamMarkdownDemo.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/features/support/demo/markdown/StreamMarkdownDemo.kt @@ -44,7 +44,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.components.part.CustomXmlRenderer +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.CustomXmlRenderer import com.ai.assistance.operit.ui.common.markdown.StreamMarkdownRenderer import com.ai.assistance.operit.util.stream.asStream import kotlinx.coroutines.CancellationException diff --git a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/fullscreen/components/MessageDisplay.kt b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/fullscreen/components/MessageDisplay.kt index 64681aed6b..e4ec0e79f3 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/fullscreen/components/MessageDisplay.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/fullscreen/components/MessageDisplay.kt @@ -27,8 +27,8 @@ import androidx.compose.ui.graphics.CompositingStrategy import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.unit.dp import com.ai.assistance.operit.data.model.ChatMessage -import com.ai.assistance.operit.ui.features.conversation.chat.components.rememberChatMessageHeightMemory -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble.BubbleStyleChatMessage +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.rememberChatMessageHeightMemory +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble.BubbleStyleChatMessage import com.ai.assistance.operit.ui.theme.LocalThemePreferenceSnapshot /** diff --git a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/AttachmentPanel.kt b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/AttachmentPanel.kt index 6da3244e4c..cf184a9b77 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/AttachmentPanel.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/AttachmentPanel.kt @@ -46,7 +46,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import com.ai.assistance.operit.ui.features.conversation.chat.components.PackageSelectorDialog +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.PackageSelectorDialog /** * 专为浮动窗口设计的简化附件选择面板 diff --git a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/ChatMessages.kt b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/ChatMessages.kt index 5d2d378d39..7bc9d4a032 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/ChatMessages.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/ChatMessages.kt @@ -5,7 +5,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import com.ai.assistance.operit.data.model.ChatMessage -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor.CursorStyleChatMessage +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor.CursorStyleChatMessage /** 单个消息项组件 将消息渲染逻辑提取到单独的组件,减少重组范围 */ @Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/FloatingChatWindowInputControls.kt b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/FloatingChatWindowInputControls.kt index f1134d2992..13b7beacc5 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/FloatingChatWindowInputControls.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/components/FloatingChatWindowInputControls.kt @@ -62,7 +62,7 @@ import androidx.compose.ui.unit.sp import com.ai.assistance.operit.R import com.ai.assistance.operit.api.chat.AIForegroundService import com.ai.assistance.operit.data.model.PromptFunctionType -import com.ai.assistance.operit.ui.features.conversation.chat.components.AttachmentChip +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.AttachmentChip import com.ai.assistance.operit.ui.floating.FloatContext import com.ai.assistance.operit.ui.floating.FloatingMode import com.ai.assistance.operit.ui.floating.ui.window.viewmodel.FloatingChatWindowModeViewModel diff --git a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/screen/FloatingChatWindowScreen.kt b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/screen/FloatingChatWindowScreen.kt index 0d4bb7a628..cf80201071 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/screen/FloatingChatWindowScreen.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/floating/ui/window/screen/FloatingChatWindowScreen.kt @@ -56,11 +56,11 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextOverflow -import com.ai.assistance.operit.ui.features.conversation.chat.components.AttachmentChip -import com.ai.assistance.operit.ui.features.conversation.chat.components.ChatMessageHeightMemory -import com.ai.assistance.operit.ui.features.conversation.chat.components.ScrollToBottomButton -import com.ai.assistance.operit.ui.features.conversation.chat.components.rememberChatMessageHeightMemory -import com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor.CursorStyleChatMessage +import com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.AttachmentChip +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.ChatMessageHeightMemory +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.navigation.ScrollToBottomButton +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.list.rememberChatMessageHeightMemory +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor.CursorStyleChatMessage import com.ai.assistance.operit.ui.floating.ui.window.components.* import com.ai.assistance.operit.ui.floating.ui.window.models.* import com.ai.assistance.operit.ui.floating.ui.window.viewmodel.* diff --git a/app/src/main/java/com/ai/assistance/operit/ui/main/OperitApp.kt b/app/src/main/java/com/ai/assistance/operit/ui/main/OperitApp.kt index 802f09088e..ee63b07407 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/main/OperitApp.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/main/OperitApp.kt @@ -8,7 +8,7 @@ import androidx.compose.material3.DrawerValue import androidx.compose.material3.rememberDrawerState import androidx.compose.runtime.Composable import androidx.lifecycle.viewmodel.compose.viewModel -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.* +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.* import com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.ChatViewModel import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState @@ -59,11 +59,11 @@ import androidx.compose.runtime.DisposableEffect import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.features.management.update.screens.UpdateScreen import com.ai.assistance.operit.util.logging.AppLogger -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalMainChatSidebarState -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalMainChatViewModel -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalOpenMainChatSidebar -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalRunMainChatAction -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.rememberChatSidebarState +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalMainChatSidebarState +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalMainChatViewModel +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalOpenMainChatSidebar +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalRunMainChatAction +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.rememberChatSidebarState // 为TopAppBar的actions提供CompositionLocal // 它允许子组件(如AIChatScreen)向上提供它们的action Composable diff --git a/app/src/main/java/com/ai/assistance/operit/ui/main/components/AppContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/main/components/AppContent.kt index d97f0cc782..3684415a1a 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/main/components/AppContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/main/components/AppContent.kt @@ -1,8 +1,8 @@ package com.ai.assistance.operit.ui.main.components import androidx.compose.foundation.background -import com.ai.assistance.operit.ui.features.conversation.chat.workspace.WorkspaceHubPage -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalMainChatViewModel +import com.ai.assistance.operit.ui.features.conversation.workspace.hub.WorkspaceHubPage +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalMainChatViewModel import android.app.Activity import android.content.Context import android.content.ContextWrapper @@ -22,7 +22,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.statusBarsPadding -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.MainChatControls +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.MainChatControls import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ChevronLeft diff --git a/app/src/main/java/com/ai/assistance/operit/ui/main/components/DrawerContent.kt b/app/src/main/java/com/ai/assistance/operit/ui/main/components/DrawerContent.kt index f356f98e62..a00ea833d2 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/main/components/DrawerContent.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/main/components/DrawerContent.kt @@ -60,11 +60,11 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.ai.assistance.operit.R -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.ChatSidebarContent -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.SidebarButtonSurface -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalRunMainChatAction -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalMainChatViewModel -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalMainChatSidebarState +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.ChatSidebarContent +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.SidebarButtonSurface +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalRunMainChatAction +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalMainChatViewModel +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalMainChatSidebarState import com.ai.assistance.operit.ui.theme.LocalThemePreferenceSnapshot import com.ai.assistance.operit.core.tools.AIToolHandler import com.ai.assistance.operit.core.tools.packTool.PackageManager diff --git a/app/src/main/java/com/ai/assistance/operit/ui/main/screens/OperitScreens.kt b/app/src/main/java/com/ai/assistance/operit/ui/main/screens/OperitScreens.kt index bcaac6906c..77458cb8cf 100644 --- a/app/src/main/java/com/ai/assistance/operit/ui/main/screens/OperitScreens.kt +++ b/app/src/main/java/com/ai/assistance/operit/ui/main/screens/OperitScreens.kt @@ -27,8 +27,8 @@ import com.ai.assistance.operit.R import com.ai.assistance.operit.ui.common.NavItem import com.ai.assistance.operit.ui.features.support.about.screens.AboutScreen import com.ai.assistance.operit.ui.features.conversation.chat.screens.AIChatScreen -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalMainChatViewModel -import com.ai.assistance.operit.ui.features.conversation.chat.sidebar.LocalRunMainChatAction +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalMainChatViewModel +import com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar.LocalRunMainChatAction import com.ai.assistance.operit.ui.features.support.demo.screens.ShizukuDemoScreen import com.ai.assistance.operit.ui.features.support.help.screens.HelpScreen import com.ai.assistance.operit.ui.features.conversation.memory.screens.MemoryScreen @@ -82,7 +82,7 @@ import com.ai.assistance.operit.ui.features.automation.terminal.EmbeddedTerminal import com.ai.assistance.operit.ui.features.automation.terminal.TerminalEntryScreen import com.ai.assistance.operit.ui.common.composedsl.ToolPkgComposeDslToolScreen import com.ai.assistance.operit.ui.main.screens.UIDebuggerToolScreen -import com.ai.assistance.operit.ui.features.conversation.chat.export.htmlpackager.HtmlPackagerScreen +import com.ai.assistance.operit.ui.features.conversation.chat.modules.export.htmlpackager.HtmlPackagerScreen import com.ai.assistance.operit.ui.features.management.settings.speech.stt.SpeechToTextToolScreen import com.ai.assistance.operit.ui.features.management.update.screens.UpdateScreen import com.ai.assistance.operit.ui.features.automation.workflow.screens.WorkflowListScreen diff --git a/app/src/main/java/com/ai/assistance/operit/util/files/FileUtils.kt b/app/src/main/java/com/ai/assistance/operit/util/files/FileUtils.kt index a0b598cae5..bb142568f9 100644 --- a/app/src/main/java/com/ai/assistance/operit/util/files/FileUtils.kt +++ b/app/src/main/java/com/ai/assistance/operit/util/files/FileUtils.kt @@ -242,7 +242,7 @@ object FileUtils { if (!file.isFile) return false // Use GitIgnoreFilter to check if the file should be ignored - if (com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process.GitIgnoreFilter.shouldIgnore(file, workspaceRoot, gitignoreRules)) { + if (com.ai.assistance.operit.ui.features.conversation.workspace.process.GitIgnoreFilter.shouldIgnore(file, workspaceRoot, gitignoreRules)) { return false } diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/TokenHitRateFormatTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/format/TokenHitRateFormatTest.kt similarity index 93% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/TokenHitRateFormatTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/format/TokenHitRateFormatTest.kt index 754fb1be26..2e3c1d4600 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/TokenHitRateFormatTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/format/TokenHitRateFormatTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.foundation.format import org.junit.Assert.assertEquals import org.junit.Test diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/PastedTextAttachmentTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/PastedTextAttachmentTest.kt similarity index 96% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/PastedTextAttachmentTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/PastedTextAttachmentTest.kt index 549269c937..ab5b4f4c7b 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/PastedTextAttachmentTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/PastedTextAttachmentTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/GalleryDragSelectionTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/GalleryDragSelectionTest.kt similarity index 91% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/GalleryDragSelectionTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/GalleryDragSelectionTest.kt index 2255e7f3a8..17f19fcd82 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/GalleryDragSelectionTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/GalleryDragSelectionTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import org.junit.Assert.assertEquals import org.junit.Test diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ImagePreviewTransformTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ImagePreviewTransformTest.kt similarity index 96% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ImagePreviewTransformTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ImagePreviewTransformTest.kt index 963352ea60..4cc348cf9b 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ImagePreviewTransformTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ImagePreviewTransformTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageSourcesTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageSourcesTest.kt similarity index 96% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageSourcesTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageSourcesTest.kt index cc2e28d642..537831a687 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageSourcesTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageSourcesTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.attachments.images +package com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images import org.junit.Assert.* import org.junit.Test diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderChatHistoryTreeTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderChatHistoryTreeTest.kt similarity index 98% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderChatHistoryTreeTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderChatHistoryTreeTest.kt index f1d8e6b4c5..33778b9259 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderChatHistoryTreeTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderChatHistoryTreeTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.folders +package com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders import com.ai.assistance.operit.data.chat.folders.ChatFolder import com.ai.assistance.operit.data.chat.folders.ChatFolderBinding diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatAreaTokenSpeedTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/ChatAreaTokenSpeedTest.kt similarity index 76% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatAreaTokenSpeedTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/ChatAreaTokenSpeedTest.kt index ad89bc0b59..0510d47251 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatAreaTokenSpeedTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/ChatAreaTokenSpeedTest.kt @@ -1,6 +1,6 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages -import com.ai.assistance.operit.ui.features.conversation.chat.components.details.calculateMessageTokenSpeed +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details.calculateMessageTokenSpeed import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Test diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageCopyTextTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/MessageCopyTextTest.kt similarity index 99% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageCopyTextTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/MessageCopyTextTest.kt index 61cf2cdfc3..a81a7e9cff 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageCopyTextTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/MessageCopyTextTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages import com.ai.assistance.operit.data.model.ChatMessage import com.ai.assistance.operit.data.model.ChatMessageDisplayMode diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageStatsFormattingTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageStatsFormattingTest.kt similarity index 96% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageStatsFormattingTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageStatsFormattingTest.kt index c8cbba1507..89e56a6b9a 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageStatsFormattingTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageStatsFormattingTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.details +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details import java.util.Locale import org.junit.Assert.assertEquals diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditorContentTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditorContentTest.kt similarity index 99% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditorContentTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditorContentTest.kt index fe937286c0..db0707f7ab 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditorContentTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditorContentTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.editor import com.ai.assistance.operit.core.chat.protocol.ThinkingMarkup import org.junit.Assert.assertEquals diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/StatusCardHtmlDocumentTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/StatusCardHtmlDocumentTest.kt similarity index 97% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/StatusCardHtmlDocumentTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/StatusCardHtmlDocumentTest.kt index 598cc38350..12358031c3 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/StatusCardHtmlDocumentTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/StatusCardHtmlDocumentTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import java.io.File import java.security.MessageDigest diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsRowsTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsRowsTest.kt similarity index 97% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsRowsTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsRowsTest.kt index b6d7d114e5..1c090c5da8 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsRowsTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsRowsTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import com.ai.assistance.operit.ui.common.markdown.MarkdownGroupedItem import com.ai.assistance.operit.util.markdown.MarkdownNodeStable @@ -7,7 +7,7 @@ import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test -import com.ai.assistance.operit.ui.features.conversation.chat.components.timeline.shouldSplitChatMessage +import com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline.shouldSplitChatMessage import com.ai.assistance.operit.ui.common.markdown.lazy.markdownNodeIdentityKeys import com.ai.assistance.operit.ui.common.markdown.lazy.splitPlainMarkdownNode diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkingMarkdownStreamTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkingMarkdownStreamTest.kt similarity index 98% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkingMarkdownStreamTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkingMarkdownStreamTest.kt index 408d35ce1a..55cee85913 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkingMarkdownStreamTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkingMarkdownStreamTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering import com.ai.assistance.operit.core.chat.protocol.ThinkingMarkup import com.ai.assistance.operit.util.stream.StreamLogger diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingIndexTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingIndexTest.kt similarity index 97% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingIndexTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingIndexTest.kt index b54440df2e..e053c096ba 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingIndexTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingIndexTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming import com.ai.assistance.operit.core.chat.tools.timing.ToolExecutionTiming import com.ai.assistance.operit.data.model.tooltiming.ToolCallExecution diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageLayoutTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageLayoutTest.kt similarity index 98% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageLayoutTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageLayoutTest.kt index 8b3b2ea7aa..4e52a559a2 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageLayoutTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageLayoutTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble +package com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchControllerTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatBatchControllerTest.kt similarity index 91% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchControllerTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatBatchControllerTest.kt index da849e2daa..d1891902f4 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchControllerTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatBatchControllerTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.batch +package com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.history import kotlinx.coroutines.CancellationException import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -7,6 +7,10 @@ import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Assert.* import org.junit.Test +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchAction +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchItemResult +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchProgress +import com.ai.assistance.operit.ui.features.conversation.chat.foundation.model.ChatBatchSummary @OptIn(ExperimentalCoroutinesApi::class) class ChatBatchControllerTest { diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/ChatListMotionStateTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatListMotionStateTest.kt similarity index 96% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/ChatListMotionStateTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatListMotionStateTest.kt index b39847ca88..cf67380553 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/ChatListMotionStateTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatListMotionStateTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.motion +package com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.history import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserClipboardTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserClipboardTest.kt similarity index 94% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserClipboardTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserClipboardTest.kt index 45d5f19b0f..b73c488828 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserClipboardTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserClipboardTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser +package com.ai.assistance.operit.ui.features.conversation.workspace.browser import org.junit.After import org.junit.Assert.assertEquals diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserSupportTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserSupportTest.kt similarity index 96% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserSupportTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserSupportTest.kt index a367688fd0..806bef22bd 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserSupportTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserSupportTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser +package com.ai.assistance.operit.ui.features.conversation.workspace.browser import java.time.LocalDateTime import java.time.ZoneId diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt similarity index 96% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt index 339d586fb0..dc6ad5473a 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt @@ -1,6 +1,6 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer +package com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer -import com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.FileBrowserClipboardItem +import com.ai.assistance.operit.ui.features.conversation.workspace.browser.FileBrowserClipboardItem import java.io.IOException import kotlinx.coroutines.cancel import kotlinx.coroutines.currentCoroutineContext diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceCommentSyntaxTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceCommentSyntaxTest.kt similarity index 92% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceCommentSyntaxTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceCommentSyntaxTest.kt index f53df4d524..7c6edcfde8 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceCommentSyntaxTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceCommentSyntaxTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor +package com.ai.assistance.operit.ui.features.conversation.workspace.editor import org.junit.Assert.* import org.junit.Test diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLinkTest.kt similarity index 98% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLinkTest.kt index 1b007f5103..669ab1739b 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLinkTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links +package com.ai.assistance.operit.ui.features.conversation.workspace.links import org.junit.Assert.assertEquals import org.junit.Assert.assertNull diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceMarkdownLinkTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceMarkdownLinkTest.kt similarity index 98% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceMarkdownLinkTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceMarkdownLinkTest.kt index 447ff8c5ef..a4a476b558 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceMarkdownLinkTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceMarkdownLinkTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links +package com.ai.assistance.operit.ui.features.conversation.workspace.links import org.junit.Assert.assertEquals import org.junit.Assert.assertNull diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/search/WorkspaceTextSearchTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/search/WorkspaceTextSearchTest.kt similarity index 90% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/search/WorkspaceTextSearchTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/search/WorkspaceTextSearchTest.kt index e4ee6b69cd..27f3765a10 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/search/WorkspaceTextSearchTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/search/WorkspaceTextSearchTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.search +package com.ai.assistance.operit.ui.features.conversation.workspace.search import org.junit.Assert.assertEquals import org.junit.Test diff --git a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/text/WorkspaceTextReadPolicyTest.kt b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/text/WorkspaceTextReadPolicyTest.kt similarity index 93% rename from app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/text/WorkspaceTextReadPolicyTest.kt rename to app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/text/WorkspaceTextReadPolicyTest.kt index 2e596714b1..96d755dcef 100644 --- a/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/text/WorkspaceTextReadPolicyTest.kt +++ b/app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/text/WorkspaceTextReadPolicyTest.kt @@ -1,4 +1,4 @@ -package com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.text +package com.ai.assistance.operit.ui.features.conversation.workspace.text import org.junit.Assert.assertEquals import org.junit.Assert.assertNull diff --git a/docs/TODO/chore/README.md b/docs/TODO/chore/README.md index 86074d4ee5..c62f6e306f 100644 --- a/docs/TODO/chore/README.md +++ b/docs/TODO/chore/README.md @@ -6,6 +6,10 @@ ## 计划索引 +- [聊天代码按职责归类](chat-responsibility-layout/index.md) + +- [会话工作区按职责归类](conversation-workspace-layout/index.md) + - [1.12.2+15 分仓与布局修复发行](release-1.12.2-plus-15/index.md) - [正式版、补丁与离线资源分仓](release-repositories/index.md) diff --git a/docs/TODO/chore/chat-responsibility-layout/01-validation.md b/docs/TODO/chore/chat-responsibility-layout/01-validation.md new file mode 100644 index 0000000000..8c7e714b56 --- /dev/null +++ b/docs/TODO/chore/chat-responsibility-layout/01-validation.md @@ -0,0 +1,116 @@ +# 聊天职责整理验证 + +本批基线为 `9b9bb75d93b96b72204067fa576db30e5279d960`,承接尚未提交的工作区迁移。来源、目标、保留原路径文件和原样提取内容见 [files.json](files.json)。 + +## 已完成的静态核对 + +- 完成 173 个主源码文件、17 个 JVM 测试文件、1 个 Android 测试文件及 1 份列表来源说明的迁移,旧路径没有保留转发文件 +- 根层仅保留 `foundation`、`modules`、`screens`、`viewmodel`,主源码分别有 63、111、4、6 个 Kotlin 文件 +- 9 个共享声明原样提取到 6 个文件,逐项对照名称、字段、默认值、可见性和完整声明文本 +- 核对 381 个非私有顶层符号名的归属集合和来源文件,原有同名接口及工厂函数组合保持原样 +- 核对应用及测试源码中的 374 处聊天导入、46 处原同包引用,拆分包的 2 处星号导入已经衔接到对应显式引用 +- `foundation` 没有导入 `modules`、`screens` 或 `viewmodel`;队列条目、角色选择目标、聊天样式和共享状态类型由基础声明包提供 +- 本批声明体内仅 `ChatViewModel.kt`、`AIChatScreen.kt` 中的全限定包路径发生替换,其余变化限于声明归位、包声明和导入 +- 合并前一批工作区迁移,对基线全部 1938 个 Kotlin、Java 源文件逐一对照;归一化全限定路径并扣除清单内原样提取的声明后,全部声明体一致 +- 当前应用源码共有 1944 个 Kotlin、Java 文件,增加的 6 个文件全部属于共享声明,没有遗漏原有文件 +- 应用、工作流、终端目录和根构建配置的旧聊天包路径扫描无结果;既往 `chore/package-layout/` 清单未改写 +- 实施阶段完整差异通过临时 Git 索引执行空白检查,当时未改变真实暂存区或 HEAD;后续提交与远端验证由对应 PR 记录 + +旧路径扫描可在仓库根目录执行: + +```sh +rg -n 'features[./]conversation[./]chat[./](archive|attachments|batch|components|copy|export|folders|motion|sidebar|util|voicemessages|webview|workspace)([./]|\b)' app .github terminal build.gradle.kts settings.gradle.kts +``` + +预期无输出,`rg` 退出码为 1。声明体核对以两批清单和迁移前快照为依据,比较时只移除包声明及导入、映射完整包路径,并核对新文件包含原样提取的声明。 + +本地实施阶段未执行编译、构建或测试;远端派发与结果以目录整理和集成 PR 的验证说明为准。上述结果属于文本、声明和引用映射核对,不能代替 Kotlin 编译和 Android 运行验证。 + +## 完整回归范围 + +以下保留全部既有聊天回归类,包含原路径未变的待发消息队列测试。本批只迁移已有测试,不新增行为测试。执行后预期所有既有断言通过,Android 测试源码能够解析新包路径。 + +
既有自动回归类 + +| 编号 | 执行的测试类 | 覆盖范围 | +| --- | --- | --- | +| C1 | `GalleryDragSelectionTest` | 图片拖选 | +| C2 | `ImagePreviewTransformTest` | 图片预览变换 | +| C3 | `SentImageSourcesTest` | 已发送图片来源 | +| C4 | `ChatBatchControllerTest` | 聊天批量操作控制器 | +| C5 | `ChatAreaTokenSpeedTest` | 消息 Token 速度显示 | +| C6 | `MessageCopyTextTest` | 消息复制文本 | +| C7 | `MessageEditorContentTest` | 消息编辑内容 | +| C8 | `PastedTextAttachmentTest` | 粘贴文本附件 | +| C9 | `TokenHitRateFormatTest` | Token 命中率格式 | +| C10 | `MessageStatsFormattingTest` | 消息统计格式 | +| C11 | `StatusCardHtmlDocumentTest` | 状态卡片文档 | +| C12 | `ThinkToolsRowsTest` | 思考与工具分组行 | +| C13 | `ThinkingMarkdownStreamTest` | 思考 Markdown 流 | +| C14 | `ToolTimingIndexTest` | 工具耗时索引 | +| C15 | `BubbleImageLayoutTest` | 气泡图片布局 | +| C16 | `FolderChatHistoryTreeTest` | 文件夹聊天历史树 | +| C17 | `ChatListMotionStateTest` | 聊天列表动画状态 | +| C18 | `PendingMessageQueueStoreTest` | 待发消息队列,测试路径保留 | +| C19 | `StreamingTimelineRefreshAndroidTest` | Android 流式时间线刷新 | + +
+ +
Android 界面回归范围 + +| 编号 | 做什么 | 预期行为 | +| --- | --- | --- | +| M1 | 打开主聊天,切换历史并接收流式回复 | 页面、滚动位置、消息分组和刷新沿用原行为 | +| M2 | 在 Agent 和经典输入框切换设置、提及、角色及待发队列 | 原入口、选择、队列操作和发送回调正常 | +| M3 | 切换消息样式,打开详情、编辑、翻译、复制和工具卡片 | 内容、样式与原交互一致 | +| M4 | 选择图片并查看图片、音视频及失效附件 | 选择、拖选、预览和失效状态一致 | +| M5 | 从侧栏和历史面板执行文件夹、归档、批量操作 | 共用状态、进度、列表刷新和删除动画一致 | +| M6 | 录制、试听、发送和取消语音消息 | 权限、录音会话和关闭后的资源清理一致 | +| M7 | 分享消息图片,使用既有项目导出入口 | 原内容渲染、预览、保存和导出回调正常 | +| M8 | 打开悬浮聊天和主题预览,使用输入扩展 | 共用组件、共享类型和插件桥接解析到新位置 | +| M9 | 打开工作区、终端、编辑器及各类文件预览 | 前一批工作区迁移继续正常衔接,文件操作行为一致 | + +
+ +工作区迁移的回归范围见[工作区迁移验证](../conversation-workspace-layout/01-validation.md)。复制、剪切、删除的全部 17 条自动用例与 13 项实机范围继续保留在[文件操作验证](../../fix/workspace-copy-streaming-progress/01-validation.md),不以本页的包迁移检查替代。 + +## 结果记录 + +自动测试和 Android 界面项均尚未运行,以下表格用于填写实际结果。 + +
待填写结果与证据 + +| 编号 | 结果与证据 | +| --- | --- | +| C1 | | +| C2 | | +| C3 | | +| C4 | | +| C5 | | +| C6 | | +| C7 | | +| C8 | | +| C9 | | +| C10 | | +| C11 | | +| C12 | | +| C13 | | +| C14 | | +| C15 | | +| C16 | | +| C17 | | +| C18 | | +| C19 | | +| M1 | | +| M2 | | +| M3 | | +| M4 | | +| M5 | | +| M6 | | +| M7 | | +| M8 | | +| M9 | | + +
+ +[DONE] 本地静态核对和完整回归范围记录,实际测试结果待填写。 diff --git a/docs/TODO/chore/chat-responsibility-layout/files.json b/docs/TODO/chore/chat-responsibility-layout/files.json new file mode 100644 index 0000000000..7a79ce17c2 --- /dev/null +++ b/docs/TODO/chore/chat-responsibility-layout/files.json @@ -0,0 +1,2038 @@ +{ + "baseline": "9b9bb75d93b96b72204067fa576db30e5279d960", + "precedingMigration": "../conversation-workspace-layout/files.json", + "files": [ + { + "source": "app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/components/timeline/StreamingTimelineRefreshAndroidTest.kt", + "target": "app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/timeline/StreamingTimelineRefreshAndroidTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.timeline", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline", + "symbols": [] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/archive/ChatArchiveFilter.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/ChatArchiveFilter.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.archive", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history", + "symbols": [ + "ChatArchiveFilter" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/AttachmentUtils.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentUtils.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments", + "symbols": [ + "AttachmentUtils" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/MediaFileGuard.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/MediaFileGuard.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments", + "symbols": [ + "MediaFileGuard", + "MediaFileUnavailableTag", + "mediaPreviewUri", + "rememberMediaFileMissing", + "rememberMediaPreviewRevision" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/AttachmentImagePreviewDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/AttachmentImagePreviewDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [ + "AttachmentImagePreviewDialog", + "AttachmentPreviewImage" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ChatImagePickerDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ChatImagePickerDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [ + "ChatImagePickerDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ExpiredImageGroupTag.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ExpiredImageGroupTag.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [ + "ExpiredImageGroupTag" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/GalleryDragSelection.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/GalleryDragSelection.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [ + "GalleryDragSelection", + "galleryDragSelectionModifier" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ImagePreviewTransform.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ImagePreviewTransform.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [ + "ImagePreviewTransform", + "transformImagePreview" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/MediaStoreImageRepository.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/MediaStoreImageRepository.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [ + "GalleryImage", + "ImageLibraryAccess", + "imageLibraryAccess", + "imageLibraryPermissions", + "loadGalleryImages" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageGroup.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageGroup.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [ + "SentImageGroup", + "SentMessageImage" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageSources.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageSources.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [ + "sentImageSources" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchController.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatBatchController.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.batch", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.history", + "symbols": [ + "ChatBatchController" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchControls.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/batch/ChatBatchControls.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.batch", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history.batch", + "symbols": [ + "ChatBatchActionBar", + "ChatBatchDeleteDialog", + "ChatBatchSelectionHeader" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchMoveDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/batch/ChatBatchMoveDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.batch", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history.batch", + "symbols": [ + "ChatBatchMoveDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentChip.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentChip.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments", + "symbols": [ + "AttachmentChip" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentPreview.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentPreview.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments", + "symbols": [ + "AttachmentPreview" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/AttachmentSelector.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/AttachmentSelector.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments", + "symbols": [ + "AttachmentSelectorPanel", + "AttachmentSelectorPopupPanel", + "PackageSelectorDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/CharacterSelectorPanel.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/characters/CharacterSelectorPanel.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.characters", + "symbols": [ + "CharacterGroupItem", + "CharacterItem", + "CharacterSelectorPanel" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatArea.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/ChatArea.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages", + "symbols": [ + "ChatArea", + "MessageCopyContent", + "buildMessageCopyContent", + "buildSelectedMessagesPlainText", + "cleanMessageContentForCopy", + "cleanMessageContentForXmlCopy" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatHeader.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatHeader.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.screens", + "symbols": [ + "ChatHeader" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatHistorySelector.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/ChatHistorySelector.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history", + "symbols": [ + "ChatHistorySelector" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatMessageHeightMemory.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/list/ChatMessageHeightMemory.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.list", + "symbols": [ + "ChatMessageHeightMemory", + "rememberChatMessageHeightMemory" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScreenContent.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatScreenContent.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.screens", + "symbols": [ + "ChatHistorySelectorPanel", + "ChatScreenContent" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScreenHeader.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/ChatScreenHeader.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.screens", + "symbols": [ + "ChatScreenHeader", + "StatItem", + "useFloatingWindowLauncher" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScrollExtensions.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/list/ChatScrollExtensions.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.list", + "symbols": [ + "animateScrollToEnd" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatScrollNavigator.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/navigation/ChatScrollNavigator.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.navigation", + "symbols": [ + "ChatScrollNavigator" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/CompactDialogLayout.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/layout/CompactDialogLayout.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.layout", + "symbols": [ + "CompactDialogMetrics", + "compactDialogHeight", + "compactDialogHeightOrWrapContent", + "compactDialogHeightWhenShort", + "rememberCompactDialogMetrics", + "rememberCompactDialogScrollState", + "verticalScrollWhenCompact", + "verticalScrollWhenShort" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ExportDialogs.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/ExportDialogs.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.export", + "symbols": [ + "AndroidExportDialog", + "ExportCompleteDialog", + "ExportPlatformDialog", + "ExportProgressDialog", + "WindowsExportDialog", + "exportAndroidApp", + "exportWindowsApp" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/FullscreenInputDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/FullscreenInputDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input", + "symbols": [ + "FullscreenInputDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/LinkPreviewDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/links/LinkPreviewDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.links", + "symbols": [ + "LinkPreviewDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MemoryFolderSelectionDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/memory/MemoryFolderSelectionDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.memory", + "symbols": [ + "FolderNode", + "MemoryFolderSelectionDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditor.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.editor", + "symbols": [ + "MessageEditor" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditorContent.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditorContent.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.editor", + "symbols": [ + "ParsedMessagePart", + "PartType", + "createMessageEditorXmlPart", + "parseMessageContentForEditor", + "recomposeMessageFromParts" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageInfoDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageInfoDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details", + "symbols": [ + "MessageInfoDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageTranslationDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/translation/MessageTranslationDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.translation", + "symbols": [ + "MessageTranslationDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/PastedTextAttachment.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/PastedTextAttachment.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments", + "symbols": [ + "extractClipboardPastedText", + "extractInsertedText" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ReferencesDisplay.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/references/ReferencesDisplay.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.references", + "symbols": [ + "ReferencesDisplay" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/RevisableTextStreamRemember.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/stream/RevisableTextStreamRemember.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.stream", + "symbols": [ + "rememberRevisableTextStream" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ScrollToBottomButton.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/navigation/ScrollToBottomButton.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.navigation", + "symbols": [ + "ScrollToBottomButton" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ShareImagePreviewDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sharing/ShareImagePreviewDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.sharing", + "symbols": [ + "ShareImagePreviewDialog", + "saveShareImageToGallery" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedFileTargetDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/imports/SharedFileTargetDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.imports", + "symbols": [ + "SharedFileTargetDialog", + "SharedIncomingContentHandler" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SharedPackageImportChoiceDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/imports/SharedPackageImportChoiceDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.imports", + "symbols": [ + "SharedPackageImportChoiceDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/SimpleLinearProgressIndicator.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/progress/SimpleLinearProgressIndicator.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.progress", + "symbols": [ + "SimpleLinearProgressIndicator" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/TokenHitRateFormat.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/format/TokenHitRateFormat.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.format", + "symbols": [ + "formatCacheHitRate" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/WorkspaceChangeConfirmDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/actions/WorkspaceChangeConfirmDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.actions", + "symbols": [ + "WorkspaceChangeConfirmDialog", + "WorkspaceChangeConfirmMode" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/AttachmentViewerDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/AttachmentViewerDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.attachments", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview", + "symbols": [ + "AttachmentViewerDialog", + "ChatAttachment" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/AudioAttachmentPlayer.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/AudioAttachmentPlayer.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.attachments", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview", + "symbols": [ + "AudioAttachmentPlayer" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/attachments/VideoAttachmentPlayer.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/preview/VideoAttachmentPlayer.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.attachments", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.preview", + "symbols": [ + "VideoAttachmentPlayer" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/config/TokenInfoDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/TokenInfoDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.config", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.usage", + "symbols": [ + "TokenInfoDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ChatContextUsageDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ChatContextUsageDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.context", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.usage", + "symbols": [ + "ChatContextUsageDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ChatContextUsageEntry.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ChatContextUsageEntry.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.context", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.usage", + "symbols": [ + "ChatContextUsageEntry" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ContextUsageFormat.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ContextUsageFormat.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.context", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.usage", + "symbols": [ + "formatUsagePercent", + "formatUsageTokens" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/ContextWindowUsageContent.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/ContextWindowUsageContent.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.context", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.usage", + "symbols": [ + "ContextUsageTotalRow", + "ContextWindowCategoryColors", + "ContextWindowUsageContent", + "rememberContextWindowCategoryColors" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/context/CumulativeUsageContent.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/usage/CumulativeUsageContent.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.context", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.usage", + "symbols": [ + "CumulativeUsageContent" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageGenerationDetails.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageGenerationDetails.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.details", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details", + "symbols": [ + "MessageGenerationDetails", + "hasDisplayableMessageTimestamp", + "hasDisplayableTimingStats", + "hasDisplayableTokenSpeedStats", + "hasDisplayableTokenStats", + "messageTokenBreakdownText" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageStatsFormatting.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageStatsFormatting.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.details", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details", + "symbols": [ + "calculateMessageTokenSpeed", + "formatCompactMessageTokens", + "formatMessageCompletionTime", + "formatMessageDuration", + "formatMessageNumber", + "formatMessageTokenSpeed" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/AwaitFirstLayoutModifier.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/AwaitFirstLayoutModifier.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "AwaitFirstLayoutModifier" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/CacheWindowLogic.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/CacheWindowLogic.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "CacheWindowLogic", + "CacheWindowScope", + "CachedItem", + "InvalidIndex", + "forEachVisibleItem" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/IntervalList.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/IntervalList.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "IntervalList", + "MutableIntervalList" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyItemScope.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyItemScope.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyItemScope" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyItemScopeImpl.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyItemScopeImpl.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyItemScopeImpl" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayout.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayout.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayout" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsInfo.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsInfo.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutBeyondBoundsInfo" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsModifierLocal.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsModifierLocal.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutBeyondBoundsProviderModifierNode", + "lazyLayoutBeyondBoundsModifier" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutBeyondBoundsState.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutBeyondBoundsState.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutBeyondBoundsState", + "calculateLazyLayoutPinnedIndices" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutCacheWindow.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutCacheWindow.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutCacheWindow" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutIntervalContent.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutIntervalContent.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutIntervalContent" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemAnimation.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemAnimation.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutAnimateItemElement", + "LazyLayoutAnimationSpecsNode", + "LazyLayoutItemAnimation" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemAnimator.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemAnimator.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutItemAnimator" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemContentFactory.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemContentFactory.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutItemContentFactory" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutItemProvider.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutItemProvider.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutItemProvider", + "findIndexByKey" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutKeyIndexMap.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutKeyIndexMap.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutKeyIndexMap", + "NearestRangeKeyIndexMap" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasurePolicy.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasurePolicy.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutMeasurePolicy" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasureScope.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasureScope.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutMeasureScope", + "LazyLayoutMeasureScopeImpl" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutMeasuredItem.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutMeasuredItem.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutMeasuredItem", + "LazyLayoutMeasuredItemProvider", + "updatedVisibleItems" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutNearestRangeState.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutNearestRangeState.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutNearestRangeState" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPinnableItem.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPinnableItem.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutPinnableItem", + "LazyLayoutPinnedItemList" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPlatform.android.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPlatform.android.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "getDefaultLazyLayoutKey" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutPrefetchState.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutPrefetchState.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "Averages", + "LazyLayoutPrefetchState", + "NestedPrefetchScope", + "PrefetchHandleProvider", + "PrefetchMetrics", + "UnspecifiedNestedPrefetchCount", + "traversablePrefetchState" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutScrollDeltaBetweenPasses.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutScrollDeltaBetweenPasses.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutScrollDeltaBetweenPasses" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutScrollScope.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutScrollScope.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutScrollScope", + "animateScrollToItem", + "isItemVisible" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutSemanticState.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutSemanticState.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutSemanticState" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutSemantics.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutSemantics.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutSemanticState", + "estimatedLazyMaxScrollOffset", + "estimatedLazyScrollOffset", + "lazyLayoutSemantics" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyLayoutStickyItems.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyLayoutStickyItems.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "StickyItemsPlacement", + "applyStickyItems" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyList.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyList.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyList", + "defaultLazyListBeyondBoundsItemCount" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListBeyondBoundsModifier.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListBeyondBoundsModifier.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListBeyondBoundsState", + "rememberLazyListBeyondBoundsState" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListCacheWindowStrategy.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListCacheWindowStrategy.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListCacheWindowScope", + "LazyListCacheWindowStrategy" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListIntervalContent.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListIntervalContent.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListInterval", + "LazyListIntervalContent" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListItemInfo.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListItemInfo.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListItemInfo" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListItemProvider.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListItemProvider.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListItemProvider", + "rememberLazyListItemProviderLambda" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListLayoutInfo.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListLayoutInfo.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListLayoutInfo", + "calculateContentSize", + "singleAxisViewportSize", + "visibleItemsAverageSize" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasure.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasure.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "measureLazyList" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasureResult.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasureResult.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListMeasureResult" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasuredItem.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasuredItem.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListMeasuredItem" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListMeasuredItemProvider.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListMeasuredItemProvider.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListMeasuredItemProvider" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListPrefetchStrategy.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListPrefetchStrategy.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListPrefetchResultScope", + "LazyListPrefetchResultScopeImpl", + "LazyListPrefetchScope", + "LazyListPrefetchStrategy" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListScrollPosition.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListScrollPosition.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListScrollPosition", + "NearestItemsExtraItemCount", + "NearestItemsSlidingWindowSize" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListScrollScope.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListScrollScope.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyLayoutScrollScope" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListSemantics.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListSemantics.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "rememberLazyListSemanticState" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyListState.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyListState.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListState", + "rememberLazyListState" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazySaveableStateHolder.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazySaveableStateHolder.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazySaveableStateHolderProvider" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/LazyScopeMarker.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/LazyScopeMarker.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyScopeMarker" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/ObservableScopeInvalidator.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/ObservableScopeInvalidator.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "ObservableScopeInvalidator" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/PrefetchScheduler.android.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/PrefetchScheduler.android.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "AndroidPrefetchScheduler", + "PriorityTask", + "rememberDefaultPrefetchScheduler" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/PrefetchScheduler.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/PrefetchScheduler.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "PrefetchRequest", + "PrefetchRequestScope", + "PrefetchScheduler", + "PriorityPrefetchScheduler" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/README.md", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/README.md", + "oldPackage": null, + "newPackage": null, + "symbols": [] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/lazy/RecyclerLazyColumn.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/lazy/RecyclerLazyColumn.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.lazy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.lazy", + "symbols": [ + "LazyListScope", + "LazyRow", + "RecyclerLazyColumn", + "items", + "itemsIndexed" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/mentions/MentionSuggestionPanel.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/mentions/MentionSuggestionPanel.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.mentions", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.mentions", + "symbols": [ + "MentionSuggestionPanel", + "MentionSuggestionPanelStyle" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ChatNodeVisibility.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ChatNodeVisibility.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "isVisibleChatMarkdownNode", + "isVisibleChatXmlContent" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/CustomXmlRenderer.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/CustomXmlRenderer.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "CustomXmlRenderer" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/DetailsTagRenderer.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/DetailsTagRenderer.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "DetailsTagRenderer" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/DialogComponents.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/DialogComponents.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "ContentDetailDialog", + "DiffContentLazyColumn" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/FileDiffDisplay.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/FileDiffDisplay.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "FileDiff", + "FileDiffDisplay" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/FontTagRenderer.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/FontTagRenderer.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "FontTagRenderer" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ParamVisualizer.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ParamVisualizer.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "ParamItem", + "ParamVisualizer" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/StatusCardHtmlDocument.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/StatusCardHtmlDocument.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "StatusCardHtmlDocument" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsRows.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsRows.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "ThinkToolsGroupInfo", + "ThinkToolsRow", + "buildThinkToolsRows", + "thinkToolsGroupTitle" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsXmlNodeGrouper.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsXmlNodeGrouper.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "ThinkToolsXmlNodeGrouper" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkingMarkdownStream.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkingMarkdownStream.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "createThinkMarkdownCharStream" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ToolDisplayComponents.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ToolDisplayComponents.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "CodeContentWithLineNumbers", + "CompactToolDisplay", + "DetailedToolDisplay", + "FormattedXmlText" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ToolResultDisplay.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ToolResultDisplay.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "ToolResultDisplay" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/XmlCanvasBlockComponents.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/XmlCanvasBlockComponents.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "CanvasExpandableHeaderRow", + "CanvasFontTextBlock", + "CanvasPillLabel" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/XmlCanvasSummaryComponents.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/XmlCanvasSummaryComponents.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [ + "CanvasStatusCard", + "CanvasToolResultRow", + "CanvasToolSummaryRow", + "CanvasWarningStatusRow" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingIndex.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingIndex.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming", + "symbols": [ + "ToolCallTiming", + "ToolTimingIndex", + "ToolTimingSummary", + "elapsedUnion" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingTitle.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingTitle.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming", + "symbols": [ + "LocalInsideToolGroup", + "LocalToolTimingIndex", + "rememberMessageToolExecutions", + "toolTimingTitle" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleAiMessageComposable.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleAiMessageComposable.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble", + "symbols": [ + "BubbleAiMessageComposable" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageBackgroundSurface.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageBackgroundSurface.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble", + "symbols": [ + "BubbleImageBackgroundSurface" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageLayout.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageLayout.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble", + "symbols": [ + "BubbleDstSliceLayout", + "BubbleImageRenderMode", + "BubbleImageStyleConfig", + "BubbleSliceLayout", + "bubbleTileExtent", + "buildSliceLayout", + "computeDstSliceLayout", + "forMessageBlock" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageTiling.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageTiling.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble", + "symbols": [ + "BubbleImageTile", + "BubbleImageTiles", + "rememberBubbleImageTiles" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleStyleChatMessage.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleStyleChatMessage.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble", + "symbols": [ + "BubbleStyleChatMessage" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleUserMessageComposable.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleUserMessageComposable.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble", + "symbols": [ + "AttachmentData", + "BubbleUserMessageComposable", + "ImageLinkData", + "MessageParseResult", + "ReplyInfo" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/common/HiddenUserMessagePlaceholderContent.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/common/HiddenUserMessagePlaceholderContent.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.common", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.common", + "symbols": [ + "HiddenUserMessagePlaceholderContent" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/AiMessageComposable.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/AiMessageComposable.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor", + "symbols": [ + "AiMessageComposable" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/CursorStyleChatMessage.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/CursorStyleChatMessage.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor", + "symbols": [ + "CursorStyleChatMessage" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/SummaryMessageComposable.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/SummaryMessageComposable.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor", + "symbols": [ + "SummaryMessageComposable" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/cursor/UserMessageComposable.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/cursor/UserMessageComposable.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.cursor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.cursor", + "symbols": [ + "AttachmentData", + "ImageLinkData", + "MessageParseResult", + "ReplyInfo", + "UserMessageComposable" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/agent/AgentChatInputSection.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/agent/AgentChatInputSection.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.agent", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.agent", + "symbols": [ + "AgentChatInputSection" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatInputSection.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/classic/ClassicChatInputSection.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.classic", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.classic", + "symbols": [ + "ClassicChatInputSection" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/classic/ClassicChatSettingsBar.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/classic/ClassicChatSettingsBar.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.classic", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.classic", + "symbols": [ + "ClassicChatSettingsBar" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/CharacterCardMemoryBindingSwitchConfirmDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/CharacterCardMemoryBindingSwitchConfirmDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common", + "symbols": [ + "CharacterCardMemoryBindingSwitchConfirmDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/CharacterCardModelBindingSwitchConfirmDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/CharacterCardModelBindingSwitchConfirmDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common", + "symbols": [ + "CharacterCardModelBindingSwitchConfirmDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ChatInputHookRegistry.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ChatInputHookRegistry.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common", + "symbols": [ + "ChatInputEvents", + "ChatInputHook", + "ChatInputHookContext", + "ChatInputHookRegistry", + "ChatInputHookResult", + "ChatInputSubmitActions" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/InputMenuTogglePluginRegistry.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/InputMenuTogglePluginRegistry.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common", + "symbols": [ + "InputMenuToggleDefinition", + "InputMenuToggleHookParams", + "InputMenuTogglePlugin", + "InputMenuTogglePluginRegistry", + "InputMenuToggleSlots" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/MentionVisualTransformation.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/MentionVisualTransformation.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common", + "symbols": [ + "rememberMentionVisualTransformation" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/PendingMessageQueuePanel.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/PendingMessageQueuePanel.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common", + "symbols": [ + "PendingMessageQueuePanel" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ThinkingQualitySlider.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ThinkingQualitySlider.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common", + "symbols": [ + "ThinkingQualitySlider" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/ToolPromptManagerDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/common/ToolPromptManagerDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.input.common", + "symbols": [ + "ToolPromptManagerDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/timeline/ChatTimelineEntries.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/timeline/ChatTimelineEntries.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.timeline", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.timeline", + "symbols": [ + "ChatMessageAppearance", + "ChatMessageSlice", + "ChatTimelineEntry", + "LocalChatMessageSlice", + "rememberChatTimelineEntries", + "shouldSplitChatMessage" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/copy/MessageCopyTextField.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/copy/MessageCopyTextField.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.copy", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.copy", + "symbols": [ + "MessageCopyTextField" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/HtmlPackagerScreen.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/htmlpackager/HtmlPackagerScreen.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.export.htmlpackager", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.export.htmlpackager", + "symbols": [ + "HtmlPackagerScreen" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/export/htmlpackager/PackagerResources.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/export/htmlpackager/PackagerResources.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.export.htmlpackager", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.export.htmlpackager", + "symbols": [ + "PackagerPlatformDialog", + "PackagerResourceGate", + "PackagerResourceState", + "PackagerResourceSummary", + "packagerResourceGroups", + "rememberPackagerResources" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/ChatFolderTree.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/ChatFolderTree.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.folders", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders", + "symbols": [ + "ChatFolderRow", + "ChatHistorySortMode", + "FolderDropZone", + "buildChatFolderTree", + "folderKey", + "node", + "resolveFolderDrop" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderChatHistoryPanel.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderChatHistoryPanel.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.folders", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders", + "symbols": [ + "FolderChatHistoryPanel" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderHistoryDialogs.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderHistoryDialogs.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.folders", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders", + "symbols": [ + "FolderHistorySettingsDialog", + "FolderNameDialog", + "HistoryAction", + "HistoryActionsDialog", + "HistoryBindingOption", + "HistoryChatEditDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderTreeList.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderTreeList.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.folders", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders", + "symbols": [ + "FolderTreeList" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/HistoryCreateCapsule.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/HistoryCreateCapsule.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.folders", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders", + "symbols": [ + "HistoryCreateCapsule" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/HistoryQuickScroller.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/HistoryQuickScroller.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.folders", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders", + "symbols": [ + "HistoryQuickScroller" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/ChatListMotionState.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatListMotionState.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.motion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.history", + "symbols": [ + "ChatListMotionState" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/DissolvingChatTitle.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/motion/DissolvingChatTitle.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.motion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history.motion", + "symbols": [ + "DissolvingChatTitle" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/NewChatIntro.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/motion/NewChatIntro.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.motion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.motion", + "symbols": [ + "NewChatIntro" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/ChatSidebarContent.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/ChatSidebarContent.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.sidebar", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar", + "symbols": [ + "ChatSidebarContent" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/ChatSidebarState.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/ChatSidebarState.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.sidebar", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar", + "symbols": [ + "ChatSidebarState", + "LocalMainChatSidebarState", + "LocalMainChatViewModel", + "LocalOpenMainChatSidebar", + "LocalRunMainChatAction", + "rememberChatSidebarState" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/MainChatControls.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/MainChatControls.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.sidebar", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar", + "symbols": [ + "MainChatControls" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/SidebarButtonSurface.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/SidebarButtonSurface.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.sidebar", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar", + "symbols": [ + "SidebarButtonSurface" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/sidebar/SidebarPluginSection.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sidebar/SidebarPluginSection.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.sidebar", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.sidebar", + "symbols": [ + "SidebarPluginSection" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/util/MentionTokenUtils.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/mentions/MentionTokenUtils.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.util", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.mentions", + "symbols": [ + "MentionTokenRange", + "findCommittedMentionTokens", + "findMentionTokenEndingAtCursor", + "findMentionTokens", + "isMentionContinuation" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/util/MessageImageGenerator.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/sharing/MessageImageGenerator.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.util", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.sharing", + "symbols": [ + "MessageImageGenerator" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/ExpiredVoiceMessageTag.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/ExpiredVoiceMessageTag.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.voicemessages", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.voice", + "symbols": [ + "ExpiredVoiceMessageTag" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessagePlayer.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessagePlayer.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.voicemessages", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.voice", + "symbols": [ + "VoiceMessagePlayer", + "voiceDurationLabel" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSession.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSession.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.voicemessages", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.voice", + "symbols": [ + "VoiceMessagePhase", + "VoiceMessageSession", + "VoiceMessageState" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSheet.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSheet.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.voicemessages", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.voice", + "symbols": [ + "VoiceMessageSheet" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageSheetContent.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageSheetContent.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.voicemessages", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.voice", + "symbols": [ + "VoiceMessageSheetContent" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceMessageXmlPlugin.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceMessageXmlPlugin.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.voicemessages", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.voice", + "symbols": [ + "VoiceMessageXmlPlugin" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/voicemessages/VoiceWaveform.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/voice/VoiceWaveform.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.voicemessages", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.voice", + "symbols": [ + "VoiceWaveform" + ] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/GalleryDragSelectionTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/GalleryDragSelectionTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/ImagePreviewTransformTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/ImagePreviewTransformTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/attachments/images/SentImageSourcesTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/images/SentImageSourcesTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.attachments.images", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments.images", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchControllerTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatBatchControllerTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.batch", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.history", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatAreaTokenSpeedTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/ChatAreaTokenSpeedTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageCopyTextTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/MessageCopyTextTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/MessageEditorContentTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/editor/MessageEditorContentTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.editor", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/PastedTextAttachmentTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/attachments/PastedTextAttachmentTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.attachments", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/TokenHitRateFormatTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/format/TokenHitRateFormatTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.format", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/details/MessageStatsFormattingTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/MessageStatsFormattingTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.details", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.details", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/StatusCardHtmlDocumentTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/StatusCardHtmlDocumentTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkToolsRowsTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkToolsRowsTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/ThinkingMarkdownStreamTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/ThinkingMarkdownStreamTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/part/tooltiming/ToolTimingIndexTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/rendering/tooltiming/ToolTimingIndexTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.part.tooltiming", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.rendering.tooltiming", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/bubble/BubbleImageLayoutTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/style/bubble/BubbleImageLayoutTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.bubble", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.messages.style.bubble", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/folders/FolderChatHistoryTreeTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/history/folders/FolderChatHistoryTreeTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.folders", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.modules.history.folders", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/motion/ChatListMotionStateTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/history/ChatListMotionStateTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.motion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel.history", + "symbols": [] + } + ], + "retainedFiles": [ + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/AIChatScreen.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/screens/AIChatScreen.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.screens", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.screens", + "symbols": [ + "AIChatScreen" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "symbols": [ + "ChatViewModel" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/FloatingWindowDelegate.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/FloatingWindowDelegate.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "symbols": [ + "FloatingWindowDelegate" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/PendingMessageQueueStore.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/PendingMessageQueueStore.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "symbols": [ + "PendingMessageQueueState", + "PendingMessageQueueStore" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/UiStateDelegate.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/UiStateDelegate.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "symbols": [ + "UiStateDelegate" + ] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/PendingMessageQueueStoreTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/PendingMessageQueueStoreTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "symbols": [] + } + ], + "extractions": [ + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/ChatArea.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatStyle.kt", + "symbol": "ChatStyle", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.model", + "start": 10161, + "end": 10210, + "declaration": "enum class ChatStyle {\n CURSOR,\n BUBBLE\n}" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/CharacterSelectorPanel.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/CharacterSelectorTarget.kt", + "symbol": "CharacterSelectorTarget", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.model", + "start": 2463, + "end": 2664, + "declaration": "sealed interface CharacterSelectorTarget {\n data class CharacterCardTarget(val id: String) : CharacterSelectorTarget\n data class CharacterGroupTarget(val id: String) : CharacterSelectorTarget\n}" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/style/input/common/PendingMessageQueuePanel.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/PendingQueueMessageItem.kt", + "symbol": "PendingQueueMessageItem", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.style.input.common", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.model", + "start": 1663, + "end": 1741, + "declaration": "data class PendingQueueMessageItem(\n val id: Long,\n val text: String\n)" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatHistoryDisplayMode.kt", + "symbol": "ChatHistoryDisplayMode", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.model", + "start": 7316, + "end": 7420, + "declaration": "enum class ChatHistoryDisplayMode {\n BY_CHARACTER_CARD,\n BY_FOLDER,\n CURRENT_CHARACTER_ONLY\n}" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/viewmodel/ChatViewModel.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/TranslationUiState.kt", + "symbol": "TranslationUiState", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.viewmodel", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.model", + "start": 7420, + "end": 7606, + "declaration": "data class TranslationUiState(\n val isLoading: Boolean = false,\n val translatedText: String? = null,\n val errorMessage: String? = null,\n val isFromCache: Boolean = false,\n)" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchController.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatBatchModels.kt", + "symbol": "ChatBatchAction", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.batch", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.model", + "start": 284, + "end": 374, + "declaration": "enum class ChatBatchAction { SUMMARIZE_TITLES, ARCHIVE, UNARCHIVE, LOCK, UNLOCK, DELETE }" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchController.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatBatchModels.kt", + "symbol": "ChatBatchItemResult", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.batch", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.model", + "start": 374, + "end": 437, + "declaration": "enum class ChatBatchItemResult { SUCCEEDED, SKIPPED, FAILED }" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchController.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatBatchModels.kt", + "symbol": "ChatBatchProgress", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.batch", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.model", + "start": 437, + "end": 531, + "declaration": "data class ChatBatchProgress(val action: ChatBatchAction, val completed: Int, val total: Int)" + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/batch/ChatBatchController.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/foundation/model/ChatBatchModels.kt", + "symbol": "ChatBatchSummary", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.batch", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.foundation.model", + "start": 531, + "end": 615, + "declaration": "data class ChatBatchSummary(val succeeded: Int, val skipped: Int, val failed: Int)" + } + ] +} diff --git a/docs/TODO/chore/chat-responsibility-layout/index.md b/docs/TODO/chore/chat-responsibility-layout/index.md new file mode 100644 index 0000000000..abb2e4547b --- /dev/null +++ b/docs/TODO/chore/chat-responsibility-layout/index.md @@ -0,0 +1,66 @@ +--- +fork: https://github.com/3316891527/Operit +status: implemented-awaiting-ci +--- + +# 聊天代码按职责归类 + +工作区迁出后,原 `conversation.chat` 有 13 个直属子包、178 个 Kotlin 文件。`components` 同时容纳输入、消息渲染、附件、列表布局和页面组装;历史列表、归档与批量操作分散在多个根包。部分共享类型定义在具体 UI 文件中,被 `ChatViewModel` 和状态存储共同使用。 + +本批只整理 Kotlin 包结构,根层保留 `screens`、`modules`、`foundation`、`viewmodel`。没有拆分 Gradle 模块,也没有拆解 `ChatViewModel` 和输入框内部逻辑。当前主源码共有 184 个 Kotlin 文件,其中增加的 6 个文件承载从原文件提取的 9 个既有共享声明。 + +```text +chat/ + foundation/ + format/ + layout/ + lazy/ + list/ + mentions/ + model/ + progress/ + stream/ + modules/ + attachments/ + characters/ + export/ + history/ + input/ + messages/ + sharing/ + sidebar/ + usage/ + voice/ + screens/ + viewmodel/ + history/ +``` + +`modules` 按聊天功能归类,输入框的 Agent、经典模式、输入扩展与提及候选集中在 `input`;消息样式、时间线、XML 渲染、复制、编辑、详情与翻译集中在 `messages`。图片选择、附件预览、音视频播放和外部分享导入归入 `attachments`,消息截图生成与分享预览归入 `sharing`。 + +`foundation` 承载自定义列表、滚动扩展、流式适配、布局、格式和文本规则。该包不依赖 `modules`、`screens` 或 `viewmodel`。自定义列表的上游版本和来源说明随目录迁移,说明内源码链接改为相对路径。 + +`screens` 保留页面组装和页面标题。`viewmodel` 保留页面级状态与协调;批量控制器和聊天列表动画状态归入 `viewmodel.history`。面板持有的录音会话仍在语音功能内,生命周期不变。 + +共享声明放在 `foundation.model`,原样保留名称、字段、默认值和可见性: + +- `ChatStyle`、`CharacterSelectorTarget`、`PendingQueueMessageItem` +- `ChatHistoryDisplayMode`、`TranslationUiState` +- `ChatBatchAction`、`ChatBatchItemResult`、`ChatBatchProgress`、`ChatBatchSummary` + +- [x] 保存本批迁移前快照,建立主源码、测试和文档的逐文件映射 +- [x] 完成 173 个主源码文件、17 个 JVM 测试文件、1 个 Android 测试文件及 1 份来源说明的迁移 +- [x] 将基础能力归入 `foundation`,功能代码归入 `modules`,页面组装归入 `screens` +- [x] 将 9 个共享声明原样提取到 6 个独立文件 +- [x] 同步显式导入、全限定名和原同包引用,将拆分包的 2 处星号导入展开为对应显式引用 +- [x] 核对声明体与提取内容,检查旧路径残留、目标冲突和完整差异空白 +- [x] 更新相关文档,保留先前工作区迁移和既往清单的阶段记录 +- [x] 完成本地整理与静态核对,按后续交付要求转入独立分支和 PR 验证 + +本批不调整发送、流式渲染、复制、删除、语音、导出或权限行为,不新增旧包转发或类型别名。跨功能调用继续沿用原来的对象、参数和回调。 + +交付分支为 `refactor/conversation-chat-workspace-layout`,PR 目标为 `dev`。本批以 [PR #93](https://github.com/3316891527/Operit/pull/93) 的文件操作实现为基线;本批新增提交只整理目录和共享声明,PR 相对 `dev` 的差异同时包含该依赖。 + +逐文件映射、保留原路径文件和原样提取记录见 [files.json](files.json),静态核对及完整回归范围见[验证记录](01-validation.md)。本批承接[会话工作区迁移](../conversation-workspace-layout/index.md),已经合并核对两轮迁移前后的全部既有源码。 + +[DONE] 本地目录整理、共享声明提取与静态核对;编译、构建、测试和 CI 尚未验证本次迁移。 diff --git a/docs/TODO/chore/conversation-workspace-layout/01-validation.md b/docs/TODO/chore/conversation-workspace-layout/01-validation.md new file mode 100644 index 0000000000..623ed34bc2 --- /dev/null +++ b/docs/TODO/chore/conversation-workspace-layout/01-validation.md @@ -0,0 +1,52 @@ +# 会话工作区迁移验证 + +本页记录工作区迁移阶段的检查结果。后续聊天包迁移及两轮合并核对见[聊天迁移验证](../chat-responsibility-layout/01-validation.md)。 + +迁移基线为 `9b9bb75d93b96b72204067fa576db30e5279d960`,逐文件来源、目标、包名与主源码声明见 [files.json](files.json)。本批实施阶段先保留本地,后续交付与 CI 记录由聊天目录整理 PR 衔接。 + +## 已完成的静态核对 + +- 清单内 82 个文件全部迁移,包含 72 个主源码文件、8 个 JVM 测试文件和 2 个 Android 测试文件,目标目录与包声明一致 +- `main`、`test`、`androidTest` 中的旧 `chat/webview/` 与 `chat/workspace/` 目录均已移除,没有保留转发文件或包别名 +- 应用源码、仓库工作流、终端目录和根构建配置中没有旧 `conversation.chat.webview` 或 `conversation.chat.workspace` 引用 +- 核对 129 处相关显式导入和 17 处拆包后的原同包引用,覆盖工作区主页、网页服务、预览扩展属性、聊天提及面板和终端入口 +- 对迁移前的 1938 个 Kotlin、Java 源码文件逐一对照,确认本批变化限于 82 个迁移文件和 16 个调用方文件 +- 去除包声明及导入,并按完整符号映射替换旧包路径后,全部声明体与基线一致;声明体内仅 `WorkspaceManager.kt` 的 `NativeCodeEditor` 和 `FileUtils.kt` 的 `GitIgnoreFilter` 使用了需要同步的全限定路径 +- 使用临时 Git 索引纳入未跟踪的新路径后执行 `git diff --cached --check`,空白检查通过,Git 识别出 82 处重命名;真实暂存区未变,HEAD 仍为迁移基线 +- 更新相关开发文档中的当前路径,`chore/package-layout/` 下既往迁移清单保持原样 + +在仓库根目录可重新检查旧引用: + +```sh +rg -n 'conversation[./]chat[./](webview|workspace)' app .github terminal build.gradle.kts settings.gradle.kts +``` + +预期无输出,`rg` 退出码为 1。源码声明体对照以清单中的 `source`、`target`、`oldPackage`、`newPackage` 和基线提交为依据,比较前仅移除包声明及导入、归一化全限定包路径。 + +## 后续验证范围 + +本地未执行编译、构建或测试,后续远端验证以对应 PR 的派发及结果记录为准。静态声明和引用核对不代替 Kotlin 编译及 Android 运行验证。 + +| 编号 | 做什么 | 预期行为 | +| --- | --- | --- | +| L1 | 编译应用与 Android 测试源码 | 新包路径、显式导入和原同包引用全部解析 | +| L2 | 执行迁移的 8 个 JVM 测试类及原流式复制测试 | 原回归用例继续通过,测试没有遗漏 | +| L3 | 打开工作区主页,切换工作区与终端 | 原导航、会话标签与终端入口正常 | +| L4 | 浏览文件,打开编辑器、图片、文档、Markdown 与网页预览 | 文件入口、预览服务与刷新行为一致 | +| L5 | 在聊天输入框使用提及候选面板 | 候选展示、样式和选择行为一致 | +| L6 | 复查完整文件操作回归范围 | 复制、剪切、删除及取消保持既有行为 | + +L6 的全部自动用例、实机项与可填写结果表见[工作区复制与删除验证](../../fix/workspace-copy-streaming-progress/01-validation.md),包含此前已实现的复制及删除覆盖范围。 + +## 结果记录 + +| 编号 | 结果与证据 | +| --- | --- | +| L1 | 未运行 | +| L2 | 未运行 | +| L3 | 未验证 | +| L4 | 未验证 | +| L5 | 未验证 | +| L6 | 未验证,完整用例沿用关联记录 | + +[DONE] 静态核对;后续编译、测试和 Android 运行结果待填写。 \ No newline at end of file diff --git a/docs/TODO/chore/conversation-workspace-layout/files.json b/docs/TODO/chore/conversation-workspace-layout/files.json new file mode 100644 index 0000000000..d29c6ec86d --- /dev/null +++ b/docs/TODO/chore/conversation-workspace-layout/files.json @@ -0,0 +1,810 @@ +{ + "baseline": "9b9bb75d93b96b72204067fa576db30e5279d960", + "files": [ + { + "source": "app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceEditorCommentTest.kt", + "target": "app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceEditorCommentTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [] + }, + { + "source": "app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceEditorInitialLineTest.kt", + "target": "app/src/androidTest/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceEditorInitialLineTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/LocalWebServer.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/LocalWebServer.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.preview", + "symbols": [ + "FileApiEntry", + "LocalWebServer" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WebViewHandler.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WebViewHandler.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.preview", + "symbols": [ + "WebViewHandler" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceFileSelector.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/components/mentions/MentionSuggestionPanel.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.chat.components.mentions", + "symbols": [ + "MentionSuggestionPanel", + "MentionSuggestionPanelStyle" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/WorkspaceUtils.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceUtils.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace", + "symbols": [ + "createAndGetDefaultWorkspace", + "createAndResetWorkspaceDirectory", + "ensureWorkspaceDirExists", + "getLegacyWorkspacePath", + "getWorkspacePath" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/computer/ComputerScreen.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/automation/terminal/ComputerScreen.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.computer", + "newPackage": "com.ai.assistance.operit.ui.features.automation.terminal", + "symbols": [ + "ComputerScreen" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/FileManager.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/FileManager.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace", + "symbols": [ + "DirectoryEntry", + "FileBrowser", + "QuickPathEntry", + "getFileIcon" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceBackupManager.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceBackupManager.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace", + "symbols": [ + "BackupManifest", + "FileStat", + "WorkspaceBackupManager" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceCommandExecutionState.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceCommandExecutionState.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace", + "symbols": [ + "WorkspaceCommandExecutionState", + "toWorkspaceCommandOutputEntries" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceConfig.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceConfig.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace", + "symbols": [ + "CommandConfig", + "ExportConfig", + "PreviewConfig", + "ServerConfig", + "WatchConfig", + "WorkspaceConfig", + "WorkspaceConfigReader" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceFileModels.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceFileModels.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace", + "symbols": [ + "OpenFileInfo", + "key" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceFilePreviewSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceFilePreviewSupport.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.preview", + "symbols": [ + "buildWorkspacePreviewUri", + "isAudio", + "isHtml", + "isImage", + "isMarkdown", + "isMediaPreviewable", + "isPdf", + "isReadOnlyDocumentPreviewable", + "isReadOnlyPreview", + "isSpreadsheetDocument", + "isVideo", + "isWordDocument", + "resolvedMimeType", + "workspaceMimeTypeForPath", + "workspaceShouldOpenAsDirectPreview" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceImagePreview.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceImagePreview.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.preview", + "symbols": [ + "WorkspaceImagePreview" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceManager.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceManager.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace", + "symbols": [ + "CommandButtonsView", + "VSCodeTab", + "WorkspaceManager" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspacePreviewRefreshBus.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspacePreviewRefreshBus.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.preview", + "symbols": [ + "WorkspacePreviewRefreshBus", + "WorkspacePreviewRefreshEvent" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceReadOnlyDocumentPreview.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/preview/WorkspaceReadOnlyDocumentPreview.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.preview", + "symbols": [ + "WorkspacePreviewFileState", + "WorkspaceReadOnlyDocumentPreview", + "rememberWorkspacePreviewFileState", + "workspacePreviewUriFromFile" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceScreen.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceScreen.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace", + "symbols": [ + "WorkspaceScreen" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/WorkspaceSetup.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/WorkspaceSetup.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace", + "symbols": [ + "ProjectTypeCard", + "WorkspaceSetup" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserClipboard.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserClipboard.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser", + "symbols": [ + "FileBrowserClipboard", + "FileBrowserClipboardItem" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserSelectionBar.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserSelectionBar.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser", + "symbols": [ + "FileBrowserSelectionBar" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserDialogs.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserDialogs.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser", + "symbols": [ + "FileBrowserContextMenu", + "FileBrowserSortDialog", + "sortDirectoryEntries" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserOperations.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserOperations.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser", + "symbols": [ + "FileBrowserOperations" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserSupport.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser", + "symbols": [ + "directoryModifiedTime", + "isValidWorkspaceEntryName", + "pruneWorkspaceShareCache" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertiesDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertiesDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.properties", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser.properties", + "symbols": [ + "WorkspacePropertiesDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertiesRepository.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertiesRepository.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.properties", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser.properties", + "symbols": [ + "PropertyNode", + "WorkspaceDirectoryTotals", + "WorkspaceProperties", + "WorkspacePropertiesRepository", + "WorkspacePropertiesTarget", + "WorkspacePropertySource", + "WorkspaceTimeChangeResult" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertyAccess.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertyAccess.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.properties", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser.properties", + "symbols": [ + "WorkspacePropertyAccess" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/properties/WorkspacePropertyProviders.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/properties/WorkspacePropertyProviders.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.properties", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser.properties", + "symbols": [ + "RemoteWorkspacePropertySource", + "SafWorkspacePropertySource" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgress.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceCopyProgress.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer", + "symbols": [ + "WorkspaceCopyProgress" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceCopyProgressDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer", + "symbols": [ + "WorkspaceCopyProgressDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgress.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteProgress.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer", + "symbols": [ + "WorkspaceDeleteOperation", + "WorkspaceDeleteProgress" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteProgressDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer", + "symbols": [ + "WorkspaceDeleteProgressDialog" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceFileOperationDialog.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceFileOperationDialog.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer", + "symbols": [ + "WorkspaceFileOperationDialog", + "WorkspaceOperationDetail" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CanvasCodeEditorView.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CanvasCodeEditorView.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [ + "CanvasCodeEditorView", + "EditorCompletionCallback", + "EditorKeyCommand" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CodeEditor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CodeEditor.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [ + "CodeEditor", + "NativeCodeEditor" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CodeFormatter.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CodeFormatter.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [ + "CodeFormatter" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/CommentSyntax.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/CommentSyntax.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [ + "CommentSyntax", + "CommentSyntaxRegistry" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorDocument.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorDocument.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [ + "EditorDocument", + "EditorEditCommand", + "editorCellWidth", + "editorCodeUnitLength", + "editorExpandOffsetToCharacterEnd", + "editorNextCharacterOffset", + "editorNextSymbolOffset", + "editorPreviousCharacterOffset", + "editorPreviousSymbolOffset", + "editorSnapOffsetToCharacterBoundary" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorMetrics.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorMetrics.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [ + "EditorMetrics" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/EditorSyntaxHighlighter.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/EditorSyntaxHighlighter.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [ + "EditorSyntaxHighlighter", + "HighlightSnapshot" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/LanguageDetector.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/LanguageDetector.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [ + "LanguageDetector" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionPopup.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionPopup.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion", + "symbols": [ + "CompletionItemRow", + "CompletionPopup" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionProvider.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionProvider.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion", + "symbols": [ + "CompletionItem", + "CompletionItemKind", + "CompletionProvider" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/CompletionProviderFactory.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/CompletionProviderFactory.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion", + "symbols": [ + "CompletionProviderFactory" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/DartCompletionProvider.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/DartCompletionProvider.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion", + "symbols": [ + "DartCompletionProvider" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/DefaultCompletionProvider.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/DefaultCompletionProvider.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion", + "symbols": [ + "DefaultCompletionProvider" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/HtmlCompletionProvider.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/HtmlCompletionProvider.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion", + "symbols": [ + "HtmlCompletionProvider" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/JavaScriptCompletionProvider.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/JavaScriptCompletionProvider.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion", + "symbols": [ + "JavaScriptCompletionProvider" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/completion/KotlinCompletionProvider.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/completion/KotlinCompletionProvider.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.completion", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.completion", + "symbols": [ + "KotlinCompletionProvider" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/BaseLanguageSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/BaseLanguageSupport.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.language", + "symbols": [ + "BaseLanguageSupport" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/DartSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/DartSupport.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.language", + "symbols": [ + "DartSupport" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/HtmlSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/HtmlSupport.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.language", + "symbols": [ + "HtmlSupport" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/JavaScriptSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/JavaScriptSupport.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.language", + "symbols": [ + "JavaScriptSupport" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/KotlinSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/KotlinSupport.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.language", + "symbols": [ + "KotlinSupport" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageFactory.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageFactory.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.language", + "symbols": [ + "LanguageFactory" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageSupport.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageSupport.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.language", + "symbols": [ + "LanguageSupport" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/language/LanguageSupportRegistry.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/language/LanguageSupportRegistry.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.language", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.language", + "symbols": [ + "LanguageSupportRegistry" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/theme/EditorTheme.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/theme/EditorTheme.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor.theme", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor.theme", + "symbols": [ + "DarkTheme", + "EditorTheme", + "LightTheme", + "getThemeForLanguage" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLink.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLink.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.links", + "symbols": [ + "WorkspaceFileLink", + "parseWorkspaceFileLink" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkHost.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLinkHost.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.links", + "symbols": [ + "LocalWorkspaceFileLinkOpener", + "WorkspaceFileLinkDialog", + "WorkspaceFileLinkHost" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceMarkdownLink.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceMarkdownLink.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.links", + "symbols": [ + "WorkspaceMarkdownLink", + "findWorkspaceMarkdownAnchorLine", + "resolveWorkspaceMarkdownLink" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/markdown/WorkspaceMarkdownPreview.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/markdown/WorkspaceMarkdownPreview.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.markdown", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.markdown", + "symbols": [ + "WorkspaceMarkdownPreview" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/DepthLimitedFileObserver.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/DepthLimitedFileObserver.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.process", + "symbols": [ + "DepthLimitedFileObserver", + "WorkspaceFileChange", + "WorkspaceFileChangeKind" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/GitIgnoreFilter.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/GitIgnoreFilter.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.process", + "symbols": [ + "GitIgnoreFilter" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceAttachmentProcessor.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceAttachmentProcessor.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.process", + "symbols": [ + "WorkspaceAttachmentProcessor" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceChangeTracker.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceChangeTracker.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.process", + "symbols": [ + "WorkspaceChangeSnapshot", + "WorkspaceChangeTracker" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/process/WorkspaceRuleFileReader.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/process/WorkspaceRuleFileReader.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.process", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.process", + "symbols": [ + "WorkspaceRuleFileReader" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/search/WorkspaceTextSearch.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/search/WorkspaceTextSearch.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.search", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.search", + "symbols": [ + "FileSearchBar", + "activeSearchMatchAfterUpdate", + "findTextMatches" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/text/WorkspaceTextReadPolicy.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/text/WorkspaceTextReadPolicy.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.text", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.text", + "symbols": [ + "WORKSPACE_TEXT_PREVIEW_LIMIT_BYTES", + "readWorkspaceTextWithinLimit" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubHome.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubHome.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.hub", + "symbols": [ + "WorkspaceHubHome" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubOverlay.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubOverlay.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.hub", + "symbols": [ + "WorkspaceHubOverlay" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubScreen.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubScreen.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.hub", + "symbols": [ + "WorkspaceHubScreen" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceHubState.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceHubState.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.hub", + "symbols": [ + "WorkspaceEntryAction", + "WorkspaceEntryRequest", + "WorkspaceHubPage" + ] + }, + { + "source": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/workspace/WorkspaceSessionTabs.kt", + "target": "app/src/main/java/com/ai/assistance/operit/ui/features/conversation/workspace/hub/WorkspaceSessionTabs.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.workspace", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.hub", + "symbols": [ + "WorkspaceSessionTabs" + ] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/FileBrowserClipboardTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/FileBrowserClipboardTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/WorkspaceBrowserSupportTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/WorkspaceBrowserSupportTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/browser/transfer/WorkspaceDeleteOperationTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.browser.transfer", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.browser.transfer", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/editor/WorkspaceCommentSyntaxTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/editor/WorkspaceCommentSyntaxTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.editor", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.editor", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceFileLinkTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceFileLinkTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.links", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/links/WorkspaceMarkdownLinkTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/links/WorkspaceMarkdownLinkTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.links", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.links", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/search/WorkspaceTextSearchTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/search/WorkspaceTextSearchTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.search", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.search", + "symbols": [] + }, + { + "source": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/chat/webview/workspace/text/WorkspaceTextReadPolicyTest.kt", + "target": "app/src/test/java/com/ai/assistance/operit/ui/features/conversation/workspace/text/WorkspaceTextReadPolicyTest.kt", + "oldPackage": "com.ai.assistance.operit.ui.features.conversation.chat.webview.workspace.text", + "newPackage": "com.ai.assistance.operit.ui.features.conversation.workspace.text", + "symbols": [] + } + ] +} diff --git a/docs/TODO/chore/conversation-workspace-layout/index.md b/docs/TODO/chore/conversation-workspace-layout/index.md new file mode 100644 index 0000000000..186d8d4ae3 --- /dev/null +++ b/docs/TODO/chore/conversation-workspace-layout/index.md @@ -0,0 +1,26 @@ +--- +fork: https://github.com/3316891527/Operit +status: implemented-awaiting-ci +--- + +# 会话工作区按职责归类 + +原 `conversation.chat.webview` 同时包含工作区、代码编辑器、文件浏览器、网页预览、聊天提及候选面板和终端入口。原 `conversation.chat.workspace` 另存放工作区主页与导航。目录归属仍以早期网页预览实现为中心,无法反映这些功能的现有职责。 + +本批将工作区提升到 `ui.features.conversation.workspace`,沿用项目已有的复数 `features`,与 `chat` 平级。现有浏览、编辑、搜索、链接、处理和文件操作子包保留各自职责,网页预览归入 `workspace.preview`,主页与导航归入 `workspace.hub`。 + +- [x] 建立逐文件迁移清单,包含 72 个主源码文件、8 个 JVM 测试文件与 2 个 Android 测试文件 +- [x] 移除旧 `chat.webview` 源码目录,工作区主页与导航一起迁出 `chat.workspace` +- [x] 提及候选面板归入 `chat.components.mentions` 并按实际组件改名为 `MentionSuggestionPanel.kt`;终端入口归入现有 `automation.terminal` +- [x] 同步所有调用、包声明、显式导入、星号导入和原同包隐式引用 +- [x] 核对迁移前后声明体,确认仅包名、导入和显式路径发生变化 +- [x] 更新当前开发文档中的路径,保留既往迁移清单的历史记录 +- [x] 完成实施阶段本地迁移,后续交付记录由聊天目录整理分支和 PR 衔接 + +此次不改变应用身份、用户工作区目录、配置 JSON、预览服务端口、编辑器行为或文件操作规则。复制与删除的实现和回归用例随目录一起迁移。 + +后续[聊天职责整理](../chat-responsibility-layout/index.md)已继续归类聊天代码,提及候选面板的当前位置为 `chat.modules.input.mentions`。本页和 `files.json` 保留工作区迁移阶段的映射,最终位置由后一阶段清单继续衔接。 + +逐文件映射见 [files.json](files.json),本批静态核对见[迁移验证记录](01-validation.md),完整文件操作回归范围见[文件操作验证](../../fix/workspace-copy-streaming-progress/01-validation.md)。 + +[DONE] 本地迁移与静态核对;编译、测试和 CI 尚未验证本次迁移。 diff --git "a/docs/TODO/feat/chat-archive-and-settings-polish/01-\345\256\236\347\216\260\344\270\216\351\252\214\350\257\201.md" "b/docs/TODO/feat/chat-archive-and-settings-polish/01-\345\256\236\347\216\260\344\270\216\351\252\214\350\257\201.md" index db7f040fde..83b6a9b65e 100644 --- "a/docs/TODO/feat/chat-archive-and-settings-polish/01-\345\256\236\347\216\260\344\270\216\351\252\214\350\257\201.md" +++ "b/docs/TODO/feat/chat-archive-and-settings-polish/01-\345\256\236\347\216\260\344\270\216\351\252\214\350\257\201.md" @@ -13,7 +13,7 @@ ## 2. 对话归档 -新增 `data/chat/archive` 与 `ui/features/chat/archive`。数据库从 27 升到 28,只为聊天元数据新增 `archived`,已有聊天默认未归档。 +归档数据实现位于 `data/chat/archive`,归档筛选界面位于 `ui/features/conversation/chat/modules/history/`。数据库从 27 升到 28,只为聊天元数据新增 `archived`,已有聊天默认未归档。 - 历史列表与主侧栏共用“归档对话”“恢复到聊天列表”操作及“已归档”筛选 - 归档保留消息、工作区、文件夹路径、角色绑定、锁定、置顶、排序和最近使用时间 diff --git "a/docs/TODO/feat/chat-batch-and-settings/01-\345\256\236\347\216\260\350\257\264\346\230\216.md" "b/docs/TODO/feat/chat-batch-and-settings/01-\345\256\236\347\216\260\350\257\264\346\230\216.md" index f727cf6ca4..f7ed3ee245 100644 --- "a/docs/TODO/feat/chat-batch-and-settings/01-\345\256\236\347\216\260\350\257\264\346\230\216.md" +++ "b/docs/TODO/feat/chat-batch-and-settings/01-\345\256\236\347\216\260\350\257\264\346\230\216.md" @@ -2,7 +2,7 @@ ## 对话批量操作 -`ui/features/chat/batch/` 独立维护执行器、进度与操作控件。侧栏和独立历史面板都通过现有聊天 ViewModel 接入,搜索与列表设置各左移一格,新建胶囊宽度不变,最右侧显示批量操作图标。 +`ui/features/conversation/chat/modules/history/batch/` 维护操作控件,执行器位于 `chat/viewmodel/history/`,动作和进度声明位于 `chat/foundation/model/`。侧栏和独立历史面板都通过现有聊天 ViewModel 接入,搜索与列表设置各左移一格,新建胶囊宽度不变,最右侧显示批量操作图标。 选择模式用整行复选框语义切换对话,不会打开聊天。可全选当前展开列表、取消选择和退出;全选包含可滚动到但尚未上屏的行,不包含折叠文件夹、另一归档视图或其他筛选范围。当前列表范围缩小时清理隐藏选择。列表仍可滚动、展开目录和快速定位。 diff --git "a/docs/TODO/feat/chat-image-picker-preview/01-\345\256\236\347\216\260\344\270\216\351\252\214\350\257\201.md" "b/docs/TODO/feat/chat-image-picker-preview/01-\345\256\236\347\216\260\344\270\216\351\252\214\350\257\201.md" index 7d92b00830..fd1787fc6f 100644 --- "a/docs/TODO/feat/chat-image-picker-preview/01-\345\256\236\347\216\260\344\270\216\351\252\214\350\257\201.md" +++ "b/docs/TODO/feat/chat-image-picker-preview/01-\345\256\236\347\216\260\344\270\216\351\252\214\350\257\201.md" @@ -8,7 +8,7 @@ ## 组件与数据流 -新增的 `ui/features/chat/attachments/images/` 包包含以下组件: +图片选择与预览位于 `ui/features/conversation/chat/modules/attachments/images/`,包含以下组件: - `ChatImagePickerDialog.kt`:全屏 Compose 相册网格,按 MediaStore 的图片时间倒序展示;支持相册筛选、跨相册多选、长按或按钮预览、确认数量、刷新,以及照片授权状态 - `MediaStoreImageRepository.kt`:在 IO 线程读取图片元数据,读取循环响应取消;区分无权限、部分图片权限和完整权限,不把查询失败显示成空相册 diff --git "a/docs/TODO/feat/chat_ui_redesign/01-\346\266\210\346\201\257\347\224\237\346\210\220\350\257\246\346\203\205.md" "b/docs/TODO/feat/chat_ui_redesign/01-\346\266\210\346\201\257\347\224\237\346\210\220\350\257\246\346\203\205.md" index c7fbb7bc69..674208efcb 100644 --- "a/docs/TODO/feat/chat_ui_redesign/01-\346\266\210\346\201\257\347\224\237\346\210\220\350\257\246\346\203\205.md" +++ "b/docs/TODO/feat/chat_ui_redesign/01-\346\266\210\346\201\257\347\224\237\346\210\220\350\257\246\346\203\205.md" @@ -8,7 +8,7 @@ ## 实现范围 -`app/src/main/java/com/ai/assistance/operit/ui/features/chat/components/details/` 独立负责生成详情和公共格式化。`ChatArea.kt` 接入详情和右下角完成时间,`MessageInfoDialog.kt` 复用完整数字、Token 明细、耗时和速率格式。 +`app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/messages/details/` 独立负责生成详情和公共格式化。`ChatArea.kt` 接入详情和右下角完成时间,`MessageInfoDialog.kt` 复用完整数字、Token 明细、耗时和速率格式。 生成详情默认折叠。启用 Token 简报时,标题只显示整数 K/M/B 总用量;不足 1,000 时显示原数字。缩写使用四舍五入,达到 1000K 或 1000M 时进位为 1M 或 1B。展开后按以下顺序显示四组信息,窄屏和大字体允许明细自然换行: diff --git "a/docs/TODO/feat/chat_ui_redesign/04-\345\267\245\344\275\234\345\214\272\344\270\216\347\273\210\347\253\257\347\273\237\344\270\200\345\205\245\345\217\243.md" "b/docs/TODO/feat/chat_ui_redesign/04-\345\267\245\344\275\234\345\214\272\344\270\216\347\273\210\347\253\257\347\273\237\344\270\200\345\205\245\345\217\243.md" index 78edc5c033..b500d356a7 100644 --- "a/docs/TODO/feat/chat_ui_redesign/04-\345\267\245\344\275\234\345\214\272\344\270\216\347\273\210\347\253\257\347\273\237\344\270\200\345\205\245\345\217\243.md" +++ "b/docs/TODO/feat/chat_ui_redesign/04-\345\267\245\344\275\234\345\214\272\344\270\216\347\273\210\347\253\257\347\273\237\344\270\200\345\205\245\345\217\243.md" @@ -6,7 +6,7 @@ ## 作用域 -- 新建 `ui/features/chat/workspace`,承载统一导航状态、主页和页面容器。 +- 工作区统一导航状态、主页和页面容器位于 `ui/features/conversation/workspace/hub/`。 - 右上角保留一个工作区按钮,继续使用已绑定/未绑定的图标;进入时隐藏输入法。 - 主页显示当前工作区、关联对话和角色卡、绑定目录、实际终端会话数,以及创建、选择、工作区和终端入口。 - 创建和选择入口直接调用现有项目模板弹窗与目录选择器;保留 Android、Linux 和 SAF 工作区的绑定能力。 diff --git "a/docs/TODO/feat/chat_ui_redesign/14-\345\257\271\350\257\235\344\270\216\350\247\222\350\211\262\350\277\233\345\205\245\344\270\273\344\276\247\350\276\271\346\240\217.md" "b/docs/TODO/feat/chat_ui_redesign/14-\345\257\271\350\257\235\344\270\216\350\247\222\350\211\262\350\277\233\345\205\245\344\270\273\344\276\247\350\276\271\346\240\217.md" index c1dfacbe0b..c5ce1bbfb4 100644 --- "a/docs/TODO/feat/chat_ui_redesign/14-\345\257\271\350\257\235\344\270\216\350\247\222\350\211\262\350\277\233\345\205\245\344\270\273\344\276\247\350\276\271\346\240\217.md" +++ "b/docs/TODO/feat/chat_ui_redesign/14-\345\257\271\350\257\235\344\270\216\350\247\222\350\211\262\350\277\233\345\205\245\344\270\273\344\276\247\350\276\271\346\240\217.md" @@ -15,7 +15,7 @@ branch: feat/chat-ui-redesign ## 实现范围 -- `ui/features/chat/sidebar/` 提供侧栏组件、共享状态和 `MainChatControls`。`OperitApp` 创建 Activity 级 ChatViewModel,侧栏和主聊天路由共用当前对话、生成状态、历史筛选及角色切换设置。 +- `ui/features/conversation/chat/modules/sidebar/` 提供侧栏组件、共享状态和 `MainChatControls`。`OperitApp` 创建 Activity 级 ChatViewModel,侧栏和主聊天路由共用当前对话、生成状态、历史筛选及角色切换设置。 - 侧栏品牌与收起按钮使用一行,角色头像、名称及切换箭头使用下一行,旁边用小图标打开角色管理。角色卡和群组选择继续复用现有选择面板,头像规则不变。 - 目录工具行包含 36dp 高的新建对话按钮,以及文件夹、搜索和历史设置图标。搜索由图标按需展开为 36dp 高的输入框,主动展开时请求焦点;关闭抽屉或跳转前清除焦点并收起输入法。 - 嵌套目录占剩余高度。原有三种显示方式、搜索、排序、拖动、置顶、锁定、绑定编辑、删除和目录数据继续复用。目录主标题、次级信息、选中行和拖动预览明确设置对应文字色,侧栏自定义背景也传递给目录。 diff --git "a/docs/TODO/feat/chat_ui_redesign/16-\350\247\222\350\211\262\345\274\271\347\252\227\344\270\216\346\250\241\345\236\213\346\240\207\350\257\206\345\217\212\350\256\260\345\277\206\350\256\276\347\275\256.md" "b/docs/TODO/feat/chat_ui_redesign/16-\350\247\222\350\211\262\345\274\271\347\252\227\344\270\216\346\250\241\345\236\213\346\240\207\350\257\206\345\217\212\350\256\260\345\277\206\350\256\276\347\275\256.md" index 383b502336..289e04f148 100644 --- "a/docs/TODO/feat/chat_ui_redesign/16-\350\247\222\350\211\262\345\274\271\347\252\227\344\270\216\346\250\241\345\236\213\346\240\207\350\257\206\345\217\212\350\256\260\345\277\206\350\256\276\347\275\256.md" +++ "b/docs/TODO/feat/chat_ui_redesign/16-\350\247\222\350\211\262\345\274\271\347\252\227\344\270\216\346\250\241\345\236\213\346\240\207\350\257\206\345\217\212\350\256\260\345\277\206\350\256\276\347\275\256.md" @@ -12,7 +12,7 @@ branch: feat/chat-ui-redesign [角色编辑](../../../../app/src/main/java/com/ai/assistance/operit/ui/features/settings/components/CharacterCardDialog.kt)复用新的[分页弹窗](../../../../app/src/main/java/com/ai/assistance/operit/ui/common/dialogs/ContentSizedTabbedDialog.kt)。窗口宽度上限为 640dp,屏幕及键盘共同限制可用高度。当前页通过滚动容器内部的完整内容测量决定页高,保留各页独立滚动位置与表单草稿;窄屏或大字体下,底部操作可换行。表单采用圆角、淡色容器和较柔和的边框。 -[Agent 输入栏](../../../../app/src/main/java/com/ai/assistance/operit/ui/features/chat/components/style/input/agent/AgentChatInputSection.kt)的两种输入布局、模型摘要、配置列表以及多模型配置展开后的各个条目,均复用 ProviderLogoLoader 的供应商素材。标识随实际配置的供应商变化;现有加载器没有登记素材时不增加占位标识。名称仍可省略,配置中的长模型名增加宽度约束。 +[Agent 输入栏](../../../../app/src/main/java/com/ai/assistance/operit/ui/features/conversation/chat/modules/input/agent/AgentChatInputSection.kt)的两种输入布局、模型摘要、配置列表以及多模型配置展开后的各个条目,均复用 ProviderLogoLoader 的供应商素材。标识随实际配置的供应商变化;现有加载器没有登记素材时不增加占位标识。名称仍可省略,配置中的长模型名增加宽度约束。 设置首页保留 GitHub 账号管理入口,登录和退出统一在既有账号页面操作。 diff --git "a/docs/TODO/feat/chat_ui_redesign/22-\344\270\212\344\270\213\346\226\207\347\273\237\350\256\241\344\270\216\347\264\257\350\256\241\347\224\250\351\207\217.md" "b/docs/TODO/feat/chat_ui_redesign/22-\344\270\212\344\270\213\346\226\207\347\273\237\350\256\241\344\270\216\347\264\257\350\256\241\347\224\250\351\207\217.md" index d46939c1b1..a638fae6d9 100644 --- "a/docs/TODO/feat/chat_ui_redesign/22-\344\270\212\344\270\213\346\226\207\347\273\237\350\256\241\344\270\216\347\264\257\350\256\241\347\224\250\351\207\217.md" +++ "b/docs/TODO/feat/chat_ui_redesign/22-\344\270\212\344\270\213\346\226\207\347\273\237\350\256\241\344\270\216\347\264\257\350\256\241\347\224\250\351\207\217.md" @@ -14,7 +14,7 @@ status: 源码完成,待仓库工作流和实机验收 ## 作用域 - 将 #1249 的请求快照、分类估算接入现有消息准备链路,详情读取不发布窗口估算,也不更新累计计数 -- 新建 `core/chat/context/` 与 `ui/features/chat/components/context/`,分别承载窗口拆分与统计界面 +- 新建 `core/chat/context/` 与 `ui/features/conversation/chat/modules/usage/`,分别承载窗口拆分与统计界面 - 窗口占用页展示消息历史及用户、AI、工具结果子项,系统提示词、常驻工具、MCP/包工具、技能目录、压缩摘要和其他占用 - 显示剩余空间、自动总结缓冲与设置阈值,复用现有手动总结操作 - 累计用量页读取当前对话已有输入、输出计数,展示总计及输入、输出构成;不从当前可见消息重新求和 diff --git "a/docs/TODO/feat/chat_ui_redesign/25-\345\244\215\345\256\241\347\277\273\350\257\221\344\270\216\347\216\273\347\222\203\346\225\210\346\236\234\346\201\242\345\244\215.md" "b/docs/TODO/feat/chat_ui_redesign/25-\345\244\215\345\256\241\347\277\273\350\257\221\344\270\216\347\216\273\347\222\203\346\225\210\346\236\234\346\201\242\345\244\215.md" index a9d7f121ba..debd689d46 100644 --- "a/docs/TODO/feat/chat_ui_redesign/25-\345\244\215\345\256\241\347\277\273\350\257\221\344\270\216\347\216\273\347\222\203\346\225\210\346\236\234\346\201\242\345\244\215.md" +++ "b/docs/TODO/feat/chat_ui_redesign/25-\345\244\215\345\256\241\347\277\273\350\257\221\344\270\216\347\216\273\347\222\203\346\225\210\346\236\234\346\201\242\345\244\215.md" @@ -12,7 +12,7 @@ ## 玻璃回归的原因与改动 -`liquidGlass` 的 `enableLens` 共享默认值由 true 改为 false,导致原来依赖默认值的三个输入框调用和一个工作区文件提及面板调用失去透镜效果。本次在 Agent 输入框两处、经典输入框一处及 `WorkspaceFileSelector` 一处显式传入 `enableLens = true`,使原有透镜不再取决于共享默认值。纯磨砂区域和气泡上原有的 `enableLens = false` 继续保留。 +`liquidGlass` 的 `enableLens` 共享默认值由 true 改为 false,导致原来依赖默认值的三个输入框调用和一个工作区文件提及面板调用失去透镜效果。本次在 Agent 输入框两处、经典输入框一处及 `chat.modules.input.mentions.MentionSuggestionPanel` 一处显式传入 `enableLens = true`,使原有透镜不再取决于共享默认值。纯磨砂区域和气泡上原有的 `enableLens = false` 继续保留。 `WaterGlass` 此前把曲面强度统一降为 0.08、折射统一降为 0.02,聊天气泡和输入框的水玻璃辨识度随之降低。本次恢复聊天区域原有的深浅主题强度:曲面为浅色 0.40、深色 0.30,折射为浅色 0.12、深色 0.09。手机与宽屏侧栏通过 `subtleRefraction = true` 显式保留 0.08、0.02,维持已经调整的低强度侧栏观感。 diff --git a/docs/TODO/feat/linux-file-preview/02-file-links-and-theme.md b/docs/TODO/feat/linux-file-preview/02-file-links-and-theme.md index cca444f027..a10a1d9ba5 100644 --- a/docs/TODO/feat/linux-file-preview/02-file-links-and-theme.md +++ b/docs/TODO/feat/linux-file-preview/02-file-links-and-theme.md @@ -4,7 +4,7 @@ ## 聊天文件入口 -新增 `ui/features/chat/webview/workspace/links/` 功能目录。WorkspaceFileLink 解析路径、来源环境与行号,WorkspaceFileLinkHost 作为 ChatScreenContent 的文件入口容器;Cursor 与 Bubble 共用的 LinkPreviewDialog 在点击“访问”后把文件请求交给该容器。 +文件链接功能位于 `ui/features/conversation/workspace/links/`。WorkspaceFileLink 解析路径、来源环境与行号,WorkspaceFileLinkHost 作为 ChatScreenContent 的文件入口容器;Cursor 与 Bubble 共用的 LinkPreviewDialog 在点击“访问”后把文件请求交给该容器。 | 链接形式 | 来源与打开行为 | | --- | --- | diff --git a/docs/TODO/feat/linux-file-preview/index.md b/docs/TODO/feat/linux-file-preview/index.md index f4f8aac9d5..24a81b72bf 100644 --- a/docs/TODO/feat/linux-file-preview/index.md +++ b/docs/TODO/feat/linux-file-preview/index.md @@ -23,7 +23,7 @@ branch: feat/linux-file-preview ## 实现范围与结构 -- 在现有 `ui/features/chat/webview/workspace/` 下扩展文件浏览器、工作区管理器和选择工作区页;文件操作菜单与排序对话框拆为同一功能包下的辅助组件。 +- 文件浏览器、工作区管理器和选择工作区页位于 `ui/features/conversation/workspace/`;文件操作菜单与排序对话框归入其 `browser/` 子包。 - 复用 `FileUtils` 的文本类型判断、已有 `CodeEditor`,以及图片、播放器、PDF、Word 和表格预览组件。 - 绑定后的 `WorkspaceManager` 默认显示 `FileBrowser`,预览通过顶部标签进入;导出、重命名和解绑移到顶部菜单,编辑操作显示在编辑页面上方。 - 未绑定状态通过 `WorkspaceScreen` 临时打开文件,保存按文件携带的来源环境执行,返回时恢复目录选择页,不修改聊天绑定。 diff --git a/docs/TODO/feat/voice-messages/01-implementation.md b/docs/TODO/feat/voice-messages/01-implementation.md index 0594c5abb0..2fdecc2f82 100644 --- a/docs/TODO/feat/voice-messages/01-implementation.md +++ b/docs/TODO/feat/voice-messages/01-implementation.md @@ -9,7 +9,7 @@ 经典和 Agent 输入组件新增可选录音回调,主聊天页主动接入。尚无当前聊天时先沿用新建聊天流程,再打开录音面板。空白文字、没有附件、没有引用且未处理请求时显示麦克风;已有附件仍走发送,正在处理仍保留取消逻辑。附件菜单里的语音通话继续使用原入口。未接入新回调的其他输入组件调用点保留原行为。 -`ui/features/chat/voicemessages/` 独立提供底部录音面板、会话状态和播放器。首次打开请求麦克风权限,录音显示计时、实际 PCM 音量波形、关闭和“说完了”。录制结束进入确认页,成功转写后才允许发送,可以试听、查看文字和重录,失败后可重试转写。 +`ui/features/conversation/chat/modules/voice/` 独立提供底部录音面板、会话状态和播放器。首次打开请求麦克风权限,录音显示计时、实际 PCM 音量波形、关闭和“说完了”。录制结束进入确认页,成功转写后才允许发送,可以试听、查看文字和重录,失败后可重试转写。 `api/speech/voicemessage/` 使用独立 AudioRecord 录制 16 kHz 单声道 PCM16 WAV,文件位于 `filesDir/media_pool/voice/`,现有媒体存储统计和音频清理会覆盖该目录。Silero VAD 检测人声,连续三秒未检测到人声时停止;从开始一直无人声同样停止并提示重新录制。第一版设置 60 秒上限,波形压缩为至多 48 个峰值。VAD 和 AudioRecord 在录制结束时释放,非阻塞读取避免取消等待音频读满。 diff --git "a/docs/TODO/fix/chat-single-scroll/01-\345\215\225\345\261\202\346\273\232\345\212\250\345\256\236\347\216\260.md" "b/docs/TODO/fix/chat-single-scroll/01-\345\215\225\345\261\202\346\273\232\345\212\250\345\256\236\347\216\260.md" index fcd0adab27..aadc6834fb 100644 --- "a/docs/TODO/fix/chat-single-scroll/01-\345\215\225\345\261\202\346\273\232\345\212\250\345\256\236\347\216\260.md" +++ "b/docs/TODO/fix/chat-single-scroll/01-\345\215\225\345\261\202\346\273\232\345\212\250\345\256\236\347\216\260.md" @@ -8,7 +8,7 @@ 主聊天由普通滚动列切换为标准 Compose LazyColumn。短回复仍作为完整条目;可见节点数达到 24 或可见节点正文总长度达到 32,000 字符时,长回复的分组标题、工具调用、结果与 Markdown 节点作为外层列表条目显示。超长纯文本按块保留全部内容,分块不切断 emoji 的代理对。 -`chat/components/timeline` 按消息准备流式和静态节点,并把条目映射到完整消息索引。消息身份包含聊天、时间戳、同时间戳序号与所选回答版本。分组和卡片使用节点类型及同类型序号作为身份,减少协议元数据过滤及流式转静态时的身份变化。 +`chat/modules/messages/timeline` 按消息准备流式和静态节点,并把条目映射到完整消息索引。消息身份包含聊天、时间戳、同时间戳序号与所选回答版本。分组和卡片使用节点类型及同类型序号作为身份,减少协议元数据过滤及流式转静态时的身份变化。 `common/markdown/lazy` 提供内容块渲染接口和消息持有的卡片状态。流式收集与静态解析不随条目离屏取消,离屏只停止布局和绘制;工具、思考、details 和分组的手动展开选择由消息保存。嵌套 Markdown 渲染清除外层片段上下文,完整消息预览与导出继续使用完整渲染入口。 diff --git "a/docs/TODO/fix/oom-workflow-audio/01-\345\256\232\344\275\215\344\270\216\344\277\256\345\244\215.md" "b/docs/TODO/fix/oom-workflow-audio/01-\345\256\232\344\275\215\344\270\216\344\277\256\345\244\215.md" index 9a2843f5cf..ee6307f69a 100644 --- "a/docs/TODO/fix/oom-workflow-audio/01-\345\256\232\344\275\215\344\270\216\344\277\256\345\244\215.md" +++ "b/docs/TODO/fix/oom-workflow-audio/01-\345\256\232\344\275\215\344\270\216\344\277\256\345\244\215.md" @@ -52,7 +52,7 @@ 文本、Base64 和需注入脚本的 HTML 响应继续按各自协议处理。没有新增播放器、改变音频编码或增加音频文件大小限制,也没有增加新的错误回退。 -修改位置:`ui/common/composedsl/ToolPkgComposeDslWebView.kt`、`ui/features/chat/webview/LocalWebServer.kt`。 +修改位置:`ui/common/composedsl/ToolPkgComposeDslWebView.kt`、`ui/features/conversation/workspace/preview/LocalWebServer.kt`。 ### 生命周期核对