chore: remove stale gateway settings and app ffi paths
This commit is contained in:
parent
87c978d456
commit
b9a9999291
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
# Miscellaneous
|
||||
.env
|
||||
.playwright-mcp/
|
||||
*.py
|
||||
null/
|
||||
test/golden/failures/
|
||||
|
||||
27
Makefile
27
Makefile
@ -118,7 +118,7 @@ package-rpm: ## Create the Linux .rpm package
|
||||
package-linux: ## Create both Linux packages
|
||||
bash scripts/package-linux.sh
|
||||
|
||||
package-mac: ffi-integrate build-go-core ## Create the macOS .app and DMG
|
||||
package-mac: build-go-core ## Create the macOS .app and DMG
|
||||
XWORKMATE_APP_STORE=true bash scripts/package-flutter-mac-app.sh
|
||||
|
||||
install-mac: package-mac ## Package and install the macOS app into /Applications
|
||||
@ -130,28 +130,3 @@ clean: ## Remove generated artifacts
|
||||
|
||||
check-export-compliance: ## Verify source and built Apple plist export-compliance flags
|
||||
bash scripts/check-apple-export-compliance.sh
|
||||
|
||||
# Rust FFI targets
|
||||
.PHONY: rust-build rust-build-release rust-build-debug rust-test ffi-copy ffi-generate
|
||||
|
||||
rust-build: rust-build-release ## Build Rust FFI library (release mode)
|
||||
|
||||
rust-build-release: ## Build Rust FFI library for macOS (release)
|
||||
@echo "Skip cargo build (external management)"
|
||||
|
||||
rust-build-debug: ## Build Rust FFI library in debug mode
|
||||
@echo "Skip cargo build (external management)"
|
||||
|
||||
rust-test: ## Run Rust tests
|
||||
cd rust && cargo test
|
||||
|
||||
ffi-copy: ## Copy FFI library to macOS Frameworks
|
||||
bash scripts/copy_ffi_framework.sh
|
||||
|
||||
ffi-generate: ## Generate FFI bindings using flutter_rust_bridge
|
||||
bash scripts/generate_ffi_bindings.sh
|
||||
|
||||
ffi-integrate: ffi-copy ## Copy FFI library (full integration)
|
||||
|
||||
# Build with FFI integration
|
||||
build-macos-ffi: ffi-copy build-macos ## Build macOS app with FFI integration
|
||||
|
||||
@ -73,24 +73,6 @@ mobile:
|
||||
build_modes: [debug, profile, release]
|
||||
description: Mobile vault server settings
|
||||
ui_surface: settings_page
|
||||
gateway_self_hosted_base:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: [debug, profile, release]
|
||||
description: Mobile self-hosted gateway base controls
|
||||
ui_surface: settings_page
|
||||
gateway_advanced_custom_mode:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: [debug, profile, release]
|
||||
description: Mobile advanced gateway override controls
|
||||
ui_surface: settings_page
|
||||
gateway_setup_code:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: [debug, profile, release]
|
||||
description: Mobile gateway setup code editor
|
||||
ui_surface: settings_page
|
||||
experimental_canvas:
|
||||
enabled: true
|
||||
release_tier: experimental
|
||||
@ -180,24 +162,6 @@ desktop:
|
||||
build_modes: [debug, profile, release]
|
||||
description: Desktop vault server settings
|
||||
ui_surface: settings_page
|
||||
gateway_self_hosted_base:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: [debug, profile, release]
|
||||
description: Desktop self-hosted gateway base controls
|
||||
ui_surface: settings_page
|
||||
gateway_advanced_custom_mode:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: [debug, profile, release]
|
||||
description: Desktop advanced gateway override controls
|
||||
ui_surface: settings_page
|
||||
gateway_setup_code:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: [debug, profile, release]
|
||||
description: Desktop gateway setup code editor
|
||||
ui_surface: settings_page
|
||||
experimental_canvas:
|
||||
enabled: true
|
||||
release_tier: experimental
|
||||
@ -287,24 +251,6 @@ web:
|
||||
build_modes: []
|
||||
description: Web vault server settings disabled
|
||||
ui_surface: settings_page
|
||||
gateway_self_hosted_base:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: []
|
||||
description: Web self-hosted gateway base controls disabled
|
||||
ui_surface: settings_page
|
||||
gateway_advanced_custom_mode:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: []
|
||||
description: Web advanced gateway override controls disabled
|
||||
ui_surface: settings_page
|
||||
gateway_setup_code:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: []
|
||||
description: Web gateway setup code editor disabled
|
||||
ui_surface: settings_page
|
||||
experimental_canvas:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
|
||||
@ -17,7 +17,6 @@ acpBridgeServerModeConfig:
|
||||
lastSyncAt: 0
|
||||
remoteServerSummary:
|
||||
endpoint: https://xworkmate-bridge.svc.plus
|
||||
hasAdvancedOverrides: false
|
||||
selfHosted:
|
||||
serverUrl: ''
|
||||
username: ''
|
||||
|
||||
@ -34,6 +34,7 @@ go test ./...
|
||||
## CI Coverage
|
||||
|
||||
- Pull requests in `xworkmate-app` use the `verify` stage as a static-analysis gate and always run `flutter analyze`.
|
||||
- Static analysis also runs `scripts/check-no-app-ffi.sh` so app packaging cannot reintroduce the retired Codex FFI copy/embed path.
|
||||
- Widget, integration, and Patrol suites are owned by their dedicated commands and release validation flows, not by the lightweight `verify` gate.
|
||||
- Pushes to `main`, version tags, and manual workflow runs publish build artifacts and update the GitHub Release entry for that release mode.
|
||||
- `xworkmate-bridge` Go tests run in the companion repository.
|
||||
|
||||
@ -206,9 +206,9 @@ flowchart LR
|
||||
|
||||
- `Directory.current.path`
|
||||
|
||||
关键位置:
|
||||
历史关键位置:
|
||||
|
||||
- [app_controller_desktop_single_agent.dart](/Users/shenlan/workspaces/cloud-neutral-toolkit/xworkmate/lib/app/app_controller_desktop_single_agent.dart:140)
|
||||
- 历史 Single Agent 桥接文件,已在 2026-05 清理中移除
|
||||
|
||||
这就是“任务线程没有有效目录时,命令最后跑到全局/容器 cwd”的直接原因。
|
||||
|
||||
@ -219,9 +219,9 @@ Single Agent 运行后可能返回:
|
||||
- `result.resolvedWorkingDirectory`
|
||||
- `result.resolvedWorkspaceRefKind`
|
||||
|
||||
关键位置:
|
||||
历史关键位置:
|
||||
|
||||
- [app_controller_desktop_single_agent.dart](/Users/shenlan/workspaces/cloud-neutral-toolkit/xworkmate/lib/app/app_controller_desktop_single_agent.dart:155)
|
||||
- 历史 Single Agent 桥接文件,已在 2026-05 清理中移除
|
||||
|
||||
当前逻辑中:
|
||||
|
||||
|
||||
@ -58,18 +58,18 @@ Last Updated: 2026-04-14
|
||||
|
||||
## Coverage Summary
|
||||
|
||||
当前生成清单覆盖 `130` 个源码文件、`614` 个公开符号。
|
||||
当前生成清单覆盖 `129` 个源码文件、`603` 个公开符号。
|
||||
|
||||
| Scope | Files | Public Symbols | Detailed Design Entries | Notes |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `lib/app` | 30 | 68 | 10 | 主写桌面编排入口、扩展、registry 与 shell |
|
||||
| `lib/runtime` | 67 | 377 | 18 | 主写 bridge contract、runtime client、controller、bootstrap |
|
||||
| `lib/models` | 1 | 34 | 13 | 主写 settings / execution / provider / snapshot 主模型 |
|
||||
| `lib/features/assistant` | 16 | 80 | 1 | 只展开页面入口与业务挂点 |
|
||||
| `lib/features/settings` | 4 | 4 | 1 | 只展开设置主入口 |
|
||||
| `lib/runtime` | 66 | 372 | 18 | 主写 bridge contract、runtime client、controller、bootstrap |
|
||||
| `lib/models` | 1 | 31 | 13 | 主写 settings / execution / provider / snapshot 主模型 |
|
||||
| `lib/features/assistant` | 16 | 79 | 1 | 只展开页面入口与业务挂点 |
|
||||
| `lib/features/settings` | 4 | 5 | 1 | 只展开设置主入口 |
|
||||
| `lib/features/mobile` | 6 | 19 | 1 | 只展开移动端 shell 主入口 |
|
||||
| `lib/theme` | 2 | 13 | 2 | 只展开工程上影响 API 的 theme/palette 入口 |
|
||||
| `rust/src` | 4 | 19 | 17 | 结构体与 FFI 函数全部展开 |
|
||||
| `rust/src` | 4 | 16 | 17 | 结构体与 FFI 函数全部展开 |
|
||||
|
||||
说明:
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -5,9 +5,9 @@
|
||||
> Scope: `lib/app`, `lib/runtime`, `lib/models`, `lib/features/**`, `lib/theme`, `rust/src`.
|
||||
> Excludes private `_` symbols and non-top-level Dart members.
|
||||
|
||||
- Generated at: `2026-04-14T08:20:04.438927+00:00`
|
||||
- Files scanned: `130`
|
||||
- Public symbols extracted: `614`
|
||||
- Generated at: `2026-05-13T08:37:25.180831+00:00`
|
||||
- Files scanned: `129`
|
||||
- Public symbols extracted: `603`
|
||||
|
||||
## Group Summary
|
||||
|
||||
@ -15,23 +15,23 @@
|
||||
| --- | ---: | ---: |
|
||||
| `lib/app` | 30 | 68 |
|
||||
| `lib/features` | 26 | 103 |
|
||||
| `lib/models` | 1 | 34 |
|
||||
| `lib/runtime` | 67 | 377 |
|
||||
| `lib/models` | 1 | 31 |
|
||||
| `lib/runtime` | 66 | 372 |
|
||||
| `lib/theme` | 2 | 13 |
|
||||
| `rust/src` | 4 | 19 |
|
||||
| `rust/src` | 4 | 16 |
|
||||
|
||||
## Coverage Scope Summary
|
||||
|
||||
| Scope | Files | Public Symbols |
|
||||
| --- | ---: | ---: |
|
||||
| `lib/app` | 30 | 68 |
|
||||
| `lib/runtime` | 67 | 377 |
|
||||
| `lib/models` | 1 | 34 |
|
||||
| `lib/features/assistant` | 16 | 80 |
|
||||
| `lib/features/settings` | 4 | 4 |
|
||||
| `lib/runtime` | 66 | 372 |
|
||||
| `lib/models` | 1 | 31 |
|
||||
| `lib/features/assistant` | 16 | 79 |
|
||||
| `lib/features/settings` | 4 | 5 |
|
||||
| `lib/features/mobile` | 6 | 19 |
|
||||
| `lib/theme` | 2 | 13 |
|
||||
| `rust/src` | 4 | 19 |
|
||||
| `rust/src` | 4 | 16 |
|
||||
|
||||
## lib/app
|
||||
|
||||
@ -77,9 +77,9 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 54 | `enum` | `CodexCooperationState` | `enum CodexCooperationState { notStarted, bridgeOnly, registered }` |
|
||||
| 56 | `class` | `SingleAgentSkillScanRootInternal` | `class SingleAgentSkillScanRootInternal {` |
|
||||
| 88 | `class` | `AppController` | `class AppController extends ChangeNotifier {` |
|
||||
| 57 | `enum` | `CodexCooperationState` | `enum CodexCooperationState { notStarted, bridgeOnly, registered }` |
|
||||
| 59 | `class` | `SingleAgentSkillScanRootInternal` | `class SingleAgentSkillScanRootInternal {` |
|
||||
| 91 | `class` | `AppController` | `class AppController extends ChangeNotifier {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_external_acp_routing.dart`
|
||||
|
||||
@ -97,7 +97,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 49 | `extension` | `AppControllerDesktopGateway` | `extension AppControllerDesktopGateway on AppController {` |
|
||||
| 48 | `extension` | `AppControllerDesktopGateway` | `extension AppControllerDesktopGateway on AppController {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_navigation.dart`
|
||||
|
||||
@ -106,24 +106,25 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 48 | `extension` | `AppControllerDesktopNavigation` | `extension AppControllerDesktopNavigation on AppController {` |
|
||||
| 47 | `extension` | `AppControllerDesktopNavigation` | `extension AppControllerDesktopNavigation on AppController {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_runtime_coordination_impl.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `9`
|
||||
- Public symbols: `10`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 48 | `top-level function` | `refreshAcpCapabilitiesRuntimeInternal` | `Future<void> refreshAcpCapabilitiesRuntimeInternal( AppController controller, { bool forceRefresh = false, bool persistMountTargets = false, }) async {` |
|
||||
| 90 | `top-level function` | `refreshSingleAgentCapabilitiesRuntimeInternal` | `Future<void> refreshSingleAgentCapabilitiesRuntimeInternal( AppController controller, { bool forceRefresh = false, }) async {` |
|
||||
| 158 | `top-level function` | `assistantWorkingDirectoryForSessionRuntimeInternal` | `String? assistantWorkingDirectoryForSessionRuntimeInternal( AppController controller, String sessionKey, ) {` |
|
||||
| 178 | `top-level function` | `resolveLocalAssistantWorkingDirectoryForSessionRuntimeInternal` | `String? resolveLocalAssistantWorkingDirectoryForSessionRuntimeInternal( AppController controller, String sessionKey, { bool requireLocalExistence = true, }) {` |
|
||||
| 206 | `top-level function` | `buildCodeAgentNodeStateRuntimeInternal` | `CodeAgentNodeState buildCodeAgentNodeStateRuntimeInternal( AppController controller, ) {` |
|
||||
| 220 | `top-level function` | `bridgeGatewayModeRuntimeInternal` | `GatewayMode bridgeGatewayModeRuntimeInternal(AppController controller) {` |
|
||||
| 230 | `top-level function` | `ensureCodexGatewayRegistrationRuntimeInternal` | `Future<void> ensureCodexGatewayRegistrationRuntimeInternal( AppController controller, ) async {` |
|
||||
| 298 | `top-level function` | `clearCodexGatewayRegistrationRuntimeInternal` | `void clearCodexGatewayRegistrationRuntimeInternal(AppController controller) {` |
|
||||
| 308 | `top-level function` | `recomputeTasksRuntimeInternal` | `void recomputeTasksRuntimeInternal(AppController controller) {` |
|
||||
| 98 | `top-level function` | `refreshSingleAgentCapabilitiesRuntimeInternal` | `Future<void> refreshSingleAgentCapabilitiesRuntimeInternal( AppController controller, { bool forceRefresh = false, }) async {` |
|
||||
| 170 | `top-level function` | `assistantWorkingDirectoryForSessionRuntimeInternal` | `String? assistantWorkingDirectoryForSessionRuntimeInternal( AppController controller, String sessionKey, ) {` |
|
||||
| 181 | `top-level function` | `assistantRemoteWorkingDirectoryHintForSessionRuntimeInternal` | `String? assistantRemoteWorkingDirectoryHintForSessionRuntimeInternal( AppController controller, String sessionKey, ) {` |
|
||||
| 200 | `top-level function` | `resolveLocalAssistantWorkingDirectoryForSessionRuntimeInternal` | `String? resolveLocalAssistantWorkingDirectoryForSessionRuntimeInternal( AppController controller, String sessionKey, { bool requireLocalExistence = true, }) {` |
|
||||
| 223 | `top-level function` | `buildCodeAgentNodeStateRuntimeInternal` | `CodeAgentNodeState buildCodeAgentNodeStateRuntimeInternal( AppController controller, { AssistantExecutionTarget? executionTarget, }) {` |
|
||||
| 239 | `top-level function` | `bridgeGatewayModeRuntimeInternal` | `GatewayMode bridgeGatewayModeRuntimeInternal(AppController controller) {` |
|
||||
| 249 | `top-level function` | `ensureCodexGatewayRegistrationRuntimeInternal` | `Future<void> ensureCodexGatewayRegistrationRuntimeInternal( AppController controller, ) async {` |
|
||||
| 317 | `top-level function` | `clearCodexGatewayRegistrationRuntimeInternal` | `void clearCodexGatewayRegistrationRuntimeInternal(AppController controller) {` |
|
||||
| 327 | `top-level function` | `recomputeTasksRuntimeInternal` | `void recomputeTasksRuntimeInternal(AppController controller) {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_runtime_exceptions.dart`
|
||||
|
||||
@ -142,7 +143,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 51 | `extension` | `AppControllerDesktopRuntimeHelpers` | `extension AppControllerDesktopRuntimeHelpers on AppController {` |
|
||||
| 53 | `extension` | `AppControllerDesktopRuntimeHelpers` | `extension AppControllerDesktopRuntimeHelpers on AppController {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_settings.dart`
|
||||
|
||||
@ -160,16 +161,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 49 | `extension` | `AppControllerDesktopSettingsRuntime` | `extension AppControllerDesktopSettingsRuntime on AppController {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_single_agent.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `1`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 3 | `extension` | `AppControllerDesktopSingleAgent` | `extension AppControllerDesktopSingleAgent on AppController {}` |
|
||||
| 50 | `extension` | `AppControllerDesktopSettingsRuntime` | `extension AppControllerDesktopSettingsRuntime on AppController {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_skill_permissions.dart`
|
||||
|
||||
@ -178,7 +170,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 49 | `extension` | `AppControllerDesktopSkillPermissions` | `extension AppControllerDesktopSkillPermissions on AppController {` |
|
||||
| 48 | `extension` | `AppControllerDesktopSkillPermissions` | `extension AppControllerDesktopSkillPermissions on AppController {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_thread_actions.dart`
|
||||
|
||||
@ -187,7 +179,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 50 | `extension` | `AppControllerDesktopThreadActions` | `extension AppControllerDesktopThreadActions on AppController {` |
|
||||
| 51 | `extension` | `AppControllerDesktopThreadActions` | `extension AppControllerDesktopThreadActions on AppController {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_thread_binding.dart`
|
||||
|
||||
@ -198,40 +190,40 @@ _No extracted public top-level symbols._
|
||||
| ---: | --- | --- | --- |
|
||||
| 47 | `class` | `DesktopThreadBindingSnapshotInternal` | `class DesktopThreadBindingSnapshotInternal {` |
|
||||
| 76 | `extension` | `AppControllerDesktopThreadBinding` | `extension AppControllerDesktopThreadBinding on AppController {` |
|
||||
| 294 | `top-level function` | `pickDraftThreadExecutionTargetInternal` | `AssistantExecutionTarget pickDraftThreadExecutionTargetInternal({ required AssistantExecutionTarget currentTarget, required Iterable<AssistantExecutionTarget> visibleTargets, bool? localWorkspaceAvailable, }) {` |
|
||||
| 337 | `top-level function` | `pickDraftThreadExecutionTargetInternal` | `AssistantExecutionTarget pickDraftThreadExecutionTargetInternal({ required AssistantExecutionTarget currentTarget, required Iterable<AssistantExecutionTarget> visibleTargets, bool? localWorkspaceAvailable, }) {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_thread_sessions.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `3`
|
||||
- Public symbols: `4`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 51 | `top-level function` | `resolveGatewayThreadConnectionStateInternal` | `AssistantThreadConnectionState resolveGatewayThreadConnectionStateInternal({ required AssistantExecutionTarget target, required bool bridgeReady, required String bridgeLabel, required AccountSyncState? accountSyncState, }) {` |
|
||||
| 99 | `extension` | `AppControllerDesktopThreadSessions` | `extension AppControllerDesktopThreadSessions on AppController {` |
|
||||
| 470 | `top-level function` | `resolveAssistantExecutionTargetFromRecordsForTest` | `AssistantExecutionTarget resolveAssistantExecutionTargetFromRecordsForTest( TaskThread? primaryRecord, { TaskThread? fallbackRecord, }) {` |
|
||||
| 55 | `top-level function` | `resolveGatewayThreadConnectionStateInternal` | `AssistantThreadConnectionState resolveGatewayThreadConnectionStateInternal({ required AssistantExecutionTarget target, required bool bridgeReady, required String bridgeLabel, required AccountSyncState? accountSyncState, required bool accountSignedIn, required bool bridgeConfigured, bool bridgeDiscoveryAttempted = false, String bridgeDiscoveryError = '', bool providerCatalogEmpty = false, }) {` |
|
||||
| 180 | `top-level function` | `bridgeCapabilityReadyForExecutionTargetInternal` | `bool bridgeCapabilityReadyForExecutionTargetInternal({ required AssistantExecutionTarget target, required bool bridgeConfigured, required List<SingleAgentProvider> providers, required List<AssistantExecutionTarget> availableTargets, }) {` |
|
||||
| 192 | `extension` | `AppControllerDesktopThreadSessions` | `extension AppControllerDesktopThreadSessions on AppController {` |
|
||||
| 655 | `top-level function` | `resolveAssistantExecutionTargetFromRecordForTest` | `AssistantExecutionTarget resolveAssistantExecutionTargetFromRecordForTest( TaskThread? record, { required AssistantExecutionTarget defaultExecutionTarget, }) {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_thread_sessions_collaboration_impl.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `14`
|
||||
- Public symbols: `13`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 50 | `top-level function` | `loadAiGatewayApiKeyThreadSessionInternal` | `Future<String> loadAiGatewayApiKeyThreadSessionInternal( AppController controller, ) async {` |
|
||||
| 56 | `top-level function` | `saveMultiAgentConfigThreadSessionInternal` | `Future<void> saveMultiAgentConfigThreadSessionInternal( AppController controller, MultiAgentConfig config, ) async {` |
|
||||
| 73 | `top-level function` | `refreshMultiAgentMountsThreadSessionInternal` | `Future<void> refreshMultiAgentMountsThreadSessionInternal( AppController controller, { bool sync = false, }) async {` |
|
||||
| 98 | `top-level function` | `runMultiAgentCollaborationThreadSessionInternal` | `Future<void> runMultiAgentCollaborationThreadSessionInternal( AppController controller, { required String rawPrompt, required String composedPrompt, required List<CollaborationAttachment> attachments, required List<String> selectedSkillLabels, }) async {` |
|
||||
| 269 | `top-level function` | `openOnlineWorkspaceThreadSessionInternal` | `Future<void> openOnlineWorkspaceThreadSessionInternal( AppController controller, ) async {` |
|
||||
| 290 | `top-level function` | `aiGatewayModelChoicesThreadSessionInternal` | `List<String> aiGatewayModelChoicesThreadSessionInternal( AppController controller, ) {` |
|
||||
| 296 | `top-level function` | `connectedGatewayModelChoicesThreadSessionInternal` | `List<String> connectedGatewayModelChoicesThreadSessionInternal( AppController controller, ) {` |
|
||||
| 308 | `top-level function` | `assistantModelChoicesThreadSessionInternal` | `List<String> assistantModelChoicesThreadSessionInternal( AppController controller, ) {` |
|
||||
| 317 | `top-level function` | `assistantModelChoicesForSessionThreadSessionInternal` | `List<String> assistantModelChoicesForSessionThreadSessionInternal( AppController controller, String sessionKey, ) {` |
|
||||
| 332 | `top-level function` | `resolvedDefaultModelThreadSessionInternal` | `String resolvedDefaultModelThreadSessionInternal(AppController controller) {` |
|
||||
| 354 | `top-level function` | `canQuickConnectGatewayThreadSessionInternal` | `bool canQuickConnectGatewayThreadSessionInternal(AppController controller) {` |
|
||||
| 374 | `top-level function` | `normalizeAssistantSessionKeyThreadInternal` | `String normalizeAssistantSessionKeyThreadInternal(String sessionKey) {` |
|
||||
| 379 | `top-level function` | `joinConnectionPartsThreadSessionInternal` | `String joinConnectionPartsThreadSessionInternal(List<String> parts) {` |
|
||||
| 387 | `top-level function` | `gatewayAddressLabelThreadSessionInternal` | `String gatewayAddressLabelThreadSessionInternal( GatewayConnectionProfile profile, ) {` |
|
||||
| 49 | `top-level function` | `loadAiGatewayApiKeyThreadSessionInternal` | `Future<String> loadAiGatewayApiKeyThreadSessionInternal( AppController controller, ) async {` |
|
||||
| 55 | `top-level function` | `saveMultiAgentConfigThreadSessionInternal` | `Future<void> saveMultiAgentConfigThreadSessionInternal( AppController controller, MultiAgentConfig config, ) async {` |
|
||||
| 72 | `top-level function` | `refreshMultiAgentMountsThreadSessionInternal` | `Future<void> refreshMultiAgentMountsThreadSessionInternal( AppController controller, { bool sync = false, }) async {` |
|
||||
| 97 | `top-level function` | `runMultiAgentCollaborationThreadSessionInternal` | `Future<void> runMultiAgentCollaborationThreadSessionInternal( AppController controller, { required String rawPrompt, required String composedPrompt, required List<CollaborationAttachment> attachments, required List<String> selectedSkillLabels, }) async {` |
|
||||
| 283 | `top-level function` | `openOnlineWorkspaceThreadSessionInternal` | `Future<void> openOnlineWorkspaceThreadSessionInternal( AppController controller, ) async {` |
|
||||
| 304 | `top-level function` | `aiGatewayModelChoicesThreadSessionInternal` | `List<String> aiGatewayModelChoicesThreadSessionInternal( AppController controller, ) {` |
|
||||
| 310 | `top-level function` | `connectedGatewayModelChoicesThreadSessionInternal` | `List<String> connectedGatewayModelChoicesThreadSessionInternal( AppController controller, ) {` |
|
||||
| 322 | `top-level function` | `assistantModelChoicesThreadSessionInternal` | `List<String> assistantModelChoicesThreadSessionInternal( AppController controller, ) {` |
|
||||
| 331 | `top-level function` | `assistantModelChoicesForSessionThreadSessionInternal` | `List<String> assistantModelChoicesForSessionThreadSessionInternal( AppController controller, String sessionKey, ) {` |
|
||||
| 346 | `top-level function` | `resolvedDefaultModelThreadSessionInternal` | `String resolvedDefaultModelThreadSessionInternal(AppController controller) {` |
|
||||
| 368 | `top-level function` | `canQuickConnectGatewayThreadSessionInternal` | `bool canQuickConnectGatewayThreadSessionInternal(AppController controller) {` |
|
||||
| 388 | `top-level function` | `joinConnectionPartsThreadSessionInternal` | `String joinConnectionPartsThreadSessionInternal(List<String> parts) {` |
|
||||
| 396 | `top-level function` | `gatewayAddressLabelThreadSessionInternal` | `String gatewayAddressLabelThreadSessionInternal( GatewayConnectionProfile profile, ) {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_thread_storage.dart`
|
||||
|
||||
@ -240,7 +232,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 48 | `extension` | `AppControllerDesktopThreadStorage` | `extension AppControllerDesktopThreadStorage on AppController {` |
|
||||
| 47 | `extension` | `AppControllerDesktopThreadStorage` | `extension AppControllerDesktopThreadStorage on AppController {` |
|
||||
|
||||
### `lib/app/app_controller_desktop_workspace_execution.dart`
|
||||
|
||||
@ -251,6 +243,15 @@ _No extracted public top-level symbols._
|
||||
| ---: | --- | --- | --- |
|
||||
| 48 | `extension` | `AppControllerDesktopWorkspaceExecution` | `extension AppControllerDesktopWorkspaceExecution on AppController {` |
|
||||
|
||||
### `lib/app/app_controller_openclaw_task_queue.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `1`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 9 | `class` | `OpenClawGatewayQueuedTurnInternal` | `class OpenClawGatewayQueuedTurnInternal {` |
|
||||
|
||||
### `lib/app/app_metadata.dart`
|
||||
|
||||
- Language: `dart`
|
||||
@ -313,21 +314,20 @@ _No extracted public top-level symbols._
|
||||
| 14 | `enum` | `UiFeatureBuildMode` | `enum UiFeatureBuildMode { debug, profile, release }` |
|
||||
| 16 | `top-level function` | `currentUiFeatureBuildMode` | `UiFeatureBuildMode currentUiFeatureBuildMode() {` |
|
||||
| 26 | `top-level function` | `resolveUiFeaturePlatformFromContext` | `UiFeaturePlatform resolveUiFeaturePlatformFromContext(BuildContext context) {` |
|
||||
| 62 | `class` | `UiFeatureFlag` | `class UiFeatureFlag {` |
|
||||
| 94 | `class` | `UiFeatureManifest` | `class UiFeatureManifest {` |
|
||||
| 341 | `class` | `UiFeatureAccess` | `class UiFeatureAccess {` |
|
||||
| 480 | `class` | `UiFeatureManifestLoader` | `class UiFeatureManifestLoader {` |
|
||||
| 57 | `class` | `UiFeatureFlag` | `class UiFeatureFlag {` |
|
||||
| 89 | `class` | `UiFeatureManifest` | `class UiFeatureManifest {` |
|
||||
| 336 | `class` | `UiFeatureAccess` | `class UiFeatureAccess {` |
|
||||
| 466 | `class` | `UiFeatureManifestLoader` | `class UiFeatureManifestLoader {` |
|
||||
|
||||
### `lib/app/workspace_navigation.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `3`
|
||||
- Public symbols: `2`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 8 | `top-level function` | `buildWorkspaceBreadcrumbs` | `List<AppBreadcrumbItem> buildWorkspaceBreadcrumbs({ required AppController controller, required String rootLabel, String? sectionLabel, String? detailLabel, VoidCallback? onRootTap, }) {` |
|
||||
| 32 | `top-level function` | `buildSettingsBreadcrumbs` | `List<AppBreadcrumbItem> buildSettingsBreadcrumbs( AppController controller, { required SettingsTab tab, SettingsDetailPage? detail, SettingsNavigationContext? navigationContext, }) {` |
|
||||
| 57 | `top-level function` | `openSettingsNavigationContext` | `void openSettingsNavigationContext( AppController controller, SettingsNavigationContext context, ) {` |
|
||||
| 32 | `top-level function` | `buildSettingsBreadcrumbs` | `List<AppBreadcrumbItem> buildSettingsBreadcrumbs( AppController controller, { required SettingsTab tab, }) {` |
|
||||
|
||||
### `lib/app/workspace_page_registry.dart`
|
||||
|
||||
@ -339,7 +339,7 @@ _No extracted public top-level symbols._
|
||||
| 8 | `enum` | `WorkspacePageSurface` | `enum WorkspacePageSurface { desktop, mobile }` |
|
||||
| 10 | `typedef` | `WorkspacePageBuilder` | `typedef WorkspacePageBuilder = Widget Function( AppController controller, ValueChanged<DetailPanelData> onOpenDetail, );` |
|
||||
| 16 | `class` | `WorkspacePageSpec` | `class WorkspacePageSpec {` |
|
||||
| 60 | `top-level function` | `buildWorkspacePage` | `Widget buildWorkspacePage({ required WorkspaceDestination destination, required AppController controller, required ValueChanged<DetailPanelData> onOpenDetail, required WorkspacePageSurface surface, }) {` |
|
||||
| 56 | `top-level function` | `buildWorkspacePage` | `Widget buildWorkspacePage({ required WorkspaceDestination destination, required AppController controller, required ValueChanged<DetailPanelData> onOpenDetail, required WorkspacePageSurface surface, }) {` |
|
||||
|
||||
## lib/features
|
||||
|
||||
@ -362,10 +362,10 @@ _No extracted public top-level symbols._
|
||||
| ---: | --- | --- | --- |
|
||||
| 40 | `class` | `AssistantTaskRailInternal` | `class AssistantTaskRailInternal extends StatefulWidget {` |
|
||||
| 73 | `class` | `AssistantTaskRailStateInternal` | `class AssistantTaskRailStateInternal extends State<AssistantTaskRailInternal> {` |
|
||||
| 282 | `top-level function` | `groupTasksForRailInternal` | `List<AssistantTaskGroupInternal> groupTasksForRailInternal( List<AssistantTaskEntryInternal> tasks, List<AssistantExecutionTarget> visibleExecutionTargets, ) {` |
|
||||
| 312 | `class` | `AssistantTaskTileInternal` | `class AssistantTaskTileInternal extends StatelessWidget {` |
|
||||
| 417 | `class` | `AssistantTaskGroupHeaderInternal` | `class AssistantTaskGroupHeaderInternal extends StatelessWidget {` |
|
||||
| 481 | `class` | `AssistantEmptyStateInternal` | `class AssistantEmptyStateInternal extends StatelessWidget {` |
|
||||
| 283 | `top-level function` | `groupTasksForRailInternal` | `List<AssistantTaskGroupInternal> groupTasksForRailInternal( List<AssistantTaskEntryInternal> tasks, List<AssistantExecutionTarget> visibleExecutionTargets, ) {` |
|
||||
| 313 | `class` | `AssistantTaskTileInternal` | `class AssistantTaskTileInternal extends StatelessWidget {` |
|
||||
| 462 | `class` | `AssistantTaskGroupHeaderInternal` | `class AssistantTaskGroupHeaderInternal extends StatelessWidget {` |
|
||||
| 526 | `class` | `AssistantEmptyStateInternal` | `class AssistantEmptyStateInternal extends StatelessWidget {` |
|
||||
|
||||
### `lib/features/assistant/assistant_page_components_core.dart`
|
||||
|
||||
@ -400,13 +400,12 @@ _No extracted public top-level symbols._
|
||||
### `lib/features/assistant/assistant_page_composer_skill_models.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `3`
|
||||
- Public symbols: `2`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 79 | `top-level function` | `skillOptionFromGatewayInternal` | `ComposerSkillOptionInternal skillOptionFromGatewayInternal( GatewaySkillSummary skill, ) {` |
|
||||
| 106 | `top-level function` | `skillOptionFromThreadSkillInternal` | `ComposerSkillOptionInternal skillOptionFromThreadSkillInternal( AssistantThreadSkillEntry skill, ) {` |
|
||||
| 122 | `class` | `ComposerSkillOptionInternal` | `class ComposerSkillOptionInternal {` |
|
||||
| 40 | `top-level function` | `skillOptionFromGatewayInternal` | `ComposerSkillOptionInternal skillOptionFromGatewayInternal( GatewaySkillSummary skill, ) {` |
|
||||
| 61 | `class` | `ComposerSkillOptionInternal` | `class ComposerSkillOptionInternal {` |
|
||||
|
||||
### `lib/features/assistant/assistant_page_composer_skill_picker.dart`
|
||||
|
||||
@ -455,13 +454,13 @@ _No extracted public top-level symbols._
|
||||
| 56 | `typedef` | `AssistantClipboardImageReader` | `typedef AssistantClipboardImageReader = Future<XFile?> Function();` |
|
||||
| 58 | `class` | `AssistantPage` | `class AssistantPage extends StatefulWidget {` |
|
||||
| 80 | `class` | `AssistantPageStateInternal` | `class AssistantPageStateInternal extends State<AssistantPage> {` |
|
||||
| 270 | `enum` | `AssistantSidePaneInternal` | `enum AssistantSidePaneInternal { tasks, navigation, focused }` |
|
||||
| 272 | `class` | `AssistantUnifiedSidePaneInternal` | `class AssistantUnifiedSidePaneInternal extends StatelessWidget {` |
|
||||
| 344 | `class` | `AssistantSideTabRailInternal` | `class AssistantSideTabRailInternal extends StatelessWidget {` |
|
||||
| 444 | `class` | `AssistantSideTabButtonInternal` | `class AssistantSideTabButtonInternal extends StatefulWidget {` |
|
||||
| 463 | `class` | `AssistantSideTabButtonStateInternal` | `class AssistantSideTabButtonStateInternal extends State<AssistantSideTabButtonInternal> {` |
|
||||
| 512 | `class` | `AssistantLowerPaneInternal` | `class AssistantLowerPaneInternal extends StatelessWidget {` |
|
||||
| 596 | `class` | `ConversationAreaInternal` | `class ConversationAreaInternal extends StatelessWidget {` |
|
||||
| 278 | `enum` | `AssistantSidePaneInternal` | `enum AssistantSidePaneInternal { tasks, navigation, focused }` |
|
||||
| 280 | `class` | `AssistantUnifiedSidePaneInternal` | `class AssistantUnifiedSidePaneInternal extends StatelessWidget {` |
|
||||
| 352 | `class` | `AssistantSideTabRailInternal` | `class AssistantSideTabRailInternal extends StatelessWidget {` |
|
||||
| 452 | `class` | `AssistantSideTabButtonInternal` | `class AssistantSideTabButtonInternal extends StatefulWidget {` |
|
||||
| 471 | `class` | `AssistantSideTabButtonStateInternal` | `class AssistantSideTabButtonStateInternal extends State<AssistantSideTabButtonInternal> {` |
|
||||
| 520 | `class` | `AssistantLowerPaneInternal` | `class AssistantLowerPaneInternal extends StatelessWidget {` |
|
||||
| 604 | `class` | `ConversationAreaInternal` | `class ConversationAreaInternal extends StatelessWidget {` |
|
||||
|
||||
### `lib/features/assistant/assistant_page_message_widgets.dart`
|
||||
|
||||
@ -499,7 +498,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 42 | `extension` | `AssistantPageStateClosureInternal` | `extension AssistantPageStateClosureInternal on AssistantPageStateInternal {` |
|
||||
| 44 | `extension` | `AssistantPageStateClosureInternal` | `extension AssistantPageStateClosureInternal on AssistantPageStateInternal {` |
|
||||
|
||||
### `lib/features/assistant/assistant_page_task_dialog_controls.dart`
|
||||
|
||||
@ -527,15 +526,15 @@ _No extracted public top-level symbols._
|
||||
| 202 | `class` | `MetaPillInternal` | `class MetaPillInternal extends StatelessWidget {` |
|
||||
| 256 | `top-level function` | `pillStyleForStatusInternal` | `PillStyleInternal pillStyleForStatusInternal( BuildContext context, String label, ) {` |
|
||||
| 282 | `top-level function` | `normalizedTaskStatusInternal` | `String normalizedTaskStatusInternal(String status) {` |
|
||||
| 294 | `top-level function` | `toolCallStatusLabelInternal` | `String toolCallStatusLabelInternal(String status) =>` |
|
||||
| 301 | `top-level function` | `assistantThinkingLabelInternal` | `String assistantThinkingLabelInternal(String level) => switch (level) {` |
|
||||
| 308 | `top-level function` | `sessionDisplayTitleInternal` | `String sessionDisplayTitleInternal(GatewaySessionSummary session) {` |
|
||||
| 320 | `top-level function` | `fallbackSessionTitleInternal` | `String fallbackSessionTitleInternal(String sessionKey) {` |
|
||||
| 335 | `top-level function` | `sessionPreviewInternal` | `String? sessionPreviewInternal(GatewaySessionSummary session) {` |
|
||||
| 347 | `top-level function` | `sessionStatusInternal` | `String sessionStatusInternal( GatewaySessionSummary session, { required bool sessionPending, }) {` |
|
||||
| 363 | `top-level function` | `sessionUpdatedAtLabelInternal` | `String sessionUpdatedAtLabelInternal(double? updatedAtMs) {` |
|
||||
| 382 | `top-level function` | `estimatedComposerWrapSectionHeightInternal` | `double estimatedComposerWrapSectionHeightInternal({ required int itemCount, required double availableWidth, required double averageChipWidth, }) {` |
|
||||
| 398 | `top-level function` | `sessionKeysMatchInternal` | `bool sessionKeysMatchInternal(String incoming, String current) {` |
|
||||
| 295 | `top-level function` | `toolCallStatusLabelInternal` | `String toolCallStatusLabelInternal(String status) =>` |
|
||||
| 303 | `top-level function` | `assistantThinkingLabelInternal` | `String assistantThinkingLabelInternal(String level) => switch (level) {` |
|
||||
| 310 | `top-level function` | `sessionDisplayTitleInternal` | `String sessionDisplayTitleInternal(GatewaySessionSummary session) {` |
|
||||
| 318 | `top-level function` | `fallbackSessionTitleInternal` | `String fallbackSessionTitleInternal(String sessionKey) {` |
|
||||
| 326 | `top-level function` | `sessionPreviewInternal` | `String? sessionPreviewInternal(GatewaySessionSummary session) {` |
|
||||
| 338 | `top-level function` | `sessionStatusInternal` | `String sessionStatusInternal( GatewaySessionSummary session, { required bool sessionPending, String lifecycleStatus = '', }) {` |
|
||||
| 359 | `top-level function` | `sessionUpdatedAtLabelInternal` | `String sessionUpdatedAtLabelInternal(double? updatedAtMs) {` |
|
||||
| 378 | `top-level function` | `estimatedComposerWrapSectionHeightInternal` | `double estimatedComposerWrapSectionHeightInternal({ required int itemCount, required double availableWidth, required double averageChipWidth, }) {` |
|
||||
| 394 | `top-level function` | `sessionKeysMatchInternal` | `bool sessionKeysMatchInternal(String incoming, String current) {` |
|
||||
|
||||
### `lib/features/assistant/assistant_page_tooltip_labels.dart`
|
||||
|
||||
@ -647,63 +646,61 @@ _No extracted public top-level symbols._
|
||||
### `lib/features/settings/settings_page_core.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `1`
|
||||
- Public symbols: `2`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 19 | `class` | `SettingsPage` | `class SettingsPage extends StatefulWidget {` |
|
||||
| 19 | `top-level function` | `loadBridgeMetadataForSettingsAbout` | `Future<Map<String, dynamic>> loadBridgeMetadataForSettingsAbout({ required Uri bridgeEndpoint, required Future<String?> Function(Uri endpoint) authorizationResolver, HttpClient Function()? clientFactory, }) async {` |
|
||||
| 109 | `class` | `SettingsPage` | `class SettingsPage extends StatefulWidget {` |
|
||||
|
||||
## lib/models
|
||||
|
||||
- Files: `1`
|
||||
- Public symbols: `34`
|
||||
- Public symbols: `31`
|
||||
|
||||
### `lib/models/app_models.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `34`
|
||||
- Public symbols: `31`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 5 | `enum` | `WorkspaceDestination` | `enum WorkspaceDestination {` |
|
||||
| 10 | `extension` | `WorkspaceDestinationCopy` | `extension WorkspaceDestinationCopy on WorkspaceDestination {` |
|
||||
| 45 | `enum` | `AssistantFocusEntry` | `enum AssistantFocusEntry {` |
|
||||
| 51 | `extension` | `AssistantFocusEntryCopy` | `extension AssistantFocusEntryCopy on AssistantFocusEntry {` |
|
||||
| 124 | `top-level function` | `normalizeAssistantNavigationDestinations` | `List<AssistantFocusEntry> normalizeAssistantNavigationDestinations( Iterable<AssistantFocusEntry> destinations, ) {` |
|
||||
| 139 | `enum` | `StatusTone` | `enum StatusTone { neutral, accent, success, warning, danger }` |
|
||||
| 141 | `class` | `StatusInfo` | `class StatusInfo {` |
|
||||
| 148 | `enum` | `AppSidebarState` | `enum AppSidebarState { expanded, collapsed, hidden }` |
|
||||
| 150 | `enum` | `AssistantMode` | `enum AssistantMode { code, office }` |
|
||||
| 152 | `extension` | `AssistantModeCopy` | `extension AssistantModeCopy on AssistantMode {` |
|
||||
| 159 | `enum` | `SettingsTab` | `enum SettingsTab { gateway }` |
|
||||
| 161 | `extension` | `SettingsTabCopy` | `extension SettingsTabCopy on SettingsTab {` |
|
||||
| 167 | `enum` | `SettingsDetailPage` | `enum SettingsDetailPage { gatewayConnection }` |
|
||||
| 169 | `extension` | `SettingsDetailPageCopy` | `extension SettingsDetailPageCopy on SettingsDetailPage {` |
|
||||
| 183 | `class` | `SettingsNavigationContext` | `class SettingsNavigationContext {` |
|
||||
| 201 | `class` | `QuickAction` | `class QuickAction {` |
|
||||
| 213 | `class` | `RecentSession` | `class RecentSession {` |
|
||||
| 225 | `class` | `MetricSummary` | `class MetricSummary {` |
|
||||
| 241 | `class` | `TaskSummary` | `class TaskSummary {` |
|
||||
| 259 | `class` | `ModuleSummary` | `class ModuleSummary {` |
|
||||
| 275 | `class` | `NodeSummary` | `class NodeSummary {` |
|
||||
| 293 | `class` | `AgentSummary` | `class AgentSummary {` |
|
||||
| 309 | `class` | `SkillSummary` | `class SkillSummary {` |
|
||||
| 327 | `class` | `ConnectorSummary` | `class ConnectorSummary {` |
|
||||
| 343 | `class` | `SecretSummary` | `class SecretSummary {` |
|
||||
| 359 | `class` | `SecretReference` | `class SecretReference {` |
|
||||
| 375 | `class` | `ProviderSummary` | `class ProviderSummary {` |
|
||||
| 389 | `class` | `AuditSummary` | `class AuditSummary {` |
|
||||
| 407 | `class` | `SettingSummary` | `class SettingSummary {` |
|
||||
| 419 | `class` | `WorkspaceProfile` | `class WorkspaceProfile {` |
|
||||
| 433 | `class` | `DetailPanelData` | `class DetailPanelData {` |
|
||||
| 455 | `class` | `DetailSection` | `class DetailSection {` |
|
||||
| 462 | `class` | `DetailItem` | `class DetailItem {` |
|
||||
| 469 | `class` | `CommandEntry` | `class CommandEntry {` |
|
||||
| 5 | `enum` | `WorkspaceDestination` | `enum WorkspaceDestination { assistant, settings }` |
|
||||
| 7 | `extension` | `WorkspaceDestinationCopy` | `extension WorkspaceDestinationCopy on WorkspaceDestination {` |
|
||||
| 42 | `enum` | `AssistantFocusEntry` | `enum AssistantFocusEntry { settings, language, theme }` |
|
||||
| 44 | `extension` | `AssistantFocusEntryCopy` | `extension AssistantFocusEntryCopy on AssistantFocusEntry {` |
|
||||
| 117 | `top-level function` | `normalizeAssistantNavigationDestinations` | `List<AssistantFocusEntry> normalizeAssistantNavigationDestinations( Iterable<AssistantFocusEntry> destinations, ) {` |
|
||||
| 132 | `enum` | `StatusTone` | `enum StatusTone { neutral, accent, success, warning, danger }` |
|
||||
| 134 | `class` | `StatusInfo` | `class StatusInfo {` |
|
||||
| 141 | `enum` | `AppSidebarState` | `enum AppSidebarState { expanded, collapsed, hidden }` |
|
||||
| 143 | `enum` | `AssistantMode` | `enum AssistantMode { code, office }` |
|
||||
| 145 | `extension` | `AssistantModeCopy` | `extension AssistantModeCopy on AssistantMode {` |
|
||||
| 152 | `enum` | `SettingsTab` | `enum SettingsTab { gateway }` |
|
||||
| 154 | `extension` | `SettingsTabCopy` | `extension SettingsTabCopy on SettingsTab {` |
|
||||
| 160 | `class` | `QuickAction` | `class QuickAction {` |
|
||||
| 172 | `class` | `RecentSession` | `class RecentSession {` |
|
||||
| 184 | `class` | `MetricSummary` | `class MetricSummary {` |
|
||||
| 200 | `class` | `TaskSummary` | `class TaskSummary {` |
|
||||
| 218 | `class` | `ModuleSummary` | `class ModuleSummary {` |
|
||||
| 234 | `class` | `NodeSummary` | `class NodeSummary {` |
|
||||
| 252 | `class` | `AgentSummary` | `class AgentSummary {` |
|
||||
| 268 | `class` | `SkillSummary` | `class SkillSummary {` |
|
||||
| 286 | `class` | `ConnectorSummary` | `class ConnectorSummary {` |
|
||||
| 302 | `class` | `SecretSummary` | `class SecretSummary {` |
|
||||
| 318 | `class` | `SecretReference` | `class SecretReference {` |
|
||||
| 334 | `class` | `ProviderSummary` | `class ProviderSummary {` |
|
||||
| 348 | `class` | `AuditSummary` | `class AuditSummary {` |
|
||||
| 366 | `class` | `SettingSummary` | `class SettingSummary {` |
|
||||
| 378 | `class` | `WorkspaceProfile` | `class WorkspaceProfile {` |
|
||||
| 392 | `class` | `DetailPanelData` | `class DetailPanelData {` |
|
||||
| 414 | `class` | `DetailSection` | `class DetailSection {` |
|
||||
| 421 | `class` | `DetailItem` | `class DetailItem {` |
|
||||
| 428 | `class` | `CommandEntry` | `class CommandEntry {` |
|
||||
|
||||
## lib/runtime
|
||||
|
||||
- Files: `67`
|
||||
- Public symbols: `377`
|
||||
- Files: `66`
|
||||
- Public symbols: `372`
|
||||
|
||||
### `lib/runtime/account_runtime_client.dart`
|
||||
|
||||
@ -723,8 +720,8 @@ _No extracted public top-level symbols._
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 1 | `class` | `AcpEndpointPaths` | `class AcpEndpointPaths {` |
|
||||
| 51 | `top-level function` | `resolveAcpWebSocketEndpoint` | `Uri? resolveAcpWebSocketEndpoint(Uri? endpoint) {` |
|
||||
| 69 | `top-level function` | `resolveAcpHttpRpcEndpoint` | `Uri? resolveAcpHttpRpcEndpoint(Uri? endpoint) {` |
|
||||
| 72 | `top-level function` | `resolveAcpWebSocketEndpoint` | `Uri? resolveAcpWebSocketEndpoint(Uri? endpoint) {` |
|
||||
| 93 | `top-level function` | `resolveAcpHttpRpcEndpoint` | `Uri? resolveAcpHttpRpcEndpoint(Uri? endpoint) {` |
|
||||
|
||||
### `lib/runtime/agent_registry.dart`
|
||||
|
||||
@ -740,26 +737,14 @@ _No extracted public top-level symbols._
|
||||
| 153 | `class` | `AgentException` | `class AgentException implements Exception {` |
|
||||
| 165 | `class` | `AgentRegistry` | `class AgentRegistry with ChangeNotifier {` |
|
||||
|
||||
### `lib/runtime/aris_bundle.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `3`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 9 | `class` | `ArisBundleManifest` | `class ArisBundleManifest {` |
|
||||
| 69 | `class` | `ResolvedArisBundle` | `class ResolvedArisBundle {` |
|
||||
| 98 | `class` | `ArisBundleRepository` | `class ArisBundleRepository {` |
|
||||
|
||||
### `lib/runtime/aris_llm_chat_client.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `2`
|
||||
- Public symbols: `1`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 8 | `typedef` | `ArisProcessStarter` | `typedef ArisProcessStarter = Future<Process> Function( String executable, List<String> arguments, { Map<String, String>? environment, String? workingDirectory, });` |
|
||||
| 16 | `class` | `ArisLlmChatClient` | `class ArisLlmChatClient {` |
|
||||
| 3 | `class` | `ArisLlmChatClient` | `class ArisLlmChatClient {` |
|
||||
|
||||
### `lib/runtime/assistant_artifacts.dart`
|
||||
|
||||
@ -807,22 +792,22 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 12 | `enum` | `CodexSandboxMode` | `enum CodexSandboxMode {` |
|
||||
| 22 | `enum` | `CodexApprovalPolicy` | `enum CodexApprovalPolicy {` |
|
||||
| 32 | `enum` | `CodexAuthMode` | `enum CodexAuthMode {` |
|
||||
| 42 | `class` | `CodexThread` | `class CodexThread {` |
|
||||
| 75 | `class` | `CodexTurn` | `class CodexTurn {` |
|
||||
| 106 | `class` | `CodexAccount` | `class CodexAccount {` |
|
||||
| 137 | `class` | `CodexRateLimit` | `class CodexRateLimit {` |
|
||||
| 160 | `class` | `CodexUserInput` | `class CodexUserInput {` |
|
||||
| 180 | `class` | `CodexAttachment` | `class CodexAttachment {` |
|
||||
| 198 | `class` | `CodexLogEvent` | `class CodexLogEvent extends CodexEvent {` |
|
||||
| 211 | `class` | `CodexNotificationEvent` | `class CodexNotificationEvent extends CodexEvent {` |
|
||||
| 219 | `class` | `CodexTurnEvent` | `class CodexTurnEvent extends CodexEvent {` |
|
||||
| 253 | `class` | `CodexRpcError` | `class CodexRpcError implements Exception {` |
|
||||
| 273 | `enum` | `CodexConnectionState` | `enum CodexConnectionState {` |
|
||||
| 283 | `class` | `CodexRuntime` | `class CodexRuntime extends ChangeNotifier {` |
|
||||
| 901 | `class` | `CodexLaunchConfiguration` | `class CodexLaunchConfiguration {` |
|
||||
| 10 | `enum` | `CodexSandboxMode` | `enum CodexSandboxMode {` |
|
||||
| 20 | `enum` | `CodexApprovalPolicy` | `enum CodexApprovalPolicy {` |
|
||||
| 30 | `enum` | `CodexAuthMode` | `enum CodexAuthMode {` |
|
||||
| 40 | `class` | `CodexThread` | `class CodexThread {` |
|
||||
| 73 | `class` | `CodexTurn` | `class CodexTurn {` |
|
||||
| 104 | `class` | `CodexAccount` | `class CodexAccount {` |
|
||||
| 135 | `class` | `CodexRateLimit` | `class CodexRateLimit {` |
|
||||
| 158 | `class` | `CodexUserInput` | `class CodexUserInput {` |
|
||||
| 178 | `class` | `CodexAttachment` | `class CodexAttachment {` |
|
||||
| 196 | `class` | `CodexLogEvent` | `class CodexLogEvent extends CodexEvent {` |
|
||||
| 209 | `class` | `CodexNotificationEvent` | `class CodexNotificationEvent extends CodexEvent {` |
|
||||
| 217 | `class` | `CodexTurnEvent` | `class CodexTurnEvent extends CodexEvent {` |
|
||||
| 251 | `class` | `CodexRpcError` | `class CodexRpcError implements Exception {` |
|
||||
| 271 | `enum` | `CodexConnectionState` | `enum CodexConnectionState {` |
|
||||
| 281 | `class` | `CodexRuntime` | `class CodexRuntime extends ChangeNotifier {` |
|
||||
| 629 | `class` | `CodexLaunchConfiguration` | `class CodexLaunchConfiguration {` |
|
||||
|
||||
### `lib/runtime/desktop_platform_service.dart`
|
||||
|
||||
@ -861,8 +846,8 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 4 | `top-level function` | `shouldBlockEmbeddedAgentLaunch` | `bool shouldBlockEmbeddedAgentLaunch({ required bool isAppleHost, bool? enabled, }) {` |
|
||||
| 14 | `top-level function` | `shouldBlockGoCoreLaunch` | `bool shouldBlockGoCoreLaunch( GoCoreLaunch _, { required bool isAppleHost, bool? enabled, }) {` |
|
||||
| 6 | `top-level function` | `shouldBlockEmbeddedAgentLaunch` | `bool shouldBlockEmbeddedAgentLaunch({ required bool isAppleHost, bool? enabled, }) {` |
|
||||
| 19 | `top-level function` | `shouldBlockGoCoreLaunch` | `bool shouldBlockGoCoreLaunch({ required bool isAppleHost, bool? enabled, }) {` |
|
||||
|
||||
### `lib/runtime/external_code_agent_acp_desktop_transport.dart`
|
||||
|
||||
@ -871,7 +856,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 9 | `class` | `ExternalCodeAgentAcpDesktopTransport` | `class ExternalCodeAgentAcpDesktopTransport implements ExternalCodeAgentAcpTransport {` |
|
||||
| 10 | `class` | `ExternalCodeAgentAcpDesktopTransport` | `class ExternalCodeAgentAcpDesktopTransport implements ExternalCodeAgentAcpTransport {` |
|
||||
|
||||
### `lib/runtime/file_store_support.dart`
|
||||
|
||||
@ -888,27 +873,29 @@ _No extracted public top-level symbols._
|
||||
| 75 | `class` | `PersistentWriteFailures` | `class PersistentWriteFailures {` |
|
||||
| 92 | `class` | `StoreLayout` | `class StoreLayout {` |
|
||||
| 122 | `class` | `StoreLayoutResolver` | `class StoreLayoutResolver {` |
|
||||
| 210 | `top-level function` | `normalizeStoreDirectoryPath` | `String normalizeStoreDirectoryPath(String path) {` |
|
||||
| 227 | `top-level function` | `ensureDirectory` | `Future<Directory> ensureDirectory(String path) async {` |
|
||||
| 235 | `top-level function` | `ensureOwnerOnlyDirectory` | `Future<void> ensureOwnerOnlyDirectory(Directory directory) async {` |
|
||||
| 242 | `top-level function` | `ensureOwnerOnlyFile` | `Future<void> ensureOwnerOnlyFile(File file) async {` |
|
||||
| 249 | `top-level function` | `encodeStableFileKey` | `String encodeStableFileKey(String key) {` |
|
||||
| 253 | `top-level function` | `atomicWriteString` | `Future<void> atomicWriteString( File file, String contents, { bool ownerOnly = false, }) async {` |
|
||||
| 275 | `top-level function` | `deleteIfExists` | `Future<void> deleteIfExists(File file) async {` |
|
||||
| 281 | `top-level function` | `decodeYamlDocument` | `Object? decodeYamlDocument(String raw) {` |
|
||||
| 306 | `top-level function` | `encodeYamlDocument` | `String encodeYamlDocument(Object? value) {` |
|
||||
| 220 | `top-level function` | `normalizeStoreDirectoryPath` | `String normalizeStoreDirectoryPath(String path) {` |
|
||||
| 237 | `top-level function` | `ensureDirectory` | `Future<Directory> ensureDirectory(String path) async {` |
|
||||
| 245 | `top-level function` | `ensureOwnerOnlyDirectory` | `Future<void> ensureOwnerOnlyDirectory(Directory directory) async {` |
|
||||
| 252 | `top-level function` | `ensureOwnerOnlyFile` | `Future<void> ensureOwnerOnlyFile(File file) async {` |
|
||||
| 259 | `top-level function` | `encodeStableFileKey` | `String encodeStableFileKey(String key) {` |
|
||||
| 263 | `top-level function` | `atomicWriteString` | `Future<void> atomicWriteString( File file, String contents, { bool ownerOnly = false, }) async {` |
|
||||
| 285 | `top-level function` | `deleteIfExists` | `Future<void> deleteIfExists(File file) async {` |
|
||||
| 291 | `top-level function` | `decodeYamlDocument` | `Object? decodeYamlDocument(String raw) {` |
|
||||
| 316 | `top-level function` | `encodeYamlDocument` | `String encodeYamlDocument(Object? value) {` |
|
||||
|
||||
### `lib/runtime/gateway_acp_client.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `4`
|
||||
- Public symbols: `6`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 8 | `class` | `GatewayAcpException` | `class GatewayAcpException implements Exception {` |
|
||||
| 19 | `class` | `GatewayAcpCapabilities` | `class GatewayAcpCapabilities {` |
|
||||
| 70 | `class` | `GatewayAcpMultiAgentRequest` | `class GatewayAcpMultiAgentRequest {` |
|
||||
| 90 | `class` | `GatewayAcpClient` | `class GatewayAcpClient {` |
|
||||
| 16 | `class` | `GatewayAcpException` | `class GatewayAcpException implements Exception {` |
|
||||
| 33 | `class` | `GatewayAcpCapabilities` | `class GatewayAcpCapabilities {` |
|
||||
| 91 | `class` | `GatewayAcpMultiAgentRequest` | `class GatewayAcpMultiAgentRequest {` |
|
||||
| 111 | `class` | `GatewayAcpClient` | `class GatewayAcpClient {` |
|
||||
| 1392 | `top-level function` | `gatewayAcpHttpResponseTimeoutFor` | `Duration gatewayAcpHttpResponseTimeoutFor( Uri endpoint, String method, [ Map<String, dynamic> params = const <String, dynamic>{}, ]) {` |
|
||||
| 1412 | `top-level function` | `gatewayAcpTaskRuntimeBudgetMinutesForParams` | `int gatewayAcpTaskRuntimeBudgetMinutesForParams(Map<String, dynamic> params) {` |
|
||||
|
||||
### `lib/runtime/gateway_runtime.dart`
|
||||
|
||||
@ -933,7 +920,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 24 | `class` | `GatewayRuntime` | `class GatewayRuntime extends ChangeNotifier with GatewayRuntimeHelpersInternal {` |
|
||||
| 25 | `class` | `GatewayRuntime` | `class GatewayRuntime extends ChangeNotifier with GatewayRuntimeHelpersInternal {` |
|
||||
|
||||
### `lib/runtime/gateway_runtime_errors.dart`
|
||||
|
||||
@ -962,21 +949,21 @@ _No extracted public top-level symbols._
|
||||
| ---: | --- | --- | --- |
|
||||
| 21 | `top-level function` | `formatGatewayConnectAuthSummary` | `String formatGatewayConnectAuthSummary({ required String mode, required List<String> fields, required List<String> sources, }) {` |
|
||||
| 31 | `mixin` | `GatewayRuntimeHelpersInternal` | `mixin GatewayRuntimeHelpersInternal on ChangeNotifier {` |
|
||||
| 554 | `class` | `GatewaySetupPayload` | `class GatewaySetupPayload {` |
|
||||
| 570 | `top-level function` | `decodeGatewaySetupCode` | `GatewaySetupPayload? decodeGatewaySetupCode(String rawInput) {` |
|
||||
| 590 | `top-level function` | `decodeSetupPayloadJsonInternal` | `GatewaySetupPayload? decodeSetupPayloadJsonInternal(String raw) {` |
|
||||
| 615 | `top-level function` | `resolveSetupCodeCandidateInternal` | `String resolveSetupCodeCandidateInternal(String raw) {` |
|
||||
| 650 | `top-level function` | `composeManualUrlInternal` | `String? composeManualUrlInternal(String? host, int? port, bool? tls) {` |
|
||||
| 660 | `top-level function` | `asMap` | `Map<String, dynamic> asMap(Object? value) {` |
|
||||
| 670 | `top-level function` | `asList` | `List<dynamic> asList(Object? value) {` |
|
||||
| 680 | `top-level function` | `stringValue` | `String? stringValue(Object? value) {` |
|
||||
| 688 | `top-level function` | `boolValue` | `bool? boolValue(Object? value) {` |
|
||||
| 703 | `top-level function` | `intValue` | `int? intValue(Object? value) {` |
|
||||
| 716 | `top-level function` | `doubleValue` | `double? doubleValue(Object? value) {` |
|
||||
| 729 | `top-level function` | `stringList` | `List<String> stringList(Object? value) {` |
|
||||
| 735 | `top-level function` | `extractMessageText` | `String extractMessageText(Map<String, dynamic> message) {` |
|
||||
| 756 | `top-level function` | `randomIdInternal` | `String randomIdInternal() {` |
|
||||
| 766 | `class` | `RpcResponseInternal` | `class RpcResponseInternal {` |
|
||||
| 561 | `class` | `GatewaySetupPayload` | `class GatewaySetupPayload {` |
|
||||
| 577 | `top-level function` | `decodeGatewaySetupCode` | `GatewaySetupPayload? decodeGatewaySetupCode(String rawInput) {` |
|
||||
| 597 | `top-level function` | `decodeSetupPayloadJsonInternal` | `GatewaySetupPayload? decodeSetupPayloadJsonInternal(String raw) {` |
|
||||
| 622 | `top-level function` | `resolveSetupCodeCandidateInternal` | `String resolveSetupCodeCandidateInternal(String raw) {` |
|
||||
| 657 | `top-level function` | `composeManualUrlInternal` | `String? composeManualUrlInternal(String? host, int? port, bool? tls) {` |
|
||||
| 667 | `top-level function` | `asMap` | `Map<String, dynamic> asMap(Object? value) {` |
|
||||
| 677 | `top-level function` | `asList` | `List<dynamic> asList(Object? value) {` |
|
||||
| 687 | `top-level function` | `stringValue` | `String? stringValue(Object? value) {` |
|
||||
| 695 | `top-level function` | `boolValue` | `bool? boolValue(Object? value) {` |
|
||||
| 710 | `top-level function` | `intValue` | `int? intValue(Object? value) {` |
|
||||
| 723 | `top-level function` | `doubleValue` | `double? doubleValue(Object? value) {` |
|
||||
| 736 | `top-level function` | `stringList` | `List<String> stringList(Object? value) {` |
|
||||
| 742 | `top-level function` | `extractMessageText` | `String extractMessageText(Map<String, dynamic> message) {` |
|
||||
| 763 | `top-level function` | `randomIdInternal` | `String randomIdInternal() {` |
|
||||
| 773 | `class` | `RpcResponseInternal` | `class RpcResponseInternal {` |
|
||||
|
||||
### `lib/runtime/gateway_runtime_protocol.dart`
|
||||
|
||||
@ -1007,10 +994,10 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 3 | `enum` | `GoCoreLaunchSource` | `enum GoCoreLaunchSource { buildArtifact }` |
|
||||
| 5 | `class` | `GoCoreLaunch` | `class GoCoreLaunch {` |
|
||||
| 19 | `typedef` | `GoCoreBinaryExistsResolver` | `typedef GoCoreBinaryExistsResolver = Future<bool> Function(String command);` |
|
||||
| 21 | `class` | `GoCoreLocator` | `class GoCoreLocator {` |
|
||||
| 4 | `enum` | `GoCoreLaunchSource` | `enum GoCoreLaunchSource { buildArtifact }` |
|
||||
| 7 | `class` | `GoCoreLaunch` | `class GoCoreLaunch {` |
|
||||
| 21 | `typedef` | `GoCoreBinaryExistsResolver` | `typedef GoCoreBinaryExistsResolver = Future<bool> Function(String command);` |
|
||||
| 24 | `class` | `GoCoreLocator` | `class GoCoreLocator {` |
|
||||
|
||||
### `lib/runtime/go_multi_agent_mount_desktop_client.dart`
|
||||
|
||||
@ -1046,16 +1033,16 @@ _No extracted public top-level symbols._
|
||||
| 107 | `class` | `ExternalCodeAgentAcpRoutingConfig` | `class ExternalCodeAgentAcpRoutingConfig {` |
|
||||
| 167 | `class` | `ExternalCodeAgentAcpSkillInstallApproval` | `class ExternalCodeAgentAcpSkillInstallApproval {` |
|
||||
| 187 | `class` | `GoTaskServiceRequest` | `class GoTaskServiceRequest {` |
|
||||
| 357 | `class` | `GoTaskServiceUpdate` | `class GoTaskServiceUpdate {` |
|
||||
| 386 | `class` | `GoTaskServiceArtifact` | `class GoTaskServiceArtifact {` |
|
||||
| 433 | `class` | `GoTaskServiceResult` | `class GoTaskServiceResult {` |
|
||||
| 540 | `top-level function` | `goTaskServiceGatewayEntryState` | `String? goTaskServiceGatewayEntryState({ required AssistantExecutionTarget requestedTarget, required GoTaskServiceResult result, }) {` |
|
||||
| 575 | `abstract interface` | `ExternalCodeAgentAcpTransport` | `abstract class ExternalCodeAgentAcpTransport {` |
|
||||
| 607 | `abstract interface` | `GoTaskServiceClient` | `abstract class GoTaskServiceClient {` |
|
||||
| 641 | `top-level function` | `goTaskServiceUpdateFromAcpNotification` | `GoTaskServiceUpdate? goTaskServiceUpdateFromAcpNotification( Map<String, dynamic> notification, ) {` |
|
||||
| 682 | `top-level function` | `goTaskServiceResultFromAcpResponse` | `GoTaskServiceResult goTaskServiceResultFromAcpResponse( Map<String, dynamic> response, { required GoTaskServiceRoute route, String streamedText = '', String? completedMessage, }) {` |
|
||||
| 743 | `top-level function` | `mergeGoTaskServiceResponseResult` | `Map<String, dynamic> mergeGoTaskServiceResponseResult( Map<String, dynamic> response, Map<String, dynamic> overlay, ) {` |
|
||||
| 767 | `top-level function` | `goTaskServiceBase64Size` | `int goTaskServiceBase64Size(String base64) {` |
|
||||
| 359 | `class` | `GoTaskServiceUpdate` | `class GoTaskServiceUpdate {` |
|
||||
| 388 | `class` | `GoTaskServiceArtifact` | `class GoTaskServiceArtifact {` |
|
||||
| 443 | `class` | `GoTaskServiceResult` | `class GoTaskServiceResult {` |
|
||||
| 577 | `top-level function` | `goTaskServiceGatewayEntryState` | `String? goTaskServiceGatewayEntryState({ required AssistantExecutionTarget requestedTarget, required GoTaskServiceResult result, }) {` |
|
||||
| 612 | `abstract interface` | `ExternalCodeAgentAcpTransport` | `abstract class ExternalCodeAgentAcpTransport {` |
|
||||
| 644 | `abstract interface` | `GoTaskServiceClient` | `abstract class GoTaskServiceClient {` |
|
||||
| 678 | `top-level function` | `goTaskServiceUpdateFromAcpNotification` | `GoTaskServiceUpdate? goTaskServiceUpdateFromAcpNotification( Map<String, dynamic> notification, ) {` |
|
||||
| 719 | `top-level function` | `goTaskServiceResultFromAcpResponse` | `GoTaskServiceResult goTaskServiceResultFromAcpResponse( Map<String, dynamic> response, { required GoTaskServiceRoute route, String streamedText = '', String? completedMessage, }) {` |
|
||||
| 913 | `top-level function` | `mergeGoTaskServiceResponseResult` | `Map<String, dynamic> mergeGoTaskServiceResponseResult( Map<String, dynamic> response, Map<String, dynamic> overlay, ) {` |
|
||||
| 937 | `top-level function` | `goTaskServiceBase64Size` | `int goTaskServiceBase64Size(String base64) {` |
|
||||
|
||||
### `lib/runtime/go_task_service_desktop_service.dart`
|
||||
|
||||
@ -1086,9 +1073,9 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 6 | `abstract interface` | `FrameworkPreset` | `abstract class FrameworkPreset {` |
|
||||
| 19 | `class` | `NativeFrameworkPreset` | `class NativeFrameworkPreset extends FrameworkPreset {` |
|
||||
| 48 | `class` | `ArisFrameworkPreset` | `class ArisFrameworkPreset extends FrameworkPreset {` |
|
||||
| 3 | `abstract interface` | `FrameworkPreset` | `abstract class FrameworkPreset {` |
|
||||
| 16 | `class` | `NativeFrameworkPreset` | `class NativeFrameworkPreset extends FrameworkPreset {` |
|
||||
| 45 | `class` | `ArisFrameworkPreset` | `class ArisFrameworkPreset extends FrameworkPreset {` |
|
||||
|
||||
### `lib/runtime/multi_agent_mount_resolver.dart`
|
||||
|
||||
@ -1103,18 +1090,17 @@ _No extracted public top-level symbols._
|
||||
### `lib/runtime/multi_agent_mounts.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `8`
|
||||
- Public symbols: `7`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 11 | `class` | `MultiAgentMountManager` | `class MultiAgentMountManager {` |
|
||||
| 139 | `abstract interface` | `CliMountAdapter` | `abstract class CliMountAdapter {` |
|
||||
| 191 | `class` | `ArisMountAdapter` | `class ArisMountAdapter extends CliMountAdapter {` |
|
||||
| 277 | `class` | `CodexMountAdapter` | `class CodexMountAdapter extends CliMountAdapter {` |
|
||||
| 350 | `class` | `ClaudeMountAdapter` | `class ClaudeMountAdapter extends CliMountAdapter {` |
|
||||
| 398 | `class` | `GeminiMountAdapter` | `class GeminiMountAdapter extends CliMountAdapter {` |
|
||||
| 446 | `class` | `OpencodeMountAdapter` | `class OpencodeMountAdapter extends CliMountAdapter {` |
|
||||
| 515 | `class` | `OpenClawMountAdapter` | `class OpenClawMountAdapter extends CliMountAdapter {` |
|
||||
| 9 | `class` | `MultiAgentMountManager` | `class MultiAgentMountManager {` |
|
||||
| 90 | `abstract interface` | `CliMountAdapter` | `abstract class CliMountAdapter {` |
|
||||
| 112 | `class` | `CodexMountAdapter` | `class CodexMountAdapter extends CliMountAdapter {` |
|
||||
| 154 | `class` | `ClaudeMountAdapter` | `class ClaudeMountAdapter extends CliMountAdapter {` |
|
||||
| 193 | `class` | `GeminiMountAdapter` | `class GeminiMountAdapter extends CliMountAdapter {` |
|
||||
| 232 | `class` | `OpencodeMountAdapter` | `class OpencodeMountAdapter extends CliMountAdapter {` |
|
||||
| 273 | `class` | `OpenClawMountAdapter` | `class OpenClawMountAdapter extends CliMountAdapter {` |
|
||||
|
||||
### `lib/runtime/multi_agent_orchestrator.dart`
|
||||
|
||||
@ -1130,7 +1116,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 24 | `class` | `MultiAgentOrchestrator` | `class MultiAgentOrchestrator extends ChangeNotifier {` |
|
||||
| 20 | `class` | `MultiAgentOrchestrator` | `class MultiAgentOrchestrator extends ChangeNotifier {` |
|
||||
|
||||
### `lib/runtime/multi_agent_orchestrator_protocol.dart`
|
||||
|
||||
@ -1216,16 +1202,14 @@ _No extracted public top-level symbols._
|
||||
### `lib/runtime/runtime_controllers_derived_tasks.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `6`
|
||||
- Public symbols: `4`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 14 | `class` | `DerivedTasksController` | `class DerivedTasksController extends ChangeNotifier {` |
|
||||
| 150 | `top-level function` | `normalizeMainSessionKey` | `String normalizeMainSessionKey(String? value) {` |
|
||||
| 155 | `top-level function` | `makeAgentSessionKey` | `String makeAgentSessionKey({required String agentId, required String baseKey}) {` |
|
||||
| 164 | `top-level function` | `matchesSessionKey` | `bool matchesSessionKey(String incoming, String current) {` |
|
||||
| 174 | `top-level function` | `encodePrettyJson` | `String encodePrettyJson(Object value) {` |
|
||||
| 179 | `top-level function` | `ephemeralIdInternal` | `String ephemeralIdInternal() =>` |
|
||||
| 6 | `class` | `DerivedTasksController` | `class DerivedTasksController extends ChangeNotifier {` |
|
||||
| 142 | `top-level function` | `matchesSessionKey` | `bool matchesSessionKey(String incoming, String current) {` |
|
||||
| 148 | `top-level function` | `encodePrettyJson` | `String encodePrettyJson(Object value) {` |
|
||||
| 153 | `top-level function` | `ephemeralIdInternal` | `String ephemeralIdInternal() =>` |
|
||||
|
||||
### `lib/runtime/runtime_controllers_entities.dart`
|
||||
|
||||
@ -1249,7 +1233,7 @@ _No extracted public top-level symbols._
|
||||
| 14 | `class` | `AiGatewayResponseExceptionInternal` | `class AiGatewayResponseExceptionInternal implements Exception {` |
|
||||
| 24 | `class` | `GatewayAgentsController` | `class GatewayAgentsController extends ChangeNotifier {` |
|
||||
| 89 | `class` | `GatewaySessionsController` | `class GatewaySessionsController extends ChangeNotifier {` |
|
||||
| 173 | `class` | `GatewayChatController` | `class GatewayChatController extends ChangeNotifier {` |
|
||||
| 146 | `class` | `GatewayChatController` | `class GatewayChatController extends ChangeNotifier {` |
|
||||
|
||||
### `lib/runtime/runtime_controllers_settings.dart`
|
||||
|
||||
@ -1258,7 +1242,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 20 | `class` | `SettingsController` | `class SettingsController extends ChangeNotifier {` |
|
||||
| 21 | `class` | `SettingsController` | `class SettingsController extends ChangeNotifier {` |
|
||||
|
||||
### `lib/runtime/runtime_controllers_settings_account.dart`
|
||||
|
||||
@ -1272,7 +1256,7 @@ _No extracted public top-level symbols._
|
||||
### `lib/runtime/runtime_controllers_settings_account_impl.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `8`
|
||||
- Public symbols: `9`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
@ -1282,8 +1266,9 @@ _No extracted public top-level symbols._
|
||||
| 158 | `top-level function` | `restoreAccountSessionSettingsInternal` | `Future<void> restoreAccountSessionSettingsInternal( SettingsController controller, { String baseUrl = '', bool quiet = false, }) async {` |
|
||||
| 225 | `top-level function` | `syncAccountSettingsInternal` | `Future<AccountSyncResult> syncAccountSettingsInternal( SettingsController controller, { String baseUrl = '', bool quiet = false, Map<String, dynamic> profilePayloadOverride = const <String, dynamic>{}, }) async {` |
|
||||
| 371 | `top-level function` | `logoutAccountSettingsInternal` | `Future<void> logoutAccountSettingsInternal( SettingsController controller, { String statusMessage = 'Signed out', bool quiet = false, }) async {` |
|
||||
| 414 | `top-level function` | `cancelAccountMfaChallengeSettingsInternal` | `Future<void> cancelAccountMfaChallengeSettingsInternal( SettingsController controller, ) async {` |
|
||||
| 444 | `top-level function` | `normalizeAccountBaseUrlSettingsInternal` | `String normalizeAccountBaseUrlSettingsInternal( String raw, { String fallback = '', }) {` |
|
||||
| 424 | `top-level function` | `cancelAccountMfaChallengeSettingsInternal` | `Future<void> cancelAccountMfaChallengeSettingsInternal( SettingsController controller, ) async {` |
|
||||
| 454 | `top-level function` | `normalizeAccountBaseUrlSettingsInternal` | `String normalizeAccountBaseUrlSettingsInternal( String raw, { String fallback = '', }) {` |
|
||||
| 574 | `top-level function` | `resolveAcpBridgeServerEffectiveConfigInternal` | `AcpBridgeServerEffectiveConfig resolveAcpBridgeServerEffectiveConfigInternal( SettingsController controller, { required AcpBridgeServerModeConfig config, }) {` |
|
||||
|
||||
### `lib/runtime/runtime_controllers_settings_connectivity_impl.dart`
|
||||
|
||||
@ -1310,28 +1295,28 @@ _No extracted public top-level symbols._
|
||||
| 3 | `top-level function` | `saveGatewaySecretsSettingsInternal` | `Future<void> saveGatewaySecretsSettingsInternal( SettingsController controller, { int? profileIndex, required String token, required String password, }) async {` |
|
||||
| 61 | `top-level function` | `clearGatewaySecretsSettingsInternal` | `Future<void> clearGatewaySecretsSettingsInternal( SettingsController controller, { int? profileIndex, bool token = false, bool password = false, }) async {` |
|
||||
| 115 | `top-level function` | `loadGatewayTokenSettingsInternal` | `Future<String> loadGatewayTokenSettingsInternal( SettingsController controller, { int? profileIndex, }) async {` |
|
||||
| 141 | `top-level function` | `loadGatewayPasswordSettingsInternal` | `Future<String> loadGatewayPasswordSettingsInternal( SettingsController controller, { int? profileIndex, }) async {` |
|
||||
| 167 | `top-level function` | `hasStoredGatewayTokenForProfileSettingsInternal` | `bool hasStoredGatewayTokenForProfileSettingsInternal( SettingsController controller, int profileIndex, ) =>` |
|
||||
| 179 | `top-level function` | `hasStoredGatewayPasswordForProfileSettingsInternal` | `bool hasStoredGatewayPasswordForProfileSettingsInternal( SettingsController controller, int profileIndex, ) => controller.secureRefsInternal.containsKey( gatewayPasswordRefForProfileSettingsInternal(controller, profileIndex), );` |
|
||||
| 186 | `top-level function` | `storedGatewayTokenMaskForProfileSettingsInternal` | `String? storedGatewayTokenMaskForProfileSettingsInternal( SettingsController controller, int profileIndex, ) =>` |
|
||||
| 199 | `top-level function` | `storedGatewayPasswordMaskForProfileSettingsInternal` | `String? storedGatewayPasswordMaskForProfileSettingsInternal( SettingsController controller, int profileIndex, ) =>` |
|
||||
| 208 | `top-level function` | `gatewayTokenRefForProfileSettingsInternal` | `String gatewayTokenRefForProfileSettingsInternal( SettingsController controller, int profileIndex, ) {` |
|
||||
| 221 | `top-level function` | `gatewayPasswordRefForProfileSettingsInternal` | `String gatewayPasswordRefForProfileSettingsInternal( SettingsController controller, int profileIndex, ) {` |
|
||||
| 234 | `top-level function` | `aiGatewayApiKeyRefSettingsInternal` | `String aiGatewayApiKeyRefSettingsInternal( SettingsController controller, [ AiGatewayProfile? profile, ]) {` |
|
||||
| 243 | `top-level function` | `vaultTokenRefSettingsInternal` | `String vaultTokenRefSettingsInternal( SettingsController controller, [ VaultConfig? profile, ]) {` |
|
||||
| 252 | `top-level function` | `ollamaCloudApiKeyRefSettingsInternal` | `String ollamaCloudApiKeyRefSettingsInternal( SettingsController controller, [ OllamaCloudConfig? profile, ]) {` |
|
||||
| 261 | `top-level function` | `saveOllamaCloudApiKeySettingsInternal` | `Future<void> saveOllamaCloudApiKeySettingsInternal( SettingsController controller, String value, ) async {` |
|
||||
| 287 | `top-level function` | `loadOllamaCloudApiKeySettingsInternal` | `Future<String> loadOllamaCloudApiKeySettingsInternal( SettingsController controller, ) async {` |
|
||||
| 304 | `top-level function` | `saveVaultTokenSettingsInternal` | `Future<void> saveVaultTokenSettingsInternal( SettingsController controller, String value, ) async {` |
|
||||
| 330 | `top-level function` | `loadVaultTokenSettingsInternal` | `Future<String> loadVaultTokenSettingsInternal( SettingsController controller, ) async {` |
|
||||
| 346 | `top-level function` | `saveAiGatewayApiKeySettingsInternal` | `Future<void> saveAiGatewayApiKeySettingsInternal( SettingsController controller, String value, ) async {` |
|
||||
| 372 | `top-level function` | `loadAiGatewayApiKeySettingsInternal` | `Future<String> loadAiGatewayApiKeySettingsInternal( SettingsController controller, ) async {` |
|
||||
| 388 | `top-level function` | `clearAiGatewayApiKeySettingsInternal` | `Future<void> clearAiGatewayApiKeySettingsInternal( SettingsController controller, ) async {` |
|
||||
| 398 | `top-level function` | `saveSecretValueByRefSettingsInternal` | `Future<void> saveSecretValueByRefSettingsInternal( SettingsController controller, String refName, String value, { required String provider, required String module, }) async {` |
|
||||
| 425 | `top-level function` | `loadSecretValueByRefSettingsInternal` | `Future<String> loadSecretValueByRefSettingsInternal( SettingsController controller, String refName, ) async {` |
|
||||
| 435 | `top-level function` | `loadVaultTokenForSecretReadsSettingsInternal` | `Future<String> loadVaultTokenForSecretReadsSettingsInternal( SettingsController controller, { String tokenOverride = '', }) async {` |
|
||||
| 454 | `top-level function` | `readVaultSecretByRefSettingsInternal` | `Future<String> readVaultSecretByRefSettingsInternal( SettingsController controller, String refName, ) async {` |
|
||||
| 484 | `top-level function` | `resolveSecretValueSettingsInternal` | `Future<String> resolveSecretValueSettingsInternal( SettingsController controller, { String explicitValue = '', String refName = '', String fallbackRefName = '', String accountTarget = '', bool allowVaultLookup = true, bool persistExplicitValue = true, }) async {` |
|
||||
| 127 | `top-level function` | `loadGatewayPasswordSettingsInternal` | `Future<String> loadGatewayPasswordSettingsInternal( SettingsController controller, { int? profileIndex, }) async {` |
|
||||
| 139 | `top-level function` | `hasStoredGatewayTokenForProfileSettingsInternal` | `bool hasStoredGatewayTokenForProfileSettingsInternal( SettingsController controller, int profileIndex, ) =>` |
|
||||
| 151 | `top-level function` | `hasStoredGatewayPasswordForProfileSettingsInternal` | `bool hasStoredGatewayPasswordForProfileSettingsInternal( SettingsController controller, int profileIndex, ) => controller.secureRefsInternal.containsKey( gatewayPasswordRefForProfileSettingsInternal(controller, profileIndex), );` |
|
||||
| 158 | `top-level function` | `storedGatewayTokenMaskForProfileSettingsInternal` | `String? storedGatewayTokenMaskForProfileSettingsInternal( SettingsController controller, int profileIndex, ) =>` |
|
||||
| 171 | `top-level function` | `storedGatewayPasswordMaskForProfileSettingsInternal` | `String? storedGatewayPasswordMaskForProfileSettingsInternal( SettingsController controller, int profileIndex, ) =>` |
|
||||
| 180 | `top-level function` | `gatewayTokenRefForProfileSettingsInternal` | `String gatewayTokenRefForProfileSettingsInternal( SettingsController controller, int profileIndex, ) {` |
|
||||
| 193 | `top-level function` | `gatewayPasswordRefForProfileSettingsInternal` | `String gatewayPasswordRefForProfileSettingsInternal( SettingsController controller, int profileIndex, ) {` |
|
||||
| 206 | `top-level function` | `aiGatewayApiKeyRefSettingsInternal` | `String aiGatewayApiKeyRefSettingsInternal( SettingsController controller, [ AiGatewayProfile? profile, ]) {` |
|
||||
| 215 | `top-level function` | `vaultTokenRefSettingsInternal` | `String vaultTokenRefSettingsInternal( SettingsController controller, [ VaultConfig? profile, ]) {` |
|
||||
| 224 | `top-level function` | `ollamaCloudApiKeyRefSettingsInternal` | `String ollamaCloudApiKeyRefSettingsInternal( SettingsController controller, [ OllamaCloudConfig? profile, ]) {` |
|
||||
| 233 | `top-level function` | `saveOllamaCloudApiKeySettingsInternal` | `Future<void> saveOllamaCloudApiKeySettingsInternal( SettingsController controller, String value, ) async {` |
|
||||
| 259 | `top-level function` | `loadOllamaCloudApiKeySettingsInternal` | `Future<String> loadOllamaCloudApiKeySettingsInternal( SettingsController controller, ) async {` |
|
||||
| 267 | `top-level function` | `saveVaultTokenSettingsInternal` | `Future<void> saveVaultTokenSettingsInternal( SettingsController controller, String value, ) async {` |
|
||||
| 293 | `top-level function` | `loadVaultTokenSettingsInternal` | `Future<String> loadVaultTokenSettingsInternal( SettingsController controller, ) async {` |
|
||||
| 301 | `top-level function` | `saveAiGatewayApiKeySettingsInternal` | `Future<void> saveAiGatewayApiKeySettingsInternal( SettingsController controller, String value, ) async {` |
|
||||
| 327 | `top-level function` | `loadAiGatewayApiKeySettingsInternal` | `Future<String> loadAiGatewayApiKeySettingsInternal( SettingsController controller, ) async {` |
|
||||
| 335 | `top-level function` | `clearAiGatewayApiKeySettingsInternal` | `Future<void> clearAiGatewayApiKeySettingsInternal( SettingsController controller, ) async {` |
|
||||
| 345 | `top-level function` | `saveSecretValueByRefSettingsInternal` | `Future<void> saveSecretValueByRefSettingsInternal( SettingsController controller, String refName, String value, { required String provider, required String module, }) async {` |
|
||||
| 372 | `top-level function` | `loadSecretValueByRefSettingsInternal` | `Future<String> loadSecretValueByRefSettingsInternal( SettingsController controller, String refName, ) async {` |
|
||||
| 382 | `top-level function` | `loadVaultTokenForSecretReadsSettingsInternal` | `Future<String> loadVaultTokenForSecretReadsSettingsInternal( SettingsController controller, { String tokenOverride = '', }) async {` |
|
||||
| 393 | `top-level function` | `readVaultSecretByRefSettingsInternal` | `Future<String> readVaultSecretByRefSettingsInternal( SettingsController controller, String refName, ) async {` |
|
||||
| 423 | `top-level function` | `resolveSecretValueSettingsInternal` | `Future<String> resolveSecretValueSettingsInternal( SettingsController controller, { String explicitValue = '', String refName = '', String fallbackRefName = '', String accountTarget = '', bool allowVaultLookup = true, bool persistExplicitValue = true, }) async {` |
|
||||
|
||||
### `lib/runtime/runtime_coordinator.dart`
|
||||
|
||||
@ -1341,7 +1326,7 @@ _No extracted public top-level symbols._
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 17 | `enum` | `CoordinatorState` | `enum CoordinatorState { disconnected, connecting, connected, ready, error }` |
|
||||
| 26 | `class` | `RuntimeCoordinator` | `class RuntimeCoordinator extends ChangeNotifier {` |
|
||||
| 20 | `class` | `RuntimeCoordinator` | `class RuntimeCoordinator extends ChangeNotifier {` |
|
||||
|
||||
### `lib/runtime/runtime_dispatch_resolver.dart`
|
||||
|
||||
@ -1374,22 +1359,22 @@ _No extracted public top-level symbols._
|
||||
### `lib/runtime/runtime_models_account.dart`
|
||||
|
||||
- Language: `dart`
|
||||
- Public symbols: `13`
|
||||
- Public symbols: `12`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 4 | `class` | `AccountSessionSummary` | `class AccountSessionSummary {` |
|
||||
| 68 | `class` | `AccountTokenConfigured` | `class AccountTokenConfigured {` |
|
||||
| 108 | `class` | `AccountSecretLocator` | `class AccountSecretLocator {` |
|
||||
| 166 | `class` | `AccountRemoteProfile` | `class AccountRemoteProfile {` |
|
||||
| 269 | `class` | `AcpBridgeServerRemoteServerSummary` | `class AcpBridgeServerRemoteServerSummary {` |
|
||||
| 312 | `class` | `AcpBridgeServerCloudSyncConfig` | `class AcpBridgeServerCloudSyncConfig {` |
|
||||
| 370 | `class` | `AcpBridgeServerSelfHostedConfig` | `class AcpBridgeServerSelfHostedConfig {` |
|
||||
| 423 | `class` | `AcpBridgeServerAdvancedOverrides` | `class AcpBridgeServerAdvancedOverrides {` |
|
||||
| 509 | `class` | `AcpBridgeServerModeConfig` | `class AcpBridgeServerModeConfig {` |
|
||||
| 577 | `class` | `AccountSyncState` | `class AccountSyncState {` |
|
||||
| 667 | `class` | `AccountSyncResult` | `class AccountSyncResult {` |
|
||||
| 686 | `top-level function` | `isSupportedAccountManagedSecretTarget` | `bool isSupportedAccountManagedSecretTarget(String target) {` |
|
||||
| 3 | `class` | `AccountSessionSummary` | `class AccountSessionSummary {` |
|
||||
| 67 | `class` | `AccountTokenConfigured` | `class AccountTokenConfigured {` |
|
||||
| 96 | `class` | `AccountSecretLocator` | `class AccountSecretLocator {` |
|
||||
| 154 | `class` | `AccountRemoteProfile` | `class AccountRemoteProfile {` |
|
||||
| 248 | `class` | `AcpBridgeServerRemoteServerSummary` | `class AcpBridgeServerRemoteServerSummary {` |
|
||||
| 276 | `class` | `AcpBridgeServerCloudSyncConfig` | `class AcpBridgeServerCloudSyncConfig {` |
|
||||
| 334 | `class` | `AcpBridgeServerSelfHostedConfig` | `class AcpBridgeServerSelfHostedConfig {` |
|
||||
| 387 | `class` | `AcpBridgeServerEffectiveConfig` | `class AcpBridgeServerEffectiveConfig {` |
|
||||
| 442 | `class` | `AcpBridgeServerModeConfig` | `class AcpBridgeServerModeConfig {` |
|
||||
| 498 | `class` | `AccountSyncState` | `class AccountSyncState {` |
|
||||
| 588 | `class` | `AccountSyncResult` | `class AccountSyncResult {` |
|
||||
| 607 | `top-level function` | `isSupportedAccountManagedSecretTarget` | `bool isSupportedAccountManagedSecretTarget(String target) {` |
|
||||
|
||||
### `lib/runtime/runtime_models_configs.dart`
|
||||
|
||||
@ -1399,16 +1384,16 @@ _No extracted public top-level symbols._
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 13 | `class` | `GatewayConnectionProfile` | `class GatewayConnectionProfile {` |
|
||||
| 136 | `top-level function` | `normalizeGatewayProfiles` | `List<GatewayConnectionProfile> normalizeGatewayProfiles({ Iterable<GatewayConnectionProfile>? profiles, }) {` |
|
||||
| 214 | `top-level function` | `replaceGatewayProfileAt` | `List<GatewayConnectionProfile> replaceGatewayProfileAt( List<GatewayConnectionProfile> profiles, int index, GatewayConnectionProfile profile, ) {` |
|
||||
| 260 | `class` | `OllamaLocalConfig` | `class OllamaLocalConfig {` |
|
||||
| 311 | `class` | `OllamaCloudConfig` | `class OllamaCloudConfig {` |
|
||||
| 378 | `class` | `VaultConfig` | `class VaultConfig {` |
|
||||
| 434 | `class` | `AiGatewayProfile` | `class AiGatewayProfile {` |
|
||||
| 532 | `class` | `AiGatewayConnectionCheck` | `class AiGatewayConnectionCheck {` |
|
||||
| 548 | `enum` | `WebSessionPersistenceMode` | `enum WebSessionPersistenceMode { browser, remote }` |
|
||||
| 550 | `extension` | `WebSessionPersistenceModeCopy` | `extension WebSessionPersistenceModeCopy on WebSessionPersistenceMode {` |
|
||||
| 567 | `class` | `WebSessionPersistenceConfig` | `class WebSessionPersistenceConfig {` |
|
||||
| 121 | `top-level function` | `normalizeGatewayProfiles` | `List<GatewayConnectionProfile> normalizeGatewayProfiles({ Iterable<GatewayConnectionProfile>? profiles, }) {` |
|
||||
| 162 | `top-level function` | `replaceGatewayProfileAt` | `List<GatewayConnectionProfile> replaceGatewayProfileAt( List<GatewayConnectionProfile> profiles, int _, GatewayConnectionProfile profile, ) {` |
|
||||
| 206 | `class` | `OllamaLocalConfig` | `class OllamaLocalConfig {` |
|
||||
| 257 | `class` | `OllamaCloudConfig` | `class OllamaCloudConfig {` |
|
||||
| 324 | `class` | `VaultConfig` | `class VaultConfig {` |
|
||||
| 380 | `class` | `AiGatewayProfile` | `class AiGatewayProfile {` |
|
||||
| 473 | `class` | `AiGatewayConnectionCheck` | `class AiGatewayConnectionCheck {` |
|
||||
| 489 | `enum` | `WebSessionPersistenceMode` | `enum WebSessionPersistenceMode { browser, remote }` |
|
||||
| 491 | `extension` | `WebSessionPersistenceModeCopy` | `extension WebSessionPersistenceModeCopy on WebSessionPersistenceMode {` |
|
||||
| 508 | `class` | `WebSessionPersistenceConfig` | `class WebSessionPersistenceConfig {` |
|
||||
|
||||
### `lib/runtime/runtime_models_connection.dart`
|
||||
|
||||
@ -1540,11 +1525,11 @@ _No extracted public top-level symbols._
|
||||
| 711 | `top-level function` | `assistantExecutionTargetFromExecutionMode` | `AssistantExecutionTarget assistantExecutionTargetFromExecutionMode( ThreadExecutionMode mode, ) {` |
|
||||
| 720 | `top-level function` | `workspaceRefKindFromWorkspaceKind` | `WorkspaceRefKind workspaceRefKindFromWorkspaceKind(WorkspaceKind kind) {` |
|
||||
| 727 | `class` | `ThreadContextState` | `class ThreadContextState {` |
|
||||
| 904 | `class` | `ThreadLifecycleState` | `class ThreadLifecycleState {` |
|
||||
| 960 | `class` | `TaskThread` | `class TaskThread {` |
|
||||
| 1291 | `top-level function` | `isNewConversationTaskTitle` | `bool isNewConversationTaskTitle(String title) {` |
|
||||
| 1296 | `top-level function` | `firstUserMessageTaskTitle` | `String firstUserMessageTaskTitle( Iterable<GatewayChatMessage> messages, { String fallback = '', }) {` |
|
||||
| 1318 | `top-level function` | `derivePersistedTaskTitle` | `String derivePersistedTaskTitle( String currentTitle, Iterable<GatewayChatMessage> messages, { String fallback = '', bool hasCustomTitle = false, }) {` |
|
||||
| 935 | `class` | `ThreadLifecycleState` | `class ThreadLifecycleState {` |
|
||||
| 991 | `class` | `TaskThread` | `class TaskThread {` |
|
||||
| 1332 | `top-level function` | `isNewConversationTaskTitle` | `bool isNewConversationTaskTitle(String title) {` |
|
||||
| 1337 | `top-level function` | `firstUserMessageTaskTitle` | `String firstUserMessageTaskTitle( Iterable<GatewayChatMessage> messages, { String fallback = '', }) {` |
|
||||
| 1359 | `top-level function` | `derivePersistedTaskTitle` | `String derivePersistedTaskTitle( String currentTitle, Iterable<GatewayChatMessage> messages, { String fallback = '', bool hasCustomTitle = false, }) {` |
|
||||
|
||||
### `lib/runtime/runtime_models_settings_snapshot.dart`
|
||||
|
||||
@ -1553,7 +1538,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 16 | `class` | `SettingsSnapshot` | `class SettingsSnapshot {` |
|
||||
| 17 | `class` | `SettingsSnapshot` | `class SettingsSnapshot {` |
|
||||
|
||||
### `lib/runtime/runtime_models_ui_state.dart`
|
||||
|
||||
@ -1583,7 +1568,7 @@ _No extracted public top-level symbols._
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 13 | `class` | `SecureConfigStore` | `class SecureConfigStore {` |
|
||||
| 9 | `class` | `SecureConfigStore` | `class SecureConfigStore {` |
|
||||
|
||||
### `lib/runtime/settings_store.dart`
|
||||
|
||||
@ -1594,9 +1579,9 @@ _No extracted public top-level symbols._
|
||||
| ---: | --- | --- | --- |
|
||||
| 8 | `enum` | `SettingsSnapshotReloadStatus` | `enum SettingsSnapshotReloadStatus { applied, invalid }` |
|
||||
| 10 | `class` | `SettingsSnapshotReloadResult` | `class SettingsSnapshotReloadResult {` |
|
||||
| 22 | `enum` | `SkippedTaskThreadReason` | `enum SkippedTaskThreadReason {` |
|
||||
| 28 | `class` | `SkippedTaskThreadRecord` | `class SkippedTaskThreadRecord {` |
|
||||
| 35 | `class` | `SettingsStore` | `class SettingsStore {` |
|
||||
| 20 | `enum` | `SkippedTaskThreadReason` | `enum SkippedTaskThreadReason {` |
|
||||
| 26 | `class` | `SkippedTaskThreadRecord` | `class SkippedTaskThreadRecord {` |
|
||||
| 36 | `class` | `SettingsStore` | `class SettingsStore {` |
|
||||
|
||||
### `lib/runtime/skill_directory_access.dart`
|
||||
|
||||
@ -1649,7 +1634,7 @@ _No extracted public top-level symbols._
|
||||
## rust/src
|
||||
|
||||
- Files: `4`
|
||||
- Public symbols: `19`
|
||||
- Public symbols: `16`
|
||||
|
||||
### `rust/src/error.rs`
|
||||
|
||||
@ -1692,12 +1677,9 @@ _No extracted public top-level symbols._
|
||||
### `rust/src/types.rs`
|
||||
|
||||
- Language: `rust`
|
||||
- Public symbols: `5`
|
||||
- Public symbols: `2`
|
||||
|
||||
| Line | Kind | Name | Signature |
|
||||
| ---: | --- | --- | --- |
|
||||
| 8 | `struct` | `CodexResult` | `pub struct CodexResult {` |
|
||||
| 38 | `struct` | `CodexMessage` | `pub struct CodexMessage {` |
|
||||
| 51 | `struct` | `CodexEvent` | `pub struct CodexEvent {` |
|
||||
| 66 | `struct` | `CodexModelInfo` | `pub struct CodexModelInfo {` |
|
||||
| 79 | `struct` | `CodexAccountInfo` | `pub struct CodexAccountInfo {` |
|
||||
| 38 | `struct` | `CodexEvent` | `pub struct CodexEvent {` |
|
||||
|
||||
@ -56,7 +56,6 @@ The app only talks to:
|
||||
- no production `xworkmate.providers.sync`
|
||||
- no production provider catalog from `providerSyncDefinitions`
|
||||
- no execution-time use of account-synced `openclawUrl`
|
||||
- no execution-time use of account-synced `apisixUrl`
|
||||
- no direct app calls to `xworkmate-bridge.svc.plus/*`
|
||||
- no direct app calls to `openclaw.svc.plus`
|
||||
|
||||
@ -71,7 +70,7 @@ The app only talks to:
|
||||
`account/sync_state.json`
|
||||
|
||||
- stores synced account metadata only
|
||||
- may retain `openclawUrl` / `apisixUrl` as account profile metadata
|
||||
- may retain `openclawUrl` as account profile metadata
|
||||
- does not overwrite executable cloud routing targets
|
||||
|
||||
`acpBridgeServerModeConfig.effective`
|
||||
|
||||
161
docs/reports/2026-05-13-flutter-stale-code-cleanup-analysis.md
Normal file
161
docs/reports/2026-05-13-flutter-stale-code-cleanup-analysis.md
Normal file
@ -0,0 +1,161 @@
|
||||
# Flutter/Dart 孤立代码与陈旧代码清理分析
|
||||
|
||||
日期:2026-05-13
|
||||
|
||||
范围:
|
||||
|
||||
- `lib/settings/mobile/runtime`:目录不存在
|
||||
- `lib/gateway`:目录不存在
|
||||
- `lib/profile`:目录不存在
|
||||
- `lib/shared/shell`:目录不存在
|
||||
- `lib/widgets/layout`:目录不存在
|
||||
- `lib/core/helper`:目录不存在
|
||||
- `lib/core/utils`:目录不存在
|
||||
- 已扫描仍存在的重点路径:`lib/runtime`、`lib/features/settings`、`lib/features/mobile`、`lib/widgets`、`lib/app`
|
||||
|
||||
## 已执行扫描
|
||||
|
||||
- `rg "^export " lib test`
|
||||
- `find lib -name "*.dart"`
|
||||
- `rg "^class |^typedef |^extension |^mixin "`
|
||||
- `rg "register|registry|routes:|GoRoute|GetIt|Provider|Riverpod|dispatch|mount|factory|builder:|runtimeType"`
|
||||
- `rg "legacy|deprecated|old|helper|tmp|unused|v1|backup|compat|fallback"`
|
||||
|
||||
## Safe To Remove
|
||||
|
||||
本轮已删除:
|
||||
|
||||
- `lib/app/app_controller_desktop_single_agent.dart`
|
||||
- 空 extension:`AppControllerDesktopSingleAgent`
|
||||
- 无方法、无动态注册、无 route/provider/ACP 入口
|
||||
- 同步移除 `lib/app/app_controller_desktop.dart` export 与所有 app controller import
|
||||
- `SettingsGlobalApplyCard`
|
||||
- 定义于 `lib/widgets/settings_page_shell.dart`
|
||||
- 无引用、未进入 Settings widget tree
|
||||
- `buildOrderedSettingsSections`
|
||||
- 定义于 `lib/widgets/settings_page_shell.dart`
|
||||
- 无引用,旧多分区 Settings shell helper
|
||||
- `AcpBridgeServerAdvancedOverrides`
|
||||
- 定义于 `lib/runtime/runtime_models_account.dart`
|
||||
- 仅被 `AcpBridgeServerModeConfig` 自身序列化引用,无 runtime usage
|
||||
- 属于旧本地/高级配置中心残留
|
||||
- `AcpBridgeServerRemoteServerSummary.hasAdvancedOverrides`
|
||||
- 仅写入固定 false,无业务消费
|
||||
- `AccountTokenConfigured.apisix` 与 `AccountRemoteProfile.apisixUrl`
|
||||
- 旧 APISIX/AI Gateway 账号同步字段
|
||||
- 当前 OpenClaw/Gateway task 链路不再消费
|
||||
- `AiGatewayProfile.fromJson(filePath -> baseUrl)` fallback
|
||||
- 旧字段兼容路径
|
||||
- `SettingsSnapshot.fromJson(apisix -> aiGateway)` fallback
|
||||
- 旧字段兼容路径
|
||||
- `main` / `agent:main:main` 会话 key alias
|
||||
- 移除于 `runtime_controllers_derived_tasks.dart`
|
||||
- 移除于 `assistant_page_task_models.dart`
|
||||
|
||||
## Probably Removable
|
||||
|
||||
以下仍需按业务闭包继续拆,不建议一次性自动删除:
|
||||
|
||||
- `lib/data/mock_data.dart`
|
||||
- stem 引用为 0,疑似旧展示数据
|
||||
- caution:可能被 dev/demo surface 间接引用,删除前需确认应用入口和测试 fixture
|
||||
- `lib/widgets/metric_card.dart`
|
||||
- stem 引用为 0
|
||||
- 看起来是旧 dashboard card,当前重点 UI 未挂载
|
||||
- `lib/widgets/section_header.dart`
|
||||
- stem 引用为 0
|
||||
- 可能是旧页面布局 helper
|
||||
- `lib/widgets/app_brand_logo.dart`
|
||||
- stem 引用为 0
|
||||
- caution:可能由 launch/splash/brand 测试或外部 import 使用
|
||||
- `lib/runtime/aris_llm_chat_client.dart`
|
||||
- 注释标记本地 Go core execution deprecated
|
||||
- caution:仍被 multi-agent orchestrator protocol/workflow/support import
|
||||
- `lib/runtime/mode_switcher.dart`
|
||||
- 仍被 runtime coordinator 与 app controller 多处使用
|
||||
- 不应直接删,后续应评估 Gateway mode 是否还需要 app-side mode switcher
|
||||
|
||||
## Dynamic Runtime Bound
|
||||
|
||||
以下存在动态入口或 runtime 注册,不应自动删除:
|
||||
|
||||
- `lib/app/workspace_page_registry.dart`
|
||||
- Workspace route/page registry
|
||||
- `lib/app/app_controller_desktop_runtime_helpers.dart`
|
||||
- `registerCodexExternalProviderInternal`
|
||||
- runtime provider registration
|
||||
- `lib/runtime/runtime_coordinator.dart`
|
||||
- external code agent registry
|
||||
- dispatch resolver
|
||||
- `lib/runtime/gateway_acp_client.dart`
|
||||
- ACP capability/provider catalog parsing
|
||||
- Gateway/OpenClaw dispatch routing
|
||||
- `lib/runtime/go_task_service_client.dart`
|
||||
- OpenClaw/Gateway task request/result contract
|
||||
- `lib/runtime/external_code_agent_acp_desktop_transport.dart`
|
||||
- ACP transport capability parse path
|
||||
- `lib/runtime/agent_registry.dart`
|
||||
- Gateway agent register/unregister/list path
|
||||
- `lib/runtime/multi_agent_mounts.dart`
|
||||
- mount adapter registration and reconcile path
|
||||
|
||||
## Legacy Compatibility Layer
|
||||
|
||||
已清理:
|
||||
|
||||
- `AcpBridgeServerAdvancedOverrides`
|
||||
- APISIX account sync fields
|
||||
- AiGateway old `filePath` fallback
|
||||
- SettingsSnapshot old `apisix` fallback
|
||||
- runtime `main`/`agent:main:main` session alias
|
||||
|
||||
保留但标记 caution:
|
||||
|
||||
- `SecretStore.legacyLocalStateKey`
|
||||
- 安全/本地持久化恢复路径,AGENTS 明确这类 legacy recovery 不自动扩张也不自动删除
|
||||
- secret `fallbackRefName`
|
||||
- 用于 secure-store ref resolution,不属于 UI 本地配置中心入口
|
||||
- `go_task_service_client.dart` 的 failure text fallback
|
||||
- task terminal-state 文本兜底,后续应继续收敛到结构化 code
|
||||
|
||||
## Export Cleanup
|
||||
|
||||
当前 barrel 扫描:
|
||||
|
||||
- `lib/app/app_controller_desktop.dart`:仍是 app controller extension 聚合入口,内部 import 为 0 属于 barrel 预期
|
||||
- `lib/features/settings/settings_page.dart`:settings feature public entry,内部 import 为 0 属于 barrel 预期
|
||||
- `lib/features/mobile/mobile_shell.dart`:mobile feature public entry,内部 import 为 0 属于 barrel 预期
|
||||
- `lib/runtime/gateway_runtime.dart`、`lib/runtime/multi_agent_orchestrator.dart`、`lib/runtime/runtime_models.dart`:runtime public barrel,动态/测试入口仍依赖
|
||||
|
||||
本轮已清理的 export:
|
||||
|
||||
- `lib/app/app_controller_desktop.dart` 不再 export `app_controller_desktop_single_agent.dart`
|
||||
|
||||
## Unreachable Widget Tree
|
||||
|
||||
已删除:
|
||||
|
||||
- Settings 全局 apply card
|
||||
- Settings 多分区排序 helper
|
||||
|
||||
仍在 widget tree:
|
||||
|
||||
- `SettingsPage`
|
||||
- 通过 `workspace_page_registry.dart` 挂载
|
||||
- `SettingsAccountPanel`
|
||||
- 通过 `SettingsPage` 挂载
|
||||
- `SettingsAboutPanel`
|
||||
- 通过 `SettingsPage` 挂载
|
||||
- `MobileShell`
|
||||
- 通过 `AppShell` responsive surface 挂载
|
||||
- `MobileGatewayPairingGuidePage`
|
||||
- 通过 `MobileShell` pairing flow 挂载
|
||||
- `AssistantFocusPanel`
|
||||
- 预览组件仍由 assistant focus panel 内部分发
|
||||
|
||||
## Refactor Suggestions
|
||||
|
||||
- 继续收敛 `SettingsSnapshot`:把不再有 UI 的 Vault/Ollama/AiGateway 配置按实际 runtime 使用拆分,避免 Settings model 继续承担旧配置中心职责。
|
||||
- 后续单独评估 `lib/data/mock_data.dart`、`MetricCard`、`SectionHeader`、`AppBrandLogo` 是否仍有真实入口。
|
||||
- 对 `runtime_controllers_settings*.dart` 继续拆闭包:account sync、secret resolution、connectivity check 三条路径应独立,避免 SettingsController 成为旧配置中心聚合点。
|
||||
- 对 `go_task_service_client.dart` terminal-state fallback 继续结构化,减少文本兜底。
|
||||
@ -1,190 +0,0 @@
|
||||
# Codex Agent FFI 集成状态报告
|
||||
|
||||
## 测试执行时间
|
||||
2026-03-14 10:20
|
||||
|
||||
## FFI 库状态
|
||||
**文件路径:** `/Applications/XWorkmate.app/Contents/Frameworks/libcodex_ffi.dylib`
|
||||
**大小:** 302 KB (ARM64)
|
||||
**架构:** Mach-O 64-bit dynamically linked shared library arm64
|
||||
|
||||
## FFI 函数可用性测试
|
||||
|
||||
### ✅ 可用的 FFI 函数(已导出)
|
||||
|
||||
| 函数名 | 状态 | 说明 |
|
||||
|--------|------|------|
|
||||
| `codex_init()` | ✅ 可用 | 初始化库,返回 0 表示成功 |
|
||||
| `codex_runtime_create()` | ✅ 可用 | 创建运行时实例,返回有效指针 |
|
||||
| `codex_runtime_destroy()` | ✅ 可用 | 销毁运行时实例,清理内存 |
|
||||
| `codex_start_thread()` | ✅ 可用 | 启动线程,返回 ThreadHandle (id=0 表示空句柄) |
|
||||
| `codex_send_message()` | ✅ 可用 | 发送消息,返回 0 表示成功 |
|
||||
| `codex_poll_events()` | ✅ 可用 | 轮询事件,返回 0 (未实现) |
|
||||
| `codex_shutdown()` | ✅ 可用 | 关闭运行时,返回 0 表示成功 |
|
||||
| `codex_last_error()` | ✅ 可用 | 获取最后错误信息 |
|
||||
|
||||
### ❌ 核心功能实现状态
|
||||
|
||||
根据 Rust 源码分析 (`rust/src/lib.rs` 和 `rust/src/runtime.rs`):
|
||||
|
||||
| 功能 | 实现状态 | 代码位置 |
|
||||
|------|----------|----------|
|
||||
| Codex CLI 进程启动 | ❌ **未实现** | `runtime.rs:235` - `// TODO: Start process` |
|
||||
| 异步消息发送 | ❌ **未实现** | `lib.rs:87` - `// TODO: Implement async message sending` |
|
||||
| 事件轮询机制 | ❌ **未实现** | `lib.rs:108` - `// TODO: Implement event polling` |
|
||||
| 响应流处理 | ❌ **未实现** | 无相关代码 |
|
||||
| 进程停止管理 | ❌ **未实现** | `runtime.rs:247` - `// TODO: Stop process` |
|
||||
| Codex 二进制查找 | ✅ **已实现** | `runtime.rs:202-221` |
|
||||
|
||||
## 对话功能测试结果
|
||||
|
||||
### 测试尝试
|
||||
尝试通过 FFI 发送消息并轮询响应:
|
||||
|
||||
```dart
|
||||
// 1. 创建运行时 ✅
|
||||
runtime = codex_runtime_create(config);
|
||||
// 结果: 成功,返回有效指针
|
||||
|
||||
// 2. 启动线程 ✅
|
||||
thread = codex_start_thread(runtime, cwd);
|
||||
// 结果: 返回 ThreadHandle,但 id=0 (空句柄)
|
||||
|
||||
// 3. 发送消息 ✅
|
||||
result = codex_send_message(runtime, thread, message);
|
||||
// 结果: 返回 0 (成功),但消息实际上未发送
|
||||
|
||||
// 4. 轮询响应 ❌
|
||||
events = codex_poll_events(runtime, buffer, bufferSize);
|
||||
// 结果: 返回 0 (无事件)
|
||||
// 原因: 未实现事件队列和处理逻辑
|
||||
```
|
||||
|
||||
### 结论
|
||||
**❌ 无法进行真正的 Codex agent 对话**
|
||||
|
||||
原因:
|
||||
1. Codex CLI 进程从未启动
|
||||
2. FFI 函数只是桩代码(stubs),返回预定义值
|
||||
3. 没有实际的消息处理和响应机制
|
||||
4. 事件轮询返回 0,因为没有事件队列
|
||||
|
||||
## 执行功能测试结果
|
||||
|
||||
### 虽拟执行测试
|
||||
尝试通过 FFI 执行类似 "创建文件" 的操作:
|
||||
|
||||
```dart
|
||||
// 发送执行指令
|
||||
codex_send_message(runtime, thread, "Create a file named test.txt");
|
||||
// 结果: 返回 0 (成功),但:
|
||||
// 1. Codex 进程未启动,无法接收指令
|
||||
// 2. 没有执行管道和输出捕获
|
||||
// 3. 没有文件系统操作的实际代码
|
||||
```
|
||||
|
||||
### 结论
|
||||
**❌ 无法执行任何 Codex agent 操作**
|
||||
|
||||
原因:
|
||||
- 没有进程管理代码
|
||||
- 没有 stdio 管道建立
|
||||
- 没有输出流处理
|
||||
- 没有文件系统操作接口
|
||||
|
||||
## 当前架构评估
|
||||
|
||||
### ✅ 已完成的部分
|
||||
1. **FFI 接口定义** - 所有必要的函数签名已定义
|
||||
2. **内存管理** - Box 智能指针正确用于 FFI 边界
|
||||
3. **类型安全** - Rust Struct 和 Dart FFI 类型对应正确
|
||||
4. **编译构建** - dylib 成功编译并可加载
|
||||
5. **基础测试** - 简单的 FFI 调用可以成功执行
|
||||
|
||||
### ❌ 缺失的关键部分
|
||||
1. **进程管理** - 无子进程启动、监控、停止机制
|
||||
2. **IPC 通信** - 无消息队列、事件通知机制
|
||||
3. **异步处理** - Rust 端无异步代码,Dart 端无回调接口
|
||||
4. **Codex 集成** - 无实际调用 Codex CLI 的代码
|
||||
5. **错误处理** - 所有错误都被忽略,返回固定值
|
||||
|
||||
## 离线模式实际工作原理
|
||||
|
||||
由于 Codex FFI 未完全实现,当前应用在"离线模式"下:
|
||||
|
||||
### 实际使用的是
|
||||
- **Stdio 桥接模式** - 通过 `CodexRuntime` Dart 类直接调用外部 Codex CLI
|
||||
- **外部 CLI 模式** - 启动独立的 `codex` 可执行文件进程,通过 stdin/stdout 通信
|
||||
|
||||
### 不是使用
|
||||
- ❌ 内置 FFI Rust 库 (`libcodex_ffi.dylib`)
|
||||
- ❌ 内存内的 Codex 实现
|
||||
- ❌ Rust 嵌入式 Codex
|
||||
|
||||
## 完整对话和执行的实现路径
|
||||
|
||||
要使 libcodex_ffi.dylib 能够进行真正的对话和执行,需要:
|
||||
|
||||
### 1. Rust 端实现
|
||||
```rust
|
||||
// 需要实现的核心组件:
|
||||
- ProcessManager: 启动/停止 Codex CLI 进程
|
||||
- MessageQueue: 异步消息队列
|
||||
- EventStream: 事件流输出 (响应、日志、错误)
|
||||
- StdioHandler: stdin/stdout/stderr 处理
|
||||
- TaskScheduler: 任务执行调度
|
||||
```
|
||||
|
||||
### 2. FFI 接口扩展
|
||||
```rust
|
||||
// 新增需要的函数:
|
||||
- codex_execute_command() - 执行 shell 命令
|
||||
- codex_read_file() - 读取文件内容
|
||||
- codex_write_file() - 写入文件
|
||||
- codex_list_directory() - 列出目录
|
||||
- codex_get_response() - 获取 AI 响应流
|
||||
```
|
||||
|
||||
### 3. Dart 端实现
|
||||
```dart
|
||||
// 需要实现:
|
||||
- StreamController: 处理响应流
|
||||
- CallbackHandler: Rust 回调转 Dart
|
||||
- ErrorHandler: 错误传播
|
||||
- TimeoutManager: 超时管理
|
||||
```
|
||||
|
||||
## 建议
|
||||
|
||||
### 短期(当前可行)
|
||||
继续使用**外部 CLI 模式**:
|
||||
- 通过 `CodexRuntime.dart` 直接启动 `codex` 可执行文件
|
||||
- 使用 Stdio 进行通信
|
||||
- 不依赖 FFI Rust 库
|
||||
|
||||
### 中期(需要开发)
|
||||
实现基本 FFI 功能:
|
||||
1. 进程管理(启动/停止 Codex)
|
||||
2. 基础消息传递
|
||||
3. 简单响应接收
|
||||
|
||||
### 长期(完整功能)
|
||||
完整 Rust FFI 实现:
|
||||
1. 嵌入式 Codex(无需外部 CLI)
|
||||
2. 异步事件流
|
||||
3. 文件系统操作
|
||||
4. 任务执行和监控
|
||||
|
||||
## 总结
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| FFI 库加载 | ✅ 通过 | dylib 可正常加载 |
|
||||
| FFI 函数调用 | ✅ 通过 | 所有函数可调用 |
|
||||
| 对话功能 | ❌ 失败 | 未实现,Codex 进程未启动 |
|
||||
| 执行功能 | ❌ 失败 | 未实现,无 IPC 机制 |
|
||||
| 响应接收 | ❌ 失败 | 未实现,无事件流 |
|
||||
|
||||
**当前状态:** libcodex_ffi.dylib 提供了 FFI 接口的**骨架**,但缺乏实现对话和执行所需的**核心逻辑**。
|
||||
|
||||
**实际可用方案:** 应用当前通过外部 Codex CLI(Stdio 模式)在离线模式下运行,不依赖 Rust FFI 库。
|
||||
@ -1,20 +0,0 @@
|
||||
# Flutter Rust Bridge Configuration
|
||||
# This file configures code generation for FFI bindings
|
||||
|
||||
rust_input:
|
||||
- rust/src/lib.rs
|
||||
|
||||
dart_output:
|
||||
- lib/runtime/codex_ffi_generated.dart
|
||||
|
||||
# Class names for generated Dart code
|
||||
rust_root_namespace: codex_ffi
|
||||
|
||||
# Output configuration
|
||||
dart_format_line_length: 120
|
||||
|
||||
# FFI library name (without extension)
|
||||
c_symbol_prefix: codex_
|
||||
|
||||
# Generate documentation
|
||||
dart_type_name_length_limit: 60
|
||||
@ -2,7 +2,6 @@ export 'app_controller_desktop_core.dart';
|
||||
export 'app_controller_desktop_navigation.dart';
|
||||
export 'app_controller_desktop_gateway.dart';
|
||||
export 'app_controller_desktop_settings.dart';
|
||||
export 'app_controller_desktop_single_agent.dart';
|
||||
export 'app_controller_desktop_thread_sessions.dart';
|
||||
export 'app_controller_desktop_thread_actions.dart';
|
||||
export 'app_controller_desktop_workspace_execution.dart';
|
||||
|
||||
@ -356,8 +356,6 @@ class AppController extends ChangeNotifier {
|
||||
ThemeMode themeModeInternal = ThemeMode.light;
|
||||
AppSidebarState sidebarStateInternal = AppSidebarState.expanded;
|
||||
SettingsTab settingsTabInternal = SettingsTab.gateway;
|
||||
SettingsDetailPage? settingsDetailInternal;
|
||||
SettingsNavigationContext? settingsNavigationContextInternal;
|
||||
DetailPanelData? detailPanelInternal;
|
||||
AppUiState appUiStateInternal = AppUiState.defaults();
|
||||
SettingsSnapshot settingsDraftInternal = SettingsSnapshot.defaults();
|
||||
@ -425,9 +423,6 @@ class AppController extends ChangeNotifier {
|
||||
ThemeMode get themeMode => themeModeInternal;
|
||||
AppSidebarState get sidebarState => sidebarStateInternal;
|
||||
SettingsTab get settingsTab => settingsTabInternal;
|
||||
SettingsDetailPage? get settingsDetail => settingsDetailInternal;
|
||||
SettingsNavigationContext? get settingsNavigationContext =>
|
||||
settingsNavigationContextInternal;
|
||||
DetailPanelData? get detailPanel => detailPanelInternal;
|
||||
bool get initializing => initializingInternal;
|
||||
String? get bootstrapError => bootstrapErrorInternal;
|
||||
@ -576,13 +571,42 @@ class AppController extends ChangeNotifier {
|
||||
]);
|
||||
|
||||
List<SingleAgentProvider> get assistantProviderCatalog =>
|
||||
normalizeSingleAgentProviderList(bridgeAgentProviderCatalogInternal);
|
||||
normalizeSingleAgentProviderList(
|
||||
bridgeAgentProviderCatalogInternal.where(
|
||||
(provider) =>
|
||||
provider.providerId != kCanonicalGatewayProviderId &&
|
||||
!provider.supportedTargets.contains(
|
||||
AssistantExecutionTarget.gateway,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
List<SingleAgentProvider> get gatewayProviderCatalog =>
|
||||
normalizeSingleAgentProviderList(bridgeGatewayProviderCatalogInternal);
|
||||
normalizeSingleAgentProviderList(<SingleAgentProvider>[
|
||||
...bridgeGatewayProviderCatalogInternal,
|
||||
...bridgeAgentProviderCatalogInternal.where(
|
||||
(provider) =>
|
||||
provider.providerId == kCanonicalGatewayProviderId ||
|
||||
provider.supportedTargets.contains(
|
||||
AssistantExecutionTarget.gateway,
|
||||
),
|
||||
),
|
||||
]);
|
||||
|
||||
List<AssistantExecutionTarget> get bridgeAvailableExecutionTargets =>
|
||||
compactAssistantExecutionTargets(bridgeAvailableExecutionTargetsInternal);
|
||||
List<AssistantExecutionTarget> get bridgeAvailableExecutionTargets {
|
||||
final targets = <AssistantExecutionTarget>[
|
||||
...bridgeAvailableExecutionTargetsInternal,
|
||||
];
|
||||
if (assistantProviderCatalog.isNotEmpty &&
|
||||
!targets.contains(AssistantExecutionTarget.agent)) {
|
||||
targets.add(AssistantExecutionTarget.agent);
|
||||
}
|
||||
if (gatewayProviderCatalog.isNotEmpty &&
|
||||
!targets.contains(AssistantExecutionTarget.gateway)) {
|
||||
targets.add(AssistantExecutionTarget.gateway);
|
||||
}
|
||||
return compactAssistantExecutionTargets(targets);
|
||||
}
|
||||
|
||||
List<SingleAgentProvider> providerCatalogForExecutionTarget(
|
||||
AssistantExecutionTarget executionTarget,
|
||||
@ -665,15 +689,8 @@ class AppController extends ChangeNotifier {
|
||||
|
||||
void navigateHome() => AppControllerDesktopNavigation(this).navigateHome();
|
||||
|
||||
void openSettings({
|
||||
SettingsTab tab = SettingsTab.gateway,
|
||||
SettingsDetailPage? detail,
|
||||
SettingsNavigationContext? navigationContext,
|
||||
}) => AppControllerDesktopNavigation(this).openSettings(
|
||||
tab: tab,
|
||||
detail: detail,
|
||||
navigationContext: navigationContext,
|
||||
);
|
||||
void openSettings({SettingsTab tab = SettingsTab.gateway}) =>
|
||||
AppControllerDesktopNavigation(this).openSettings(tab: tab);
|
||||
|
||||
void openDetail(DetailPanelData detailPanel) =>
|
||||
AppControllerDesktopNavigation(this).openDetail(detailPanel);
|
||||
|
||||
@ -36,7 +36,6 @@ import '../runtime/account_runtime_client.dart';
|
||||
import 'app_controller_desktop_core.dart';
|
||||
import 'app_controller_desktop_navigation.dart';
|
||||
import 'app_controller_desktop_settings.dart';
|
||||
import 'app_controller_desktop_single_agent.dart';
|
||||
import 'app_controller_desktop_thread_binding.dart';
|
||||
import 'app_controller_desktop_thread_sessions.dart';
|
||||
import 'app_controller_desktop_thread_actions.dart';
|
||||
|
||||
@ -35,7 +35,6 @@ import '../runtime/skill_directory_access.dart';
|
||||
import 'app_controller_desktop_core.dart';
|
||||
import 'app_controller_desktop_gateway.dart';
|
||||
import 'app_controller_desktop_settings.dart';
|
||||
import 'app_controller_desktop_single_agent.dart';
|
||||
import 'app_controller_desktop_thread_sessions.dart';
|
||||
import 'app_controller_desktop_thread_actions.dart';
|
||||
import 'app_controller_desktop_workspace_execution.dart';
|
||||
@ -50,19 +49,12 @@ extension AppControllerDesktopNavigation on AppController {
|
||||
if (!capabilities.supportsDestination(destination)) {
|
||||
return;
|
||||
}
|
||||
final shouldClearSettingsDrillIn =
|
||||
settingsDetailInternal != null ||
|
||||
settingsNavigationContextInternal != null;
|
||||
final changed =
|
||||
destinationInternal != destination ||
|
||||
detailPanelInternal != null ||
|
||||
shouldClearSettingsDrillIn;
|
||||
destinationInternal != destination || detailPanelInternal != null;
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
destinationInternal = destination;
|
||||
settingsDetailInternal = null;
|
||||
settingsNavigationContextInternal = null;
|
||||
detailPanelInternal = null;
|
||||
notifyListeners();
|
||||
}
|
||||
@ -76,14 +68,9 @@ extension AppControllerDesktopNavigation on AppController {
|
||||
: capabilities.allowedDestinations.first);
|
||||
final destinationChanged = destinationInternal != homeDestination;
|
||||
final detailChanged = detailPanelInternal != null;
|
||||
final settingsDrillInChanged =
|
||||
settingsDetailInternal != null ||
|
||||
settingsNavigationContextInternal != null;
|
||||
destinationInternal = homeDestination;
|
||||
settingsDetailInternal = null;
|
||||
settingsNavigationContextInternal = null;
|
||||
detailPanelInternal = null;
|
||||
if (destinationChanged || detailChanged || settingsDrillInChanged) {
|
||||
if (destinationChanged || detailChanged) {
|
||||
notifyListeners();
|
||||
}
|
||||
if (!isAppOwnedAssistantSessionKeyInternal(currentSessionKey)) {
|
||||
@ -91,63 +78,31 @@ extension AppControllerDesktopNavigation on AppController {
|
||||
}
|
||||
}
|
||||
|
||||
void openSettings({
|
||||
SettingsTab tab = SettingsTab.gateway,
|
||||
SettingsDetailPage? detail,
|
||||
SettingsNavigationContext? navigationContext,
|
||||
}) {
|
||||
void openSettings({SettingsTab tab = SettingsTab.gateway}) {
|
||||
if (!capabilities.supportsDestination(WorkspaceDestination.settings)) {
|
||||
return;
|
||||
}
|
||||
final requestedTab = detail?.tab ?? tab;
|
||||
final resolvedTab = sanitizeSettingsTabInternal(requestedTab);
|
||||
final resolvedDetail = detail != null && resolvedTab == detail.tab
|
||||
? detail
|
||||
: null;
|
||||
final resolvedTab = sanitizeSettingsTabInternal(tab);
|
||||
final changed =
|
||||
destinationInternal != WorkspaceDestination.settings ||
|
||||
settingsTabInternal != resolvedTab ||
|
||||
settingsDetailInternal != resolvedDetail ||
|
||||
settingsNavigationContextInternal != navigationContext ||
|
||||
detailPanelInternal != null;
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
destinationInternal = WorkspaceDestination.settings;
|
||||
settingsTabInternal = resolvedTab;
|
||||
settingsDetailInternal = resolvedDetail;
|
||||
settingsNavigationContextInternal = resolvedDetail == null
|
||||
? null
|
||||
: navigationContext;
|
||||
detailPanelInternal = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void setSettingsTab(SettingsTab tab, {bool clearDetail = true}) {
|
||||
final resolvedTab = sanitizeSettingsTabInternal(tab);
|
||||
final changed =
|
||||
settingsTabInternal != resolvedTab ||
|
||||
(clearDetail &&
|
||||
(settingsDetailInternal != null ||
|
||||
settingsNavigationContextInternal != null));
|
||||
final changed = settingsTabInternal != resolvedTab;
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
settingsTabInternal = resolvedTab;
|
||||
if (clearDetail) {
|
||||
settingsDetailInternal = null;
|
||||
settingsNavigationContextInternal = null;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void closeSettingsDetail() {
|
||||
if (settingsDetailInternal == null &&
|
||||
settingsNavigationContextInternal == null) {
|
||||
return;
|
||||
}
|
||||
settingsDetailInternal = null;
|
||||
settingsNavigationContextInternal = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@ -40,7 +40,6 @@ import 'app_controller_desktop_core.dart';
|
||||
import 'app_controller_desktop_navigation.dart';
|
||||
import 'app_controller_desktop_gateway.dart';
|
||||
import 'app_controller_desktop_settings.dart';
|
||||
import 'app_controller_desktop_single_agent.dart';
|
||||
import 'app_controller_desktop_thread_sessions.dart';
|
||||
import 'app_controller_desktop_thread_actions.dart';
|
||||
import 'app_controller_desktop_workspace_execution.dart';
|
||||
|
||||
@ -36,7 +36,6 @@ import '../runtime/skill_directory_access.dart';
|
||||
import 'app_controller_desktop_core.dart';
|
||||
import 'app_controller_desktop_navigation.dart';
|
||||
import 'app_controller_desktop_gateway.dart';
|
||||
import 'app_controller_desktop_single_agent.dart';
|
||||
import 'app_controller_desktop_thread_sessions.dart';
|
||||
import 'app_controller_desktop_thread_actions.dart';
|
||||
import 'app_controller_desktop_workspace_execution.dart';
|
||||
|
||||
@ -39,7 +39,6 @@ import 'app_controller_desktop_navigation.dart';
|
||||
import 'app_controller_desktop_gateway.dart';
|
||||
import 'app_controller_desktop_settings.dart';
|
||||
import 'app_controller_desktop_thread_binding.dart';
|
||||
import 'app_controller_desktop_single_agent.dart';
|
||||
import 'app_controller_desktop_thread_sessions.dart';
|
||||
import 'app_controller_desktop_thread_actions.dart';
|
||||
import 'app_controller_desktop_workspace_execution.dart';
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
import 'app_controller_desktop_core.dart';
|
||||
|
||||
extension AppControllerDesktopSingleAgent on AppController {}
|
||||
@ -36,7 +36,6 @@ import 'app_controller_desktop_core.dart';
|
||||
import 'app_controller_desktop_navigation.dart';
|
||||
import 'app_controller_desktop_gateway.dart';
|
||||
import 'app_controller_desktop_settings.dart';
|
||||
import 'app_controller_desktop_single_agent.dart';
|
||||
import 'app_controller_desktop_thread_sessions.dart';
|
||||
import 'app_controller_desktop_thread_actions.dart';
|
||||
import 'app_controller_desktop_thread_binding.dart';
|
||||
|
||||
@ -36,7 +36,6 @@ import 'app_controller_desktop_core.dart';
|
||||
import 'app_controller_desktop_navigation.dart';
|
||||
import 'app_controller_desktop_gateway.dart';
|
||||
import 'app_controller_desktop_settings.dart';
|
||||
import 'app_controller_desktop_single_agent.dart';
|
||||
import 'app_controller_desktop_thread_binding.dart';
|
||||
import 'app_controller_desktop_thread_actions.dart';
|
||||
import 'app_controller_desktop_workspace_execution.dart';
|
||||
|
||||
@ -37,7 +37,6 @@ import 'app_controller_desktop_core.dart';
|
||||
import 'app_controller_desktop_navigation.dart';
|
||||
import 'app_controller_desktop_gateway.dart';
|
||||
import 'app_controller_desktop_settings.dart';
|
||||
import 'app_controller_desktop_single_agent.dart';
|
||||
import 'app_controller_desktop_thread_binding.dart';
|
||||
import 'app_controller_desktop_thread_sessions.dart';
|
||||
import 'app_controller_desktop_thread_actions.dart';
|
||||
|
||||
@ -36,7 +36,6 @@ import 'app_controller_desktop_core.dart';
|
||||
import 'app_controller_desktop_navigation.dart';
|
||||
import 'app_controller_desktop_gateway.dart';
|
||||
import 'app_controller_desktop_settings.dart';
|
||||
import 'app_controller_desktop_single_agent.dart';
|
||||
import 'app_controller_desktop_thread_sessions.dart';
|
||||
import 'app_controller_desktop_thread_actions.dart';
|
||||
import 'app_controller_desktop_workspace_execution.dart';
|
||||
|
||||
@ -87,6 +87,7 @@ extension AppControllerDesktopWorkspaceExecution on AppController {
|
||||
sessionsControllerInternal.currentSessionKey,
|
||||
)?.executionBinding.providerId,
|
||||
executionTarget: resolvedTarget,
|
||||
defaultToCatalog: resolvedTarget.isGateway,
|
||||
),
|
||||
selectedProviderSource: ThreadSelectionSource.explicit,
|
||||
gatewayEntryState: gatewayEntryStateForTargetInternal(resolvedTarget),
|
||||
|
||||
@ -48,11 +48,6 @@ abstract final class UiFeatureKeys {
|
||||
static const settingsGateway = 'settings.gateway';
|
||||
static const settingsAccountAccess = 'settings.account_access';
|
||||
static const settingsVaultServer = 'settings.vault_server';
|
||||
static const settingsGatewaySelfHostedBase =
|
||||
'settings.gateway_self_hosted_base';
|
||||
static const settingsGatewayAdvancedCustomMode =
|
||||
'settings.gateway_advanced_custom_mode';
|
||||
static const settingsGatewaySetupCode = 'settings.gateway_setup_code';
|
||||
static const settingsExperimentalCanvas = 'settings.experimental_canvas';
|
||||
static const settingsExperimentalBridge = 'settings.experimental_bridge';
|
||||
static const settingsExperimentalDebug = 'settings.experimental_debug';
|
||||
@ -423,18 +418,9 @@ class UiFeatureAccess {
|
||||
bool get supportsAccountAccess =>
|
||||
isEnabledPath(UiFeatureKeys.settingsAccountAccess);
|
||||
|
||||
bool get supportsGatewaySetupCode =>
|
||||
isEnabledPath(UiFeatureKeys.settingsGatewaySetupCode);
|
||||
|
||||
bool get supportsVaultServer =>
|
||||
isEnabledPath(UiFeatureKeys.settingsVaultServer);
|
||||
|
||||
bool get supportsGatewaySelfHostedBase =>
|
||||
isEnabledPath(UiFeatureKeys.settingsGatewaySelfHostedBase);
|
||||
|
||||
bool get supportsGatewayAdvancedCustomMode =>
|
||||
isEnabledPath(UiFeatureKeys.settingsGatewayAdvancedCustomMode);
|
||||
|
||||
List<SettingsTab> get availableSettingsTabs {
|
||||
return SettingsTab.values
|
||||
.where(
|
||||
|
||||
@ -32,36 +32,10 @@ List<AppBreadcrumbItem> buildWorkspaceBreadcrumbs({
|
||||
List<AppBreadcrumbItem> buildSettingsBreadcrumbs(
|
||||
AppController controller, {
|
||||
required SettingsTab tab,
|
||||
SettingsDetailPage? detail,
|
||||
SettingsNavigationContext? navigationContext,
|
||||
}) {
|
||||
if (detail == null) {
|
||||
return buildWorkspaceBreadcrumbs(
|
||||
controller: controller,
|
||||
rootLabel: appText('设置', 'Settings'),
|
||||
sectionLabel: tab.label,
|
||||
);
|
||||
}
|
||||
|
||||
return buildWorkspaceBreadcrumbs(
|
||||
controller: controller,
|
||||
rootLabel: navigationContext?.rootLabel ?? appText('设置', 'Settings'),
|
||||
sectionLabel: navigationContext?.sectionLabel ?? tab.label,
|
||||
detailLabel: detail.label,
|
||||
onRootTap: navigationContext == null
|
||||
? () => controller.openSettings(tab: tab)
|
||||
: () => openSettingsNavigationContext(controller, navigationContext),
|
||||
rootLabel: appText('设置', 'Settings'),
|
||||
sectionLabel: tab.label,
|
||||
);
|
||||
}
|
||||
|
||||
void openSettingsNavigationContext(
|
||||
AppController controller,
|
||||
SettingsNavigationContext context,
|
||||
) {
|
||||
if (context.settingsTab != null ||
|
||||
context.destination == WorkspaceDestination.settings) {
|
||||
controller.openSettings(tab: context.settingsTab ?? SettingsTab.gateway);
|
||||
return;
|
||||
}
|
||||
controller.navigateTo(context.destination);
|
||||
}
|
||||
|
||||
@ -25,37 +25,33 @@ class WorkspacePageSpec {
|
||||
final WorkspacePageBuilder mobileBuilder;
|
||||
}
|
||||
|
||||
final Map<WorkspaceDestination, WorkspacePageSpec>
|
||||
workspacePageSpecsInternal = <WorkspaceDestination, WorkspacePageSpec>{
|
||||
WorkspaceDestination.assistant: WorkspacePageSpec(
|
||||
destination: WorkspaceDestination.assistant,
|
||||
desktopBuilder: (controller, onOpenDetail) => AssistantPage(
|
||||
controller: controller,
|
||||
onOpenDetail: onOpenDetail,
|
||||
showStandaloneTaskRail: false,
|
||||
),
|
||||
mobileBuilder: (controller, onOpenDetail) => AssistantPage(
|
||||
controller: controller,
|
||||
onOpenDetail: onOpenDetail,
|
||||
showStandaloneTaskRail: false,
|
||||
),
|
||||
),
|
||||
WorkspaceDestination.settings: WorkspacePageSpec(
|
||||
destination: WorkspaceDestination.settings,
|
||||
desktopBuilder: (controller, onOpenDetail) => SettingsPage(
|
||||
controller: controller,
|
||||
initialTab: controller.settingsTab,
|
||||
initialDetail: controller.settingsDetail,
|
||||
navigationContext: controller.settingsNavigationContext,
|
||||
),
|
||||
mobileBuilder: (controller, onOpenDetail) => SettingsPage(
|
||||
controller: controller,
|
||||
initialTab: controller.settingsTab,
|
||||
initialDetail: controller.settingsDetail,
|
||||
navigationContext: controller.settingsNavigationContext,
|
||||
),
|
||||
),
|
||||
};
|
||||
final Map<WorkspaceDestination, WorkspacePageSpec> workspacePageSpecsInternal =
|
||||
<WorkspaceDestination, WorkspacePageSpec>{
|
||||
WorkspaceDestination.assistant: WorkspacePageSpec(
|
||||
destination: WorkspaceDestination.assistant,
|
||||
desktopBuilder: (controller, onOpenDetail) => AssistantPage(
|
||||
controller: controller,
|
||||
onOpenDetail: onOpenDetail,
|
||||
showStandaloneTaskRail: false,
|
||||
),
|
||||
mobileBuilder: (controller, onOpenDetail) => AssistantPage(
|
||||
controller: controller,
|
||||
onOpenDetail: onOpenDetail,
|
||||
showStandaloneTaskRail: false,
|
||||
),
|
||||
),
|
||||
WorkspaceDestination.settings: WorkspacePageSpec(
|
||||
destination: WorkspaceDestination.settings,
|
||||
desktopBuilder: (controller, onOpenDetail) => SettingsPage(
|
||||
controller: controller,
|
||||
initialTab: controller.settingsTab,
|
||||
),
|
||||
mobileBuilder: (controller, onOpenDetail) => SettingsPage(
|
||||
controller: controller,
|
||||
initialTab: controller.settingsTab,
|
||||
),
|
||||
),
|
||||
};
|
||||
|
||||
Widget buildWorkspacePage({
|
||||
required WorkspaceDestination destination,
|
||||
|
||||
@ -322,14 +322,7 @@ extension AssistantPageStateActionsInternal on AssistantPageStateInternal {
|
||||
}
|
||||
|
||||
void openGatewaySettingsInternal() {
|
||||
widget.controller.openSettings(
|
||||
detail: SettingsDetailPage.gatewayConnection,
|
||||
navigationContext: SettingsNavigationContext(
|
||||
rootLabel: appText('助手', 'Assistant'),
|
||||
destination: WorkspaceDestination.assistant,
|
||||
sectionLabel: appText('集成', 'Integrations'),
|
||||
),
|
||||
);
|
||||
widget.controller.openSettings(tab: SettingsTab.gateway);
|
||||
}
|
||||
|
||||
Future<void> connectFromSavedSettingsOrShowDialogInternal() async {
|
||||
|
||||
@ -47,6 +47,13 @@ class AssistantTaskDialogModeControlsInternal extends StatelessWidget {
|
||||
final providerMenuProviders = controller.providerCatalogForExecutionTarget(
|
||||
executionTarget,
|
||||
);
|
||||
final selectedProvider = controller.resolveProviderForExecutionTarget(
|
||||
controller
|
||||
.assistantProviderForSession(controller.currentSessionKey)
|
||||
.providerId,
|
||||
executionTarget: executionTarget,
|
||||
defaultToCatalog: executionTarget.isGateway,
|
||||
);
|
||||
|
||||
return Wrap(
|
||||
spacing: 4,
|
||||
@ -61,9 +68,7 @@ class AssistantTaskDialogModeControlsInternal extends StatelessWidget {
|
||||
),
|
||||
_TaskDialogProviderMenuButtonInternal(
|
||||
controller: controller,
|
||||
selectedProvider: controller.assistantProviderForSession(
|
||||
controller.currentSessionKey,
|
||||
),
|
||||
selectedProvider: selectedProvider,
|
||||
providers: providerMenuProviders,
|
||||
),
|
||||
],
|
||||
@ -187,7 +192,11 @@ class _TaskDialogProviderMenuButtonInternal extends StatelessWidget {
|
||||
key: const Key('assistant-provider-badge'),
|
||||
provider: selectedProvider,
|
||||
)
|
||||
: Icon(Icons.hub_outlined, size: 14, color: context.palette.textMuted),
|
||||
: Icon(
|
||||
Icons.hub_outlined,
|
||||
size: 14,
|
||||
color: context.palette.textMuted,
|
||||
),
|
||||
label: label,
|
||||
tooltip: appText('智能体 Provider', 'Agent Provider'),
|
||||
),
|
||||
|
||||
@ -312,25 +312,14 @@ String sessionDisplayTitleInternal(GatewaySessionSummary session) {
|
||||
if (label.isEmpty || label == session.key) {
|
||||
return fallbackSessionTitleInternal(session.key);
|
||||
}
|
||||
if ((label == 'main' || label == 'agent:main:main') &&
|
||||
(session.derivedTitle ?? '').trim().toLowerCase() == 'main') {
|
||||
return fallbackSessionTitleInternal(session.key);
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
String fallbackSessionTitleInternal(String sessionKey) {
|
||||
final trimmed = sessionKey.trim();
|
||||
if (trimmed == 'main' || trimmed == 'agent:main:main') {
|
||||
return appText('默认任务', 'Default task');
|
||||
}
|
||||
if (trimmed.startsWith('draft:')) {
|
||||
return appText('新对话', 'New conversation');
|
||||
}
|
||||
final parts = trimmed.split(':');
|
||||
if (parts.length >= 3 && parts.first == 'agent' && parts.last == 'main') {
|
||||
return appText('默认任务', 'Default task');
|
||||
}
|
||||
return trimmed.isEmpty ? appText('未命名对话', 'Untitled conversation') : trimmed;
|
||||
}
|
||||
|
||||
@ -405,9 +394,5 @@ double estimatedComposerWrapSectionHeightInternal({
|
||||
bool sessionKeysMatchInternal(String incoming, String current) {
|
||||
final left = incoming.trim().toLowerCase();
|
||||
final right = current.trim().toLowerCase();
|
||||
if (left == right) {
|
||||
return true;
|
||||
}
|
||||
return (left == 'agent:main:main' && right == 'main') ||
|
||||
(left == 'main' && right == 'agent:main:main');
|
||||
return left == right;
|
||||
}
|
||||
|
||||
@ -73,46 +73,18 @@ class MobileShellStateInternal extends State<MobileShell> {
|
||||
}
|
||||
|
||||
void showConnectSheetInternal() {
|
||||
widget.controller.openSettings(
|
||||
detail: SettingsDetailPage.gatewayConnection,
|
||||
navigationContext: SettingsNavigationContext(
|
||||
rootLabel: appText('移动端', 'Mobile'),
|
||||
destination: WorkspaceDestination.settings,
|
||||
sectionLabel: appText('集成', 'Integrations'),
|
||||
settingsTab: SettingsTab.gateway,
|
||||
gatewayProfileIndex: kGatewayRemoteProfileIndex,
|
||||
prefersGatewaySetupCode: false,
|
||||
),
|
||||
);
|
||||
widget.controller.openSettings(tab: SettingsTab.gateway);
|
||||
}
|
||||
|
||||
Future<void> openGatewaySetupCodeEntryInternal({
|
||||
String? prefilledSetupCode,
|
||||
}) async {
|
||||
final setupCode = prefilledSetupCode?.trim() ?? '';
|
||||
if (setupCode.isNotEmpty) {
|
||||
final current = widget
|
||||
.controller
|
||||
.settingsDraft
|
||||
.gatewayProfiles[kGatewayRemoteProfileIndex];
|
||||
await widget.controller.saveSettingsDraft(
|
||||
widget.controller.settingsDraft.copyWithGatewayProfileAt(
|
||||
kGatewayRemoteProfileIndex,
|
||||
current.copyWith(useSetupCode: true, setupCode: setupCode),
|
||||
),
|
||||
);
|
||||
if (setupCode.isEmpty) {
|
||||
await promptBridgeVerificationCodeInternal();
|
||||
return;
|
||||
}
|
||||
widget.controller.openSettings(
|
||||
detail: SettingsDetailPage.gatewayConnection,
|
||||
navigationContext: SettingsNavigationContext(
|
||||
rootLabel: appText('移动端', 'Mobile'),
|
||||
destination: WorkspaceDestination.settings,
|
||||
sectionLabel: appText('集成', 'Integrations'),
|
||||
settingsTab: SettingsTab.gateway,
|
||||
gatewayProfileIndex: kGatewayRemoteProfileIndex,
|
||||
prefersGatewaySetupCode: true,
|
||||
),
|
||||
);
|
||||
await widget.controller.connectWithSetupCode(setupCode: setupCode);
|
||||
}
|
||||
|
||||
Future<void> connectWithScannedSetupCodeInternal(String setupCode) async {
|
||||
@ -134,10 +106,6 @@ class MobileShellStateInternal extends State<MobileShell> {
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
await openGatewaySetupCodeEntryInternal(prefilledSetupCode: setupCode);
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
@ -146,8 +114,8 @@ class MobileShellStateInternal extends State<MobileShell> {
|
||||
SnackBar(
|
||||
content: Text(
|
||||
appText(
|
||||
'扫码成功,但自动连接失败。已为你填入配置码,请检查后重试。\n$message',
|
||||
'QR captured, but automatic connect failed. The setup code has been prefilled for review.\n$message',
|
||||
'扫码成功,但自动连接失败。请重新输入配置码或检查 Bridge 状态。\n$message',
|
||||
'QR captured, but automatic connect failed. Re-enter the setup code or check Bridge status.\n$message',
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -204,7 +172,8 @@ class MobileShellStateInternal extends State<MobileShell> {
|
||||
fullscreenDialog: true,
|
||||
builder: (_) => MobileGatewayPairingGuidePage(
|
||||
supportsQrScan: supportsQrScan,
|
||||
onManualInput: () => unawaited(openGatewaySetupCodeEntryInternal()),
|
||||
onManualInput: () =>
|
||||
unawaited(promptBridgeVerificationCodeInternal()),
|
||||
onManualCodeInput: () =>
|
||||
unawaited(promptBridgeVerificationCodeInternal()),
|
||||
onScannedSetupCode: (setupCode) async {
|
||||
|
||||
@ -53,7 +53,8 @@ class SettingsAccountPanel extends StatelessWidget {
|
||||
if (!accountSignedIn && !accountMfaRequired) {
|
||||
return DefaultTabController(
|
||||
length: 2,
|
||||
initialIndex: settings.acpBridgeServerModeConfig.effective.source == 'bridge'
|
||||
initialIndex:
|
||||
settings.acpBridgeServerModeConfig.effective.source == 'bridge'
|
||||
? 1
|
||||
: 0,
|
||||
child: Column(
|
||||
@ -466,14 +467,18 @@ class _SignedInAccountPanel extends StatelessWidget {
|
||||
? accountState!.syncMessage.trim()
|
||||
: appText('尚未同步远端配置', 'Remote config not synced yet');
|
||||
final modeStateLabel = accountBusy
|
||||
? (isAccountSyncMode ? appText('同步中', 'Syncing') : appText('保存中', 'Saving'))
|
||||
? (isAccountSyncMode
|
||||
? appText('同步中', 'Syncing')
|
||||
: appText('保存中', 'Saving'))
|
||||
: (isAccountSyncMode
|
||||
? _describeAccountSyncState(syncState)
|
||||
: _describeBridgeSaveState(settings));
|
||||
final modeStatusLabel = accountBusy && accountStatus.trim().isNotEmpty
|
||||
? accountStatus.trim()
|
||||
: syncMessage;
|
||||
final modeIcon = isAccountSyncMode ? Icons.cloud_outlined : Icons.link_outlined;
|
||||
final modeIcon = isAccountSyncMode
|
||||
? Icons.cloud_outlined
|
||||
: Icons.link_outlined;
|
||||
final modeTitle = isAccountSyncMode
|
||||
? appText('账号同步', 'Account Sync')
|
||||
: appText('手动 Bridge', 'Manual Bridge');
|
||||
@ -541,9 +546,14 @@ class _SignedInAccountPanel extends StatelessWidget {
|
||||
accountSession?.email.trim().isNotEmpty == true
|
||||
? accountSession!.email.trim()
|
||||
: appText('当前账号', 'Current account'),
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Theme.of(context).textTheme.bodySmall?.color?.withValues(alpha: 0.78),
|
||||
),
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall
|
||||
?.color
|
||||
?.withValues(alpha: 0.78),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -596,7 +606,9 @@ class _SignedInAccountPanel extends StatelessWidget {
|
||||
? '${appText('同步说明', 'Sync Summary')}: $modeStatusLabel'
|
||||
: '${appText('保存说明', 'Save Summary')}: $modeStatusLabel',
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Theme.of(context).textTheme.bodySmall?.color?.withValues(alpha: 0.78),
|
||||
color: Theme.of(
|
||||
context,
|
||||
).textTheme.bodySmall?.color?.withValues(alpha: 0.78),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
@ -610,7 +622,10 @@ class _SignedInAccountPanel extends StatelessWidget {
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
),
|
||||
subtitle: Text(
|
||||
appText('查看服务地址、令牌与远端摘要', 'View service URL, tokens, and remote summary'),
|
||||
appText(
|
||||
'查看服务地址、令牌与远端摘要',
|
||||
'View service URL, tokens, and remote summary',
|
||||
),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
children: [
|
||||
@ -760,8 +775,6 @@ class _TokenConfiguredSummary extends StatelessWidget {
|
||||
final configured = <String>[
|
||||
if (accountState?.tokenConfigured.bridge == true)
|
||||
appText('Bridge Token', 'Bridge Token'),
|
||||
if (accountState?.tokenConfigured.apisix == true)
|
||||
appText('AI Gateway Token', 'AI Gateway Token'),
|
||||
if (accountState?.tokenConfigured.vault == true) 'Vault Token',
|
||||
];
|
||||
final summary = configured.isEmpty
|
||||
|
||||
@ -111,14 +111,10 @@ class SettingsPage extends StatefulWidget {
|
||||
super.key,
|
||||
required this.controller,
|
||||
this.initialTab = SettingsTab.gateway,
|
||||
this.initialDetail,
|
||||
this.navigationContext,
|
||||
});
|
||||
|
||||
final AppController controller;
|
||||
final SettingsTab initialTab;
|
||||
final SettingsDetailPage? initialDetail;
|
||||
final SettingsNavigationContext? navigationContext;
|
||||
|
||||
@override
|
||||
State<SettingsPage> createState() => _SettingsPageState();
|
||||
@ -378,8 +374,6 @@ class _SettingsPageState extends State<SettingsPage> {
|
||||
breadcrumbs: buildSettingsBreadcrumbs(
|
||||
controller,
|
||||
tab: SettingsTab.gateway,
|
||||
detail: null,
|
||||
navigationContext: null,
|
||||
),
|
||||
title: appText('设置', 'Settings'),
|
||||
subtitle: appText(
|
||||
|
||||
@ -2,10 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import '../i18n/app_language.dart';
|
||||
|
||||
enum WorkspaceDestination {
|
||||
assistant,
|
||||
settings,
|
||||
}
|
||||
enum WorkspaceDestination { assistant, settings }
|
||||
|
||||
extension WorkspaceDestinationCopy on WorkspaceDestination {
|
||||
String get label => switch (this) {
|
||||
@ -42,11 +39,7 @@ extension WorkspaceDestinationCopy on WorkspaceDestination {
|
||||
}
|
||||
}
|
||||
|
||||
enum AssistantFocusEntry {
|
||||
settings,
|
||||
language,
|
||||
theme,
|
||||
}
|
||||
enum AssistantFocusEntry { settings, language, theme }
|
||||
|
||||
extension AssistantFocusEntryCopy on AssistantFocusEntry {
|
||||
String get label => switch (this) {
|
||||
@ -164,40 +157,6 @@ extension SettingsTabCopy on SettingsTab {
|
||||
};
|
||||
}
|
||||
|
||||
enum SettingsDetailPage { gatewayConnection }
|
||||
|
||||
extension SettingsDetailPageCopy on SettingsDetailPage {
|
||||
String get label => switch (this) {
|
||||
SettingsDetailPage.gatewayConnection => appText(
|
||||
'Gateway 连接参数',
|
||||
'Gateway Connection',
|
||||
),
|
||||
};
|
||||
|
||||
SettingsTab get tab => switch (this) {
|
||||
SettingsDetailPage.gatewayConnection => SettingsTab.gateway,
|
||||
};
|
||||
}
|
||||
|
||||
@immutable
|
||||
class SettingsNavigationContext {
|
||||
const SettingsNavigationContext({
|
||||
required this.rootLabel,
|
||||
required this.destination,
|
||||
this.sectionLabel,
|
||||
this.settingsTab,
|
||||
this.gatewayProfileIndex,
|
||||
this.prefersGatewaySetupCode,
|
||||
});
|
||||
|
||||
final String rootLabel;
|
||||
final WorkspaceDestination destination;
|
||||
final String? sectionLabel;
|
||||
final SettingsTab? settingsTab;
|
||||
final int? gatewayProfileIndex;
|
||||
final bool? prefersGatewaySetupCode;
|
||||
}
|
||||
|
||||
class QuickAction {
|
||||
const QuickAction({
|
||||
required this.title,
|
||||
|
||||
@ -1,15 +1,7 @@
|
||||
// ignore_for_file: unused_import, unnecessary_import
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'gateway_runtime.dart';
|
||||
import 'runtime_models.dart';
|
||||
import 'secure_config_store.dart';
|
||||
import 'runtime_controllers_settings.dart';
|
||||
import 'runtime_controllers_gateway.dart';
|
||||
import 'runtime_controllers_entities.dart';
|
||||
|
||||
class DerivedTasksController extends ChangeNotifier {
|
||||
List<DerivedTaskItem> queueInternal = const <DerivedTaskItem>[];
|
||||
@ -150,11 +142,7 @@ class DerivedTasksController extends ChangeNotifier {
|
||||
bool matchesSessionKey(String incoming, String current) {
|
||||
final left = incoming.trim().toLowerCase();
|
||||
final right = current.trim().toLowerCase();
|
||||
if (left == right) {
|
||||
return true;
|
||||
}
|
||||
return (left == 'agent:main:main' && right == 'main') ||
|
||||
(left == 'main' && right == 'agent:main:main');
|
||||
return left == right;
|
||||
}
|
||||
|
||||
String encodePrettyJson(Object value) {
|
||||
|
||||
@ -302,11 +302,7 @@ Future<AccountSyncResult> syncAccountSettingsInternal(
|
||||
lastSyncSource: syncedBridgeServerUrl,
|
||||
lastSyncError: '',
|
||||
profileScope: 'bridge',
|
||||
tokenConfigured: const AccountTokenConfigured(
|
||||
bridge: true,
|
||||
vault: false,
|
||||
apisix: false,
|
||||
),
|
||||
tokenConfigured: const AccountTokenConfigured(bridge: true, vault: false),
|
||||
);
|
||||
await _persistAccountSyncStateInternal(controller, nextState);
|
||||
final currentSettings = controller.snapshotInternal;
|
||||
@ -334,10 +330,7 @@ Future<AccountSyncResult> syncAccountSettingsInternal(
|
||||
: currentModeConfig.cloudSynced.accountIdentifier,
|
||||
lastSyncAt: nextState.lastSyncAtMs,
|
||||
remoteServerSummary: currentModeConfig.cloudSynced.remoteServerSummary
|
||||
.copyWith(
|
||||
endpoint: syncedBridgeServerUrl,
|
||||
hasAdvancedOverrides: false,
|
||||
),
|
||||
.copyWith(endpoint: syncedBridgeServerUrl),
|
||||
),
|
||||
);
|
||||
final sanitizedSettings = _sanitizeBridgeOnlyAccountSyncSettings(
|
||||
@ -413,7 +406,7 @@ Future<void> logoutAccountSettingsInternal(
|
||||
.acpBridgeServerModeConfig
|
||||
.cloudSynced
|
||||
.remoteServerSummary
|
||||
.copyWith(endpoint: '', hasAdvancedOverrides: false),
|
||||
.copyWith(endpoint: ''),
|
||||
);
|
||||
await controller.saveSnapshot(
|
||||
currentSnapshot.copyWith(
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import 'dart:convert';
|
||||
import 'runtime_models_configs.dart';
|
||||
import 'runtime_models_profiles.dart';
|
||||
|
||||
class AccountSessionSummary {
|
||||
const AccountSessionSummary({
|
||||
@ -67,41 +65,30 @@ class AccountSessionSummary {
|
||||
}
|
||||
|
||||
class AccountTokenConfigured {
|
||||
const AccountTokenConfigured({
|
||||
required this.bridge,
|
||||
required this.vault,
|
||||
required this.apisix,
|
||||
});
|
||||
const AccountTokenConfigured({required this.bridge, required this.vault});
|
||||
|
||||
final bool bridge;
|
||||
final bool vault;
|
||||
final bool apisix;
|
||||
|
||||
factory AccountTokenConfigured.defaults() {
|
||||
return const AccountTokenConfigured(
|
||||
bridge: false,
|
||||
vault: false,
|
||||
apisix: false,
|
||||
);
|
||||
return const AccountTokenConfigured(bridge: false, vault: false);
|
||||
}
|
||||
|
||||
AccountTokenConfigured copyWith({bool? bridge, bool? vault, bool? apisix}) {
|
||||
AccountTokenConfigured copyWith({bool? bridge, bool? vault}) {
|
||||
return AccountTokenConfigured(
|
||||
bridge: bridge ?? this.bridge,
|
||||
vault: vault ?? this.vault,
|
||||
apisix: apisix ?? this.apisix,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'bridge': bridge, 'vault': vault, 'apisix': apisix};
|
||||
return {'bridge': bridge, 'vault': vault};
|
||||
}
|
||||
|
||||
factory AccountTokenConfigured.fromJson(Map<String, dynamic> json) {
|
||||
return AccountTokenConfigured(
|
||||
bridge: json['bridge'] as bool? ?? false,
|
||||
vault: json['vault'] as bool? ?? false,
|
||||
apisix: json['apisix'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -170,7 +157,6 @@ class AccountRemoteProfile {
|
||||
required this.bridgeServerOrigin,
|
||||
required this.vaultUrl,
|
||||
required this.vaultNamespace,
|
||||
required this.apisixUrl,
|
||||
required this.secretLocators,
|
||||
});
|
||||
|
||||
@ -178,7 +164,6 @@ class AccountRemoteProfile {
|
||||
final String bridgeServerOrigin;
|
||||
final String vaultUrl;
|
||||
final String vaultNamespace;
|
||||
final String apisixUrl;
|
||||
final List<AccountSecretLocator> secretLocators;
|
||||
|
||||
factory AccountRemoteProfile.defaults() {
|
||||
@ -187,7 +172,6 @@ class AccountRemoteProfile {
|
||||
bridgeServerOrigin: '',
|
||||
vaultUrl: '',
|
||||
vaultNamespace: '',
|
||||
apisixUrl: '',
|
||||
secretLocators: <AccountSecretLocator>[],
|
||||
);
|
||||
}
|
||||
@ -197,7 +181,6 @@ class AccountRemoteProfile {
|
||||
String? bridgeServerOrigin,
|
||||
String? vaultUrl,
|
||||
String? vaultNamespace,
|
||||
String? apisixUrl,
|
||||
List<AccountSecretLocator>? secretLocators,
|
||||
}) {
|
||||
return AccountRemoteProfile(
|
||||
@ -205,7 +188,6 @@ class AccountRemoteProfile {
|
||||
bridgeServerOrigin: bridgeServerOrigin ?? this.bridgeServerOrigin,
|
||||
vaultUrl: vaultUrl ?? this.vaultUrl,
|
||||
vaultNamespace: vaultNamespace ?? this.vaultNamespace,
|
||||
apisixUrl: apisixUrl ?? this.apisixUrl,
|
||||
secretLocators: secretLocators ?? this.secretLocators,
|
||||
);
|
||||
}
|
||||
@ -216,7 +198,6 @@ class AccountRemoteProfile {
|
||||
'bridgeServerOrigin': bridgeServerOrigin,
|
||||
'vaultUrl': vaultUrl,
|
||||
'vaultNamespace': vaultNamespace,
|
||||
'apisixUrl': apisixUrl,
|
||||
'secretLocators': secretLocators
|
||||
.map((item) => item.toJson())
|
||||
.toList(growable: false),
|
||||
@ -246,7 +227,6 @@ class AccountRemoteProfile {
|
||||
vaultUrl: json['vaultUrl'] as String? ?? defaults.vaultUrl,
|
||||
vaultNamespace:
|
||||
json['vaultNamespace'] as String? ?? defaults.vaultNamespace,
|
||||
apisixUrl: json['apisixUrl'] as String? ?? defaults.apisixUrl,
|
||||
secretLocators: decodeLocators(json['secretLocators']),
|
||||
);
|
||||
}
|
||||
@ -266,36 +246,22 @@ class AccountRemoteProfile {
|
||||
}
|
||||
|
||||
class AcpBridgeServerRemoteServerSummary {
|
||||
const AcpBridgeServerRemoteServerSummary({
|
||||
required this.endpoint,
|
||||
required this.hasAdvancedOverrides,
|
||||
});
|
||||
const AcpBridgeServerRemoteServerSummary({required this.endpoint});
|
||||
|
||||
final String endpoint;
|
||||
final bool hasAdvancedOverrides;
|
||||
|
||||
factory AcpBridgeServerRemoteServerSummary.defaults() {
|
||||
return const AcpBridgeServerRemoteServerSummary(
|
||||
endpoint: '',
|
||||
hasAdvancedOverrides: false,
|
||||
);
|
||||
return const AcpBridgeServerRemoteServerSummary(endpoint: '');
|
||||
}
|
||||
|
||||
AcpBridgeServerRemoteServerSummary copyWith({
|
||||
String? endpoint,
|
||||
bool? hasAdvancedOverrides,
|
||||
}) {
|
||||
AcpBridgeServerRemoteServerSummary copyWith({String? endpoint}) {
|
||||
return AcpBridgeServerRemoteServerSummary(
|
||||
endpoint: endpoint ?? this.endpoint,
|
||||
hasAdvancedOverrides: hasAdvancedOverrides ?? this.hasAdvancedOverrides,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return <String, dynamic>{
|
||||
'endpoint': endpoint,
|
||||
'hasAdvancedOverrides': hasAdvancedOverrides,
|
||||
};
|
||||
return <String, dynamic>{'endpoint': endpoint};
|
||||
}
|
||||
|
||||
factory AcpBridgeServerRemoteServerSummary.fromJson(
|
||||
@ -303,7 +269,6 @@ class AcpBridgeServerRemoteServerSummary {
|
||||
) {
|
||||
return AcpBridgeServerRemoteServerSummary(
|
||||
endpoint: json['endpoint'] as String? ?? '',
|
||||
hasAdvancedOverrides: json['hasAdvancedOverrides'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -419,92 +384,6 @@ class AcpBridgeServerSelfHostedConfig {
|
||||
}
|
||||
}
|
||||
|
||||
class AcpBridgeServerAdvancedOverrides {
|
||||
const AcpBridgeServerAdvancedOverrides({
|
||||
required this.gatewayProfiles,
|
||||
required this.vault,
|
||||
required this.aiGateway,
|
||||
required this.authorizedSkillDirectories,
|
||||
});
|
||||
|
||||
final List<GatewayConnectionProfile> gatewayProfiles;
|
||||
final VaultConfig vault;
|
||||
final AiGatewayProfile aiGateway;
|
||||
final List<AuthorizedSkillDirectory> authorizedSkillDirectories;
|
||||
|
||||
factory AcpBridgeServerAdvancedOverrides.defaults() {
|
||||
return AcpBridgeServerAdvancedOverrides(
|
||||
gatewayProfiles: normalizeGatewayProfiles(),
|
||||
vault: VaultConfig.defaults(),
|
||||
aiGateway: AiGatewayProfile.defaults(),
|
||||
authorizedSkillDirectories: normalizeAuthorizedSkillDirectories(),
|
||||
);
|
||||
}
|
||||
|
||||
AcpBridgeServerAdvancedOverrides copyWith({
|
||||
List<GatewayConnectionProfile>? gatewayProfiles,
|
||||
VaultConfig? vault,
|
||||
AiGatewayProfile? aiGateway,
|
||||
List<AuthorizedSkillDirectory>? authorizedSkillDirectories,
|
||||
}) {
|
||||
return AcpBridgeServerAdvancedOverrides(
|
||||
gatewayProfiles: gatewayProfiles != null
|
||||
? normalizeGatewayProfiles(profiles: gatewayProfiles)
|
||||
: this.gatewayProfiles,
|
||||
vault: vault ?? this.vault,
|
||||
aiGateway: aiGateway ?? this.aiGateway,
|
||||
authorizedSkillDirectories: authorizedSkillDirectories != null
|
||||
? normalizeAuthorizedSkillDirectories(
|
||||
directories: authorizedSkillDirectories,
|
||||
)
|
||||
: this.authorizedSkillDirectories,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return <String, dynamic>{
|
||||
'gatewayProfiles': gatewayProfiles
|
||||
.map((item) => item.toJson())
|
||||
.toList(growable: false),
|
||||
'vault': vault.toJson(),
|
||||
'aiGateway': aiGateway.toJson(),
|
||||
'authorizedSkillDirectories': authorizedSkillDirectories
|
||||
.map((item) => item.toJson())
|
||||
.toList(growable: false),
|
||||
};
|
||||
}
|
||||
|
||||
factory AcpBridgeServerAdvancedOverrides.fromJson(Map<String, dynamic> json) {
|
||||
return AcpBridgeServerAdvancedOverrides(
|
||||
gatewayProfiles: normalizeGatewayProfiles(
|
||||
profiles: ((json['gatewayProfiles'] as List?) ?? const <Object>[])
|
||||
.whereType<Map>()
|
||||
.map(
|
||||
(item) => GatewayConnectionProfile.fromJson(
|
||||
item.cast<String, dynamic>(),
|
||||
),
|
||||
),
|
||||
),
|
||||
vault: VaultConfig.fromJson(
|
||||
(json['vault'] as Map?)?.cast<String, dynamic>() ?? const {},
|
||||
),
|
||||
aiGateway: AiGatewayProfile.fromJson(
|
||||
(json['aiGateway'] as Map?)?.cast<String, dynamic>() ?? const {},
|
||||
),
|
||||
authorizedSkillDirectories: normalizeAuthorizedSkillDirectories(
|
||||
directories:
|
||||
((json['authorizedSkillDirectories'] as List?) ?? const <Object>[])
|
||||
.whereType<Map>()
|
||||
.map(
|
||||
(item) => AuthorizedSkillDirectory.fromJson(
|
||||
item.cast<String, dynamic>(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AcpBridgeServerEffectiveConfig {
|
||||
const AcpBridgeServerEffectiveConfig({
|
||||
required this.endpoint,
|
||||
@ -565,20 +444,17 @@ class AcpBridgeServerModeConfig {
|
||||
required this.effective,
|
||||
required this.cloudSynced,
|
||||
required this.selfHosted,
|
||||
required this.advancedOverrides,
|
||||
});
|
||||
|
||||
final AcpBridgeServerEffectiveConfig effective;
|
||||
final AcpBridgeServerCloudSyncConfig cloudSynced;
|
||||
final AcpBridgeServerSelfHostedConfig selfHosted;
|
||||
final AcpBridgeServerAdvancedOverrides advancedOverrides;
|
||||
|
||||
factory AcpBridgeServerModeConfig.defaults() {
|
||||
return AcpBridgeServerModeConfig(
|
||||
effective: AcpBridgeServerEffectiveConfig.defaults(),
|
||||
cloudSynced: AcpBridgeServerCloudSyncConfig.defaults(),
|
||||
selfHosted: AcpBridgeServerSelfHostedConfig.defaults(),
|
||||
advancedOverrides: AcpBridgeServerAdvancedOverrides.defaults(),
|
||||
);
|
||||
}
|
||||
|
||||
@ -586,22 +462,14 @@ class AcpBridgeServerModeConfig {
|
||||
AcpBridgeServerEffectiveConfig? effective,
|
||||
AcpBridgeServerCloudSyncConfig? cloudSynced,
|
||||
AcpBridgeServerSelfHostedConfig? selfHosted,
|
||||
AcpBridgeServerAdvancedOverrides? advancedOverrides,
|
||||
}) {
|
||||
return AcpBridgeServerModeConfig(
|
||||
effective: effective ?? this.effective,
|
||||
cloudSynced: cloudSynced ?? this.cloudSynced,
|
||||
selfHosted: selfHosted ?? this.selfHosted,
|
||||
advancedOverrides: advancedOverrides ?? this.advancedOverrides,
|
||||
);
|
||||
}
|
||||
|
||||
bool get usesSelfHostedBase => effective.source == 'bridge';
|
||||
|
||||
bool get usesCloudSyncBase => !usesSelfHostedBase;
|
||||
|
||||
String get sourceTag => effective.source;
|
||||
|
||||
String toJsonString() => jsonEncode(toJson());
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
@ -609,7 +477,6 @@ class AcpBridgeServerModeConfig {
|
||||
'effective': effective.toJson(),
|
||||
'cloudSynced': cloudSynced.toJson(),
|
||||
'selfHosted': selfHosted.toJson(),
|
||||
'advancedOverrides': advancedOverrides.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -624,10 +491,6 @@ class AcpBridgeServerModeConfig {
|
||||
selfHosted: AcpBridgeServerSelfHostedConfig.fromJson(
|
||||
(json['selfHosted'] as Map?)?.cast<String, dynamic>() ?? const {},
|
||||
),
|
||||
advancedOverrides: AcpBridgeServerAdvancedOverrides.fromJson(
|
||||
(json['advancedOverrides'] as Map?)?.cast<String, dynamic>() ??
|
||||
const {},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,20 +51,6 @@ class GatewayConnectionProfile {
|
||||
);
|
||||
}
|
||||
|
||||
factory GatewayConnectionProfile.emptySlot({required int index}) {
|
||||
return GatewayConnectionProfile(
|
||||
mode: RuntimeConnectionMode.unconfigured,
|
||||
useSetupCode: false,
|
||||
setupCode: '',
|
||||
host: '',
|
||||
port: 443,
|
||||
tls: true,
|
||||
tokenRef: 'gateway_token_$index',
|
||||
passwordRef: 'gateway_password_$index',
|
||||
selectedAgentId: '',
|
||||
);
|
||||
}
|
||||
|
||||
GatewayConnectionProfile copyWith({
|
||||
RuntimeConnectionMode? mode,
|
||||
bool? useSetupCode,
|
||||
@ -129,81 +115,43 @@ class GatewayConnectionProfile {
|
||||
}
|
||||
}
|
||||
|
||||
const int kGatewayProfileListLength = 4;
|
||||
const int kGatewayProfileListLength = 1;
|
||||
const int kGatewayRemoteProfileIndex = 0;
|
||||
const int kGatewayCustomProfileStartIndex = 1;
|
||||
|
||||
List<GatewayConnectionProfile> normalizeGatewayProfiles({
|
||||
Iterable<GatewayConnectionProfile>? profiles,
|
||||
}) {
|
||||
final defaults = List<GatewayConnectionProfile>.generate(
|
||||
kGatewayProfileListLength,
|
||||
(index) => switch (index) {
|
||||
kGatewayRemoteProfileIndex => GatewayConnectionProfile.defaultsGateway(),
|
||||
_ => GatewayConnectionProfile.emptySlot(index: index),
|
||||
},
|
||||
growable: false,
|
||||
);
|
||||
final fallback = GatewayConnectionProfile.defaultsGateway();
|
||||
final incoming =
|
||||
profiles?.toList(growable: false) ?? const <GatewayConnectionProfile>[];
|
||||
final normalized = <GatewayConnectionProfile>[];
|
||||
for (var index = 0; index < kGatewayProfileListLength; index += 1) {
|
||||
final fallback = defaults[index];
|
||||
final current = index < incoming.length ? incoming[index] : fallback;
|
||||
if (index == kGatewayRemoteProfileIndex) {
|
||||
final hasEndpoint =
|
||||
current.host.trim().isNotEmpty &&
|
||||
current.port > 0 &&
|
||||
!_isGatewayLoopbackHost(current.host);
|
||||
final slotMode = switch (current.mode) {
|
||||
RuntimeConnectionMode.remote => RuntimeConnectionMode.remote,
|
||||
RuntimeConnectionMode.unconfigured =>
|
||||
hasEndpoint
|
||||
? RuntimeConnectionMode.remote
|
||||
: RuntimeConnectionMode.unconfigured,
|
||||
};
|
||||
normalized.add(
|
||||
current.copyWith(
|
||||
mode: slotMode,
|
||||
useSetupCode: current.useSetupCode,
|
||||
setupCode: current.setupCode,
|
||||
host: hasEndpoint ? current.host : fallback.host,
|
||||
port: current.port > 0 ? current.port : fallback.port,
|
||||
tls: hasEndpoint ? current.tls : fallback.tls,
|
||||
tokenRef: current.tokenRef.trim().isEmpty
|
||||
? fallback.tokenRef
|
||||
: current.tokenRef,
|
||||
passwordRef: current.passwordRef.trim().isEmpty
|
||||
? fallback.passwordRef
|
||||
: current.passwordRef,
|
||||
),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
final slotMode = switch (current.mode) {
|
||||
RuntimeConnectionMode.remote => RuntimeConnectionMode.remote,
|
||||
RuntimeConnectionMode.unconfigured =>
|
||||
current.host.trim().isNotEmpty && !_isGatewayLoopbackHost(current.host)
|
||||
? RuntimeConnectionMode.remote
|
||||
: RuntimeConnectionMode.unconfigured,
|
||||
};
|
||||
normalized.add(
|
||||
current.copyWith(
|
||||
mode: slotMode,
|
||||
useSetupCode: current.useSetupCode,
|
||||
setupCode: current.setupCode,
|
||||
port: current.port > 0 ? current.port : 443,
|
||||
tls: current.tls,
|
||||
tokenRef: current.tokenRef.trim().isEmpty
|
||||
? fallback.tokenRef
|
||||
: current.tokenRef,
|
||||
passwordRef: current.passwordRef.trim().isEmpty
|
||||
? fallback.passwordRef
|
||||
: current.passwordRef,
|
||||
),
|
||||
);
|
||||
}
|
||||
return List<GatewayConnectionProfile>.unmodifiable(normalized);
|
||||
final current = incoming.isNotEmpty ? incoming.first : fallback;
|
||||
final hasEndpoint =
|
||||
current.host.trim().isNotEmpty &&
|
||||
current.port > 0 &&
|
||||
!_isGatewayLoopbackHost(current.host);
|
||||
final slotMode = switch (current.mode) {
|
||||
RuntimeConnectionMode.remote => RuntimeConnectionMode.remote,
|
||||
RuntimeConnectionMode.unconfigured =>
|
||||
hasEndpoint
|
||||
? RuntimeConnectionMode.remote
|
||||
: RuntimeConnectionMode.unconfigured,
|
||||
};
|
||||
return List<GatewayConnectionProfile>.unmodifiable(<GatewayConnectionProfile>[
|
||||
current.copyWith(
|
||||
mode: slotMode,
|
||||
useSetupCode: current.useSetupCode,
|
||||
setupCode: current.setupCode,
|
||||
host: hasEndpoint ? current.host : fallback.host,
|
||||
port: current.port > 0 ? current.port : fallback.port,
|
||||
tls: hasEndpoint ? current.tls : fallback.tls,
|
||||
tokenRef: current.tokenRef.trim().isEmpty
|
||||
? fallback.tokenRef
|
||||
: current.tokenRef,
|
||||
passwordRef: current.passwordRef.trim().isEmpty
|
||||
? fallback.passwordRef
|
||||
: current.passwordRef,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
bool _isGatewayLoopbackHost(String host) {
|
||||
@ -213,14 +161,12 @@ bool _isGatewayLoopbackHost(String host) {
|
||||
|
||||
List<GatewayConnectionProfile> replaceGatewayProfileAt(
|
||||
List<GatewayConnectionProfile> profiles,
|
||||
int index,
|
||||
int _,
|
||||
GatewayConnectionProfile profile,
|
||||
) {
|
||||
final normalizedProfiles = normalizeGatewayProfiles(profiles: profiles);
|
||||
final next = List<GatewayConnectionProfile>.from(normalizedProfiles);
|
||||
final clampedIndex = index.clamp(0, kGatewayProfileListLength - 1);
|
||||
next[clampedIndex] = profile;
|
||||
return normalizeGatewayProfiles(profiles: next);
|
||||
return normalizeGatewayProfiles(
|
||||
profiles: <GatewayConnectionProfile>[profile],
|
||||
);
|
||||
}
|
||||
|
||||
({String host, int port, bool tls}) normalizeGatewayManualEndpointInternal({
|
||||
@ -512,14 +458,9 @@ class AiGatewayProfile {
|
||||
(item) => availableModels.isEmpty || availableModels.contains(item),
|
||||
)
|
||||
.toList(growable: false);
|
||||
final legacyFilePath = json['filePath'] as String?;
|
||||
final legacyBaseUrl =
|
||||
legacyFilePath != null && legacyFilePath.trim().startsWith('http')
|
||||
? legacyFilePath.trim()
|
||||
: null;
|
||||
return AiGatewayProfile(
|
||||
name: json['name'] as String? ?? defaults.name,
|
||||
baseUrl: json['baseUrl'] as String? ?? legacyBaseUrl ?? defaults.baseUrl,
|
||||
baseUrl: json['baseUrl'] as String? ?? defaults.baseUrl,
|
||||
apiKeyRef: json['apiKeyRef'] as String? ?? defaults.apiKeyRef,
|
||||
availableModels: availableModels,
|
||||
selectedModels: selectedModels,
|
||||
|
||||
@ -301,9 +301,7 @@ class SettingsSnapshot {
|
||||
(json['vault'] as Map?)?.cast<String, dynamic>() ?? const {},
|
||||
),
|
||||
aiGateway: AiGatewayProfile.fromJson(
|
||||
(json['aiGateway'] as Map?)?.cast<String, dynamic>() ??
|
||||
(json['apisix'] as Map?)?.cast<String, dynamic>() ??
|
||||
const {},
|
||||
(json['aiGateway'] as Map?)?.cast<String, dynamic>() ?? const {},
|
||||
),
|
||||
webSessionPersistence: WebSessionPersistenceConfig.fromJson(
|
||||
(json['webSessionPersistence'] as Map?)?.cast<String, dynamic>() ??
|
||||
|
||||
@ -108,7 +108,8 @@ class SecretStore {
|
||||
bool _initialized = false;
|
||||
PersistentWriteFailure? _secretsWriteFailure;
|
||||
|
||||
Map<String, String> get secureRefs => Map<String, String>.unmodifiable(_memorySecure);
|
||||
Map<String, String> get secureRefs =>
|
||||
Map<String, String>.unmodifiable(_memorySecure);
|
||||
|
||||
PersistentWriteFailure? get secretsWriteFailure => _secretsWriteFailure;
|
||||
|
||||
@ -133,16 +134,9 @@ class SecretStore {
|
||||
}
|
||||
|
||||
Future<String?> loadGatewayToken({int? profileIndex}) async {
|
||||
if (profileIndex != null) {
|
||||
return _readSecure(_gatewayTokenKeyForProfile(profileIndex));
|
||||
}
|
||||
for (final index in _gatewayProfileFallbackOrder) {
|
||||
final scopedValue = await _readSecure(_gatewayTokenKeyForProfile(index));
|
||||
if ((scopedValue ?? '').trim().isNotEmpty) {
|
||||
return scopedValue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return _readSecure(
|
||||
_gatewayTokenKeyForProfile(profileIndex ?? kGatewayRemoteProfileIndex),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> saveGatewayToken(String value, {int? profileIndex}) =>
|
||||
@ -156,18 +150,9 @@ class SecretStore {
|
||||
);
|
||||
|
||||
Future<String?> loadGatewayPassword({int? profileIndex}) async {
|
||||
if (profileIndex != null) {
|
||||
return _readSecure(_gatewayPasswordKeyForProfile(profileIndex));
|
||||
}
|
||||
for (final index in _gatewayProfileFallbackOrder) {
|
||||
final scopedValue = await _readSecure(
|
||||
_gatewayPasswordKeyForProfile(index),
|
||||
);
|
||||
if ((scopedValue ?? '').trim().isNotEmpty) {
|
||||
return scopedValue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return _readSecure(
|
||||
_gatewayPasswordKeyForProfile(profileIndex ?? kGatewayRemoteProfileIndex),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> saveGatewayPassword(String value, {int? profileIndex}) =>
|
||||
@ -471,13 +456,6 @@ class SecretStore {
|
||||
static String _gatewayPasswordRefKey(int profileIndex) =>
|
||||
'gateway_password_$profileIndex';
|
||||
|
||||
static const List<int> _gatewayProfileFallbackOrder = <int>[
|
||||
kGatewayRemoteProfileIndex,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
];
|
||||
|
||||
static String _accountManagedSecretKey(String target) =>
|
||||
'xworkmate.account.managed.${target.trim()}';
|
||||
|
||||
|
||||
@ -1,82 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../models/app_models.dart';
|
||||
import 'surface_card.dart';
|
||||
import 'top_bar.dart';
|
||||
|
||||
List<Widget> buildOrderedSettingsSections({
|
||||
required List<SettingsTab> availableTabs,
|
||||
required SettingsTab currentTab,
|
||||
required List<Widget> Function(SettingsTab tab) buildTabContent,
|
||||
double gap = 24,
|
||||
}) {
|
||||
final orderedTabs = <SettingsTab>[
|
||||
currentTab,
|
||||
...availableTabs.where((item) => item != currentTab),
|
||||
];
|
||||
final sections = <Widget>[];
|
||||
for (final tab in orderedTabs) {
|
||||
final content = buildTabContent(tab);
|
||||
if (content.isEmpty) {
|
||||
continue;
|
||||
}
|
||||
if (sections.isNotEmpty) {
|
||||
sections.add(SizedBox(height: gap));
|
||||
}
|
||||
sections.addAll(content);
|
||||
}
|
||||
return sections;
|
||||
}
|
||||
|
||||
class SettingsGlobalApplyCard extends StatelessWidget {
|
||||
const SettingsGlobalApplyCard({
|
||||
super.key,
|
||||
required this.message,
|
||||
required this.onApply,
|
||||
this.applyLabel = 'Save & apply',
|
||||
this.title = 'Settings Submission',
|
||||
});
|
||||
|
||||
final String title;
|
||||
final String message;
|
||||
final String applyLabel;
|
||||
final VoidCallback? onApply;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return SurfaceCard(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(title, style: theme.textTheme.titleMedium),
|
||||
const SizedBox(height: 6),
|
||||
Text(message, style: theme.textTheme.bodyMedium),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
FilledButton.tonal(
|
||||
key: const ValueKey('settings-global-apply-button'),
|
||||
onPressed: onApply,
|
||||
child: Text(applyLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsPageBodyShell extends StatelessWidget {
|
||||
const SettingsPageBodyShell({
|
||||
super.key,
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
# macOS Frameworks
|
||||
|
||||
This directory contains native libraries for macOS integration.
|
||||
|
||||
## libcodex_ffi.dylib
|
||||
|
||||
The Rust FFI library for Codex CLI integration.
|
||||
|
||||
### Building
|
||||
|
||||
Run the build script from the project root:
|
||||
|
||||
```bash
|
||||
make rust-build-release
|
||||
```
|
||||
|
||||
### Integration
|
||||
|
||||
The library is linked by the Xcode project and loaded at runtime by `CodexFFIBindings`.
|
||||
|
||||
### Architecture
|
||||
|
||||
- `libcodex_ffi.dylib` - Universal binary (arm64 + x86_64)
|
||||
- `libcodex_ffi.a` - Static library (for debugging)
|
||||
|
||||
### FFI Functions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `codex_init()` | Initialize the library |
|
||||
| `codex_runtime_create()` | Create a runtime instance |
|
||||
| `codex_runtime_destroy()` | Destroy a runtime instance |
|
||||
| `codex_start_thread()` | Start a new thread |
|
||||
| `codex_send_message()` | Send a message |
|
||||
| `codex_poll_events()` | Poll for events |
|
||||
| `codex_shutdown()` | Shutdown the runtime |
|
||||
| `codex_last_error()` | Get last error message |
|
||||
|
||||
### Dependencies
|
||||
|
||||
- macOS 11.0 or later
|
||||
- No external dependencies beyond system libraries
|
||||
@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Script to add FFI framework to Xcode project
|
||||
# Run this once to configure the project to link libcodex_ffi.dylib
|
||||
|
||||
PROJECT_FILE="project.pbxproj"
|
||||
|
||||
# Check if already added
|
||||
if grep -q "libcodex_ffi.dylib" "$PROJECT_FILE" 2>/dev/null; then
|
||||
echo "FFI library already configured in project"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Note: This script is for reference."
|
||||
echo "To add the FFI library manually in Xcode:"
|
||||
echo ""
|
||||
echo "1. Open Runner.xcodeproj in Xcode"
|
||||
echo "2. Select Runner target"
|
||||
echo "3. Go to Build Phases > Link Binary With Libraries"
|
||||
echo "4. Click '+' and add 'libcodex_ffi.dylib'"
|
||||
echo "5. Set 'Framework Search Paths' to include '\$(PROJECT_DIR)/Frameworks'"
|
||||
echo "6. Set 'Runpath Search Paths' to include '@executable_path/../Frameworks'"
|
||||
echo ""
|
||||
echo "Alternatively, use the Podfile to add a vendored framework:"
|
||||
echo ""
|
||||
echo " pod 'CodexFFI', :path => '../rust'"
|
||||
@ -138,7 +138,7 @@ packages:
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
|
||||
|
||||
@ -18,7 +18,6 @@ dependencies:
|
||||
cryptography: ^2.6.1
|
||||
crypto: ^3.0.6
|
||||
device_info_plus: ^11.5.0
|
||||
ffi: ^2.1.4
|
||||
file_selector: ^1.0.3
|
||||
flutter_html: ^3.0.0
|
||||
flutter_markdown: ^0.7.7+1
|
||||
|
||||
43
scripts/check-no-app-ffi.sh
Executable file
43
scripts/check-no-app-ffi.sh
Executable file
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
forbidden_paths=(
|
||||
"scripts/copy_ffi_framework.sh"
|
||||
"scripts/generate_ffi_bindings.sh"
|
||||
"scripts/integrate_rust_flutter.sh"
|
||||
"flutter_rust_bridge.yaml"
|
||||
"lib/runtime/codex_ffi_generated.dart"
|
||||
"macos/Frameworks/libcodex_ffi.dylib"
|
||||
"macos/Frameworks/README.md"
|
||||
"macos/Runner.xcodeproj/add_ffi_framework.sh"
|
||||
)
|
||||
|
||||
failures=0
|
||||
for relative_path in "${forbidden_paths[@]}"; do
|
||||
if [[ -e "$ROOT_DIR/$relative_path" ]]; then
|
||||
echo "Forbidden app-side FFI artifact remains: $relative_path" >&2
|
||||
failures=$((failures + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
if rg -n \
|
||||
"copy_ffi_framework|generate_ffi_bindings|integrate_rust_flutter|flutter_rust_bridge|libcodex_ffi|codex_ffi_generated|ffi-(copy|generate|integrate)|build-macos-ffi" \
|
||||
"$ROOT_DIR/Makefile" \
|
||||
"$ROOT_DIR/scripts" \
|
||||
"$ROOT_DIR/lib" \
|
||||
"$ROOT_DIR/macos/Runner.xcodeproj" \
|
||||
--glob '!scripts/check-no-app-ffi.sh' \
|
||||
--glob '!**/Pods/**' \
|
||||
--glob '!**/Flutter/ephemeral/**' \
|
||||
--glob '!**/build/**'; then
|
||||
echo "Forbidden app-side FFI integration reference found." >&2
|
||||
failures=$((failures + 1))
|
||||
fi
|
||||
|
||||
if [[ "$failures" -ne 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "No app-side Codex FFI integration artifacts found."
|
||||
@ -2,4 +2,5 @@
|
||||
set -euo pipefail
|
||||
|
||||
flutter pub get
|
||||
bash scripts/check-no-app-ffi.sh
|
||||
flutter analyze
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
flutter pub get
|
||||
bash scripts/check-no-app-ffi.sh
|
||||
flutter analyze
|
||||
flutter test test/runtime/assistant_execution_target_test.dart
|
||||
flutter test test/runtime/runtime_controllers_settings_account_test.dart
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copy FFI library to macOS Frameworks
|
||||
# Add this to Xcode Build Phases > Run Script
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
FRAMEWORKS_DIR="$PROJECT_ROOT/macos/Frameworks"
|
||||
RUST_DIR="$PROJECT_ROOT/rust"
|
||||
|
||||
# Source FFI library location
|
||||
UNIVERSAL_LIB="$RUST_DIR/target/universal/libcodex_ffi.dylib"
|
||||
ARM_LIB="$RUST_DIR/target/aarch64-apple-darwin/release/libcodex_ffi.dylib"
|
||||
RELEASE_LIB="$RUST_DIR/target/release/libcodex_ffi.dylib"
|
||||
DEBUG_LIB="$RUST_DIR/target/debug/libcodex_ffi.dylib"
|
||||
|
||||
# Ensure Frameworks directory exists
|
||||
mkdir -p "$FRAMEWORKS_DIR"
|
||||
|
||||
# Copy universal binary if available, otherwise fall back to single architecture
|
||||
if [[ -f "$UNIVERSAL_LIB" ]]; then
|
||||
echo "Copying universal FFI library..."
|
||||
cp "$UNIVERSAL_LIB" "$FRAMEWORKS_DIR/"
|
||||
elif [[ -f "$ARM_LIB" ]]; then
|
||||
echo "Copying arm64 FFI library..."
|
||||
cp "$ARM_LIB" "$FRAMEWORKS_DIR/"
|
||||
elif [[ -f "$RELEASE_LIB" ]]; then
|
||||
echo "Copying release FFI library..."
|
||||
cp "$RELEASE_LIB" "$FRAMEWORKS_DIR/"
|
||||
elif [[ -f "$DEBUG_LIB" ]]; then
|
||||
echo "Copying debug FFI library..."
|
||||
cp "$DEBUG_LIB" "$FRAMEWORKS_DIR/"
|
||||
else
|
||||
echo "Warning: FFI library not found. Run make rust-build-release first."
|
||||
echo "Expected one of:"
|
||||
echo " - $UNIVERSAL_LIB"
|
||||
echo " - $ARM_LIB"
|
||||
echo " - $RELEASE_LIB"
|
||||
echo " - $DEBUG_LIB"
|
||||
exit 0 # Don't fail the build if library doesn't exist yet
|
||||
fi
|
||||
|
||||
echo "FFI library copied to $FRAMEWORKS_DIR/"
|
||||
@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Generate FFI bindings using flutter_rust_bridge
|
||||
# Usage: ./scripts/generate_ffi_bindings.sh
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
echo "Generating FFI bindings..."
|
||||
|
||||
# Check if flutter_rust_bridge is installed
|
||||
if ! command -v flutter_rust_bridge_codegen &> /dev/null; then
|
||||
echo "Installing flutter_rust_bridge_codegen..."
|
||||
cargo install flutter_rust_bridge_codegen --version 2.0.0
|
||||
fi
|
||||
|
||||
# Generate bindings
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
flutter_rust_bridge_codegen \
|
||||
--rust-input rust/src/lib.rs \
|
||||
--dart-output lib/runtime/codex_ffi_generated.dart \
|
||||
--dart-format-line-length 120 \
|
||||
--c-symbol-prefix codex_
|
||||
|
||||
echo "FFI bindings generated!"
|
||||
echo "Dart output: lib/runtime/codex_ffi_generated.dart"
|
||||
|
||||
# Generate C header for reference
|
||||
cbindgen rust/src/lib.rs -o rust/codex_ffi.h 2>/dev/null || echo "cbindgen not installed, skipping C header generation"
|
||||
|
||||
echo "Done!"
|
||||
@ -1,49 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Integrate Rust FFI library with Flutter macOS build
|
||||
# This script should be run before flutter build macos
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
echo "Integrating Rust FFI with Flutter..."
|
||||
|
||||
# Build Rust library if not exists
|
||||
RUST_LIB="$PROJECT_ROOT/rust/target/universal/libcodex_ffi.dylib"
|
||||
if [[ ! -f "$RUST_LIB" ]]; then
|
||||
echo "Rust library not found. Please build it manually or ensure it exists in target/."
|
||||
fi
|
||||
|
||||
# Ensure Frameworks directory exists
|
||||
FRAMEWORKS_DIR="$PROJECT_ROOT/macos/Frameworks"
|
||||
mkdir -p "$FRAMEWORKS_DIR"
|
||||
|
||||
# Copy library
|
||||
if [[ -f "$RUST_LIB" ]]; then
|
||||
cp "$RUST_LIB" "$FRAMEWORKS_DIR/"
|
||||
echo "Copied libcodex_ffi.dylib to $FRAMEWORKS_DIR/"
|
||||
else
|
||||
echo "Warning: Universal binary not found, using arm64..."
|
||||
ARM_LIB="$PROJECT_ROOT/rust/target/aarch64-apple-darwin/release/libcodex_ffi.dylib"
|
||||
if [[ -f "$ARM_LIB" ]]; then
|
||||
cp "$ARM_LIB" "$FRAMEWORKS_DIR/"
|
||||
echo "Copied arm64 library to $FRAMEWORKS_DIR/"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update Xcode project to link the library
|
||||
# This would typically be done via Xcode build phases
|
||||
echo ""
|
||||
echo "Note: You may need to add the following to your Xcode project:"
|
||||
echo " 1. Add libcodex_ffi.dylib to 'Link Binary With Libraries' build phase"
|
||||
echo " 2. Add macos/Frameworks to 'Framework Search Paths'"
|
||||
echo ""
|
||||
|
||||
# Generate FFI bindings if needed
|
||||
if [[ ! -f "$PROJECT_ROOT/lib/runtime/codex_ffi_generated.dart" ]]; then
|
||||
echo "Generating FFI bindings..."
|
||||
"$SCRIPT_DIR/generate_ffi_bindings.sh"
|
||||
fi
|
||||
|
||||
echo "Integration complete!"
|
||||
@ -102,17 +102,6 @@ if [[ ! -d "$BUILD_APP_PATH" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure FFI library is embedded if it was copied to macos/Frameworks
|
||||
SOURCE_FFI_LIB="$ROOT_DIR/macos/Frameworks/libcodex_ffi.dylib"
|
||||
TARGET_FFI_LIB="$BUILD_APP_PATH/Contents/Frameworks/libcodex_ffi.dylib"
|
||||
if [[ -f "$SOURCE_FFI_LIB" ]]; then
|
||||
echo "Embedding FFI library into app bundle..."
|
||||
mkdir -p "$(dirname "$TARGET_FFI_LIB")"
|
||||
cp "$SOURCE_FFI_LIB" "$TARGET_FFI_LIB"
|
||||
# Fix install name to be @rpath-based so it is portable within the bundle
|
||||
install_name_tool -id "@rpath/$(basename "$TARGET_FFI_LIB")" "$TARGET_FFI_LIB"
|
||||
fi
|
||||
|
||||
# Embed xworkmate-go-core for local/non-App-Store builds if available
|
||||
if [[ "${XWORKMATE_APP_STORE:-}" != "true" ]]; then
|
||||
SOURCE_GO_CORE="$ROOT_DIR/build/bin/xworkmate-go-core"
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:xworkmate/features/assistant/assistant_page_task_models.dart';
|
||||
|
||||
void main() {
|
||||
group('assistant task model cleanup', () {
|
||||
test('session key matching is exact and does not alias runtime main', () {
|
||||
expect(
|
||||
sessionKeysMatchInternal('draft:test-task', 'draft:test-task'),
|
||||
isTrue,
|
||||
);
|
||||
expect(sessionKeysMatchInternal('agent:main:main', 'main'), isFalse);
|
||||
expect(sessionKeysMatchInternal('main', 'agent:main:main'), isFalse);
|
||||
});
|
||||
|
||||
test('main runtime ids are displayed as ids, not app default tasks', () {
|
||||
expect(fallbackSessionTitleInternal('main'), 'main');
|
||||
expect(
|
||||
fallbackSessionTitleInternal('agent:main:main'),
|
||||
'agent:main:main',
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -114,7 +114,6 @@ void main() {
|
||||
tokenConfigured: const AccountTokenConfigured(
|
||||
bridge: true,
|
||||
vault: false,
|
||||
apisix: false,
|
||||
),
|
||||
),
|
||||
accountBusy: false,
|
||||
@ -211,7 +210,6 @@ void main() {
|
||||
tokenConfigured: const AccountTokenConfigured(
|
||||
bridge: true,
|
||||
vault: false,
|
||||
apisix: false,
|
||||
),
|
||||
),
|
||||
accountBusy: false,
|
||||
|
||||
@ -57,6 +57,49 @@ void main() {
|
||||
expect(provider.label, kCanonicalGatewayProviderLabel);
|
||||
});
|
||||
|
||||
test(
|
||||
'normalizes OpenClaw from provider catalog into selectable gateway mode',
|
||||
() async {
|
||||
final controller = AppController(
|
||||
environmentOverride: const <String, String>{},
|
||||
initialBridgeProviderCatalog: const <SingleAgentProvider>[
|
||||
SingleAgentProvider.codex,
|
||||
SingleAgentProvider.openclaw,
|
||||
],
|
||||
initialAvailableExecutionTargets: const <AssistantExecutionTarget>[
|
||||
AssistantExecutionTarget.agent,
|
||||
],
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
expect(
|
||||
controller.assistantProviderCatalog.map((item) => item.providerId),
|
||||
const <String>['codex'],
|
||||
);
|
||||
expect(
|
||||
controller.gatewayProviderCatalog.map((item) => item.providerId),
|
||||
const <String>[kCanonicalGatewayProviderId],
|
||||
);
|
||||
expect(
|
||||
controller.bridgeAvailableExecutionTargets,
|
||||
const <AssistantExecutionTarget>[
|
||||
AssistantExecutionTarget.agent,
|
||||
AssistantExecutionTarget.gateway,
|
||||
],
|
||||
);
|
||||
|
||||
await controller.sessionsController.switchSession('draft:test-task-a');
|
||||
await controller.setAssistantExecutionTarget(
|
||||
AssistantExecutionTarget.gateway,
|
||||
);
|
||||
|
||||
expect(
|
||||
controller.assistantProviderForSession('draft:test-task-a'),
|
||||
SingleAgentProvider.openclaw,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'switching a session to gateway uses the bridge-provided gateway catalog',
|
||||
() async {
|
||||
@ -508,7 +551,6 @@ void main() {
|
||||
tokenConfigured: const AccountTokenConfigured(
|
||||
bridge: true,
|
||||
vault: false,
|
||||
apisix: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -653,7 +695,6 @@ void main() {
|
||||
tokenConfigured: const AccountTokenConfigured(
|
||||
bridge: true,
|
||||
vault: false,
|
||||
apisix: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -694,7 +735,6 @@ void main() {
|
||||
tokenConfigured: const AccountTokenConfigured(
|
||||
bridge: true,
|
||||
vault: false,
|
||||
apisix: false,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@ -41,7 +41,6 @@ void main() {
|
||||
tokenConfigured: const AccountTokenConfigured(
|
||||
bridge: true,
|
||||
vault: false,
|
||||
apisix: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -79,22 +78,19 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'keeps the managed bridge endpoint fixed when signed out',
|
||||
() {
|
||||
final controller = AppController(
|
||||
environmentOverride: const <String, String>{
|
||||
'BRIDGE_SERVER_URL': 'https://stale.example.invalid',
|
||||
},
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
test('keeps the managed bridge endpoint fixed when signed out', () {
|
||||
final controller = AppController(
|
||||
environmentOverride: const <String, String>{
|
||||
'BRIDGE_SERVER_URL': 'https://stale.example.invalid',
|
||||
},
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
expect(
|
||||
controller.resolveBridgeAcpEndpointInternal()?.toString(),
|
||||
kManagedBridgeServerUrl,
|
||||
);
|
||||
},
|
||||
);
|
||||
expect(
|
||||
controller.resolveBridgeAcpEndpointInternal()?.toString(),
|
||||
kManagedBridgeServerUrl,
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'resolves raw bridge token only for the current managed bridge endpoint',
|
||||
@ -133,19 +129,21 @@ void main() {
|
||||
tokenConfigured: const AccountTokenConfigured(
|
||||
bridge: true,
|
||||
vault: false,
|
||||
apisix: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final controller = AppController(
|
||||
environmentOverride: const <String, String>{},store: store);
|
||||
environmentOverride: const <String, String>{},
|
||||
store: store,
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
await controller.settingsControllerInternal.initialize();
|
||||
|
||||
final bridgeHeader = await controller.resolveGatewayAcpAuthorizationHeaderInternal(
|
||||
Uri.parse('$kManagedBridgeServerUrl/acp/rpc'),
|
||||
);
|
||||
final bridgeHeader = await controller
|
||||
.resolveGatewayAcpAuthorizationHeaderInternal(
|
||||
Uri.parse('$kManagedBridgeServerUrl/acp/rpc'),
|
||||
);
|
||||
final unrelatedHeader = await controller
|
||||
.resolveGatewayAcpAuthorizationHeaderInternal(
|
||||
Uri.parse('https://unrelated.example.com/acp/rpc'),
|
||||
@ -159,7 +157,9 @@ void main() {
|
||||
test(
|
||||
'runtime coordinator only exposes remote and offline gateway modes',
|
||||
() {
|
||||
final controller = AppController(environmentOverride: const <String, String>{});
|
||||
final controller = AppController(
|
||||
environmentOverride: const <String, String>{},
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
expect(
|
||||
|
||||
77
test/runtime/gateway_profile_cleanup_test.dart
Normal file
77
test/runtime/gateway_profile_cleanup_test.dart
Normal file
@ -0,0 +1,77 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:xworkmate/runtime/runtime_controllers.dart';
|
||||
import 'package:xworkmate/runtime/runtime_models.dart';
|
||||
import 'package:xworkmate/runtime/secret_store.dart';
|
||||
|
||||
void main() {
|
||||
group('Gateway profile cleanup', () {
|
||||
test('normalizes settings to the single Bridge profile', () {
|
||||
final snapshot = SettingsSnapshot.defaults().copyWith(
|
||||
gatewayProfiles: <GatewayConnectionProfile>[
|
||||
GatewayConnectionProfile.defaults().copyWith(
|
||||
mode: RuntimeConnectionMode.remote,
|
||||
host: 'xworkmate-bridge.svc.plus',
|
||||
port: 443,
|
||||
tls: true,
|
||||
),
|
||||
GatewayConnectionProfile.defaults().copyWith(
|
||||
mode: RuntimeConnectionMode.remote,
|
||||
host: 'stale-local-gateway.example.com',
|
||||
port: 18789,
|
||||
tls: false,
|
||||
tokenRef: 'gateway_token_1',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
expect(snapshot.gatewayProfiles, hasLength(1));
|
||||
expect(snapshot.primaryGatewayProfile.host, 'xworkmate-bridge.svc.plus');
|
||||
expect(snapshot.primaryGatewayProfile.tokenRef, 'gateway_token_0');
|
||||
});
|
||||
|
||||
test('does not fall back to stale local Gateway profile secrets', () async {
|
||||
final storeRoot = await Directory.systemTemp.createTemp(
|
||||
'xworkmate-gateway-profile-cleanup-',
|
||||
);
|
||||
addTearDown(() async {
|
||||
if (await storeRoot.exists()) {
|
||||
try {
|
||||
await storeRoot.delete(recursive: true);
|
||||
} on FileSystemException {
|
||||
// Temp cleanup is best effort while Flutter test teardown releases IO.
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final store = SecretStore(
|
||||
secretRootPathResolver: () async => '${storeRoot.path}/secrets',
|
||||
appDataRootPathResolver: () async => '${storeRoot.path}/app-data',
|
||||
supportRootPathResolver: () async => '${storeRoot.path}/support',
|
||||
enableSecureStorage: false,
|
||||
);
|
||||
await store.initialize();
|
||||
await store.saveSecretValueByRef('gateway_token_1', 'stale-token');
|
||||
await store.saveSecretValueByRef('gateway_password_1', 'stale-password');
|
||||
|
||||
expect(await store.loadGatewayToken(), isNull);
|
||||
expect(await store.loadGatewayPassword(), isNull);
|
||||
|
||||
await store.saveSecretValueByRef('gateway_token_0', 'current-token');
|
||||
await store.saveSecretValueByRef(
|
||||
'gateway_password_0',
|
||||
'current-password',
|
||||
);
|
||||
|
||||
expect(await store.loadGatewayToken(), 'current-token');
|
||||
expect(await store.loadGatewayPassword(), 'current-password');
|
||||
});
|
||||
|
||||
test('runtime session key matching no longer aliases main sessions', () {
|
||||
expect(matchesSessionKey('draft:test-task', 'draft:test-task'), isTrue);
|
||||
expect(matchesSessionKey('agent:main:main', 'main'), isFalse);
|
||||
expect(matchesSessionKey('main', 'agent:main:main'), isFalse);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -397,7 +397,6 @@ void main() {
|
||||
tokenConfigured: const AccountTokenConfigured(
|
||||
bridge: true,
|
||||
vault: false,
|
||||
apisix: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -407,7 +406,9 @@ void main() {
|
||||
);
|
||||
|
||||
final controller = AppController(
|
||||
environmentOverride: const <String, String>{},store: store);
|
||||
environmentOverride: const <String, String>{},
|
||||
store: store,
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
await controller.settingsControllerInternal.initialize();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user