Skip to content

refactor(agent): remove Agent Drive - #40887

Open
BeautyyuYanli wants to merge 4 commits into
mainfrom
lody/e8469012-ff4
Open

refactor(agent): remove Agent Drive#40887
BeautyyuYanli wants to merge 4 commits into
mainfrom
lody/e8469012-ff4

Conversation

@BeautyyuYanli

Copy link
Copy Markdown
Contributor

Important

  1. Make sure you have read our contribution guidelines
  2. Ensure there is an associated issue and you have been assigned to it
  3. Use the correct syntax to link this PR: Fixes #<issue number>.

Summary

  • Remove the Agent Drive table, SQLAlchemy models, legacy Agent Soul file schema, Console/Inner/File routes, services, and Drive-specific ownership and cloning paths.
  • Remove the dify.drive layer, Agent Stub Drive protocol and materialization routes, sandbox Drive mount configuration, and dify-agent drive list/pull/push.
  • Add an Alembic migration that removes legacy Soul and workflow JSON fields before dropping agent_drive_files, while preserving historical migrations.
  • Keep config_skills, config_files, dify.config, Agent Stub config APIs, dify-agent config, and generic file upload/download behavior as the single surviving asset path.
  • Remove Drive-only unit, runtime, CLI, and E2E coverage; retain and strengthen focused coverage for the migration and surviving config-native flows.
  • Regenerate Agent CLI help, Console OpenAPI Markdown, and TypeScript contracts with the repository generators.

Issue: N/A — scoped removal of the obsolete Agent Drive storage and runtime path.

Root cause

Agent Drive introduced a parallel asset system alongside the newer config-native skill and file path. It maintained its own per-agent pointer table, Console and inner APIs, runtime layer, Agent Stub protocol, sandbox CLI commands, shell mount configuration, cloning behavior, ownership rules, generated contracts, and test fixtures.

The config-native path now owns Agent skill and file references through Agent Soul snapshots and dify.config. Keeping both paths left duplicate lifecycle and interface surfaces, including Drive row copying, Drive-specific mention checks, conversation ToolFile takeover, and duplicate E2E seeding.

Impact

Agent Drive is intentionally removed without a compatibility shim. The former Drive Console and inner endpoints are no longer registered, dify.drive compositions cannot be built, Agent Stub no longer exposes Drive routes, and the sandbox CLI no longer offers Drive commands.

Migration 89919253ca7a removes the legacy top-level Soul files field, removes persisted drive_key values from workflow file references, and drops agent_drive_files. Historical Drive assets are not converted into config assets. Generic UploadFile and ToolFile rows and object-storage objects are not deleted by the schema migration because those records have shared lifecycle semantics and object-storage I/O is not transactional.

Existing config-native skills and files remain part of Agent Soul snapshots and continue through publish, clone, runtime materialization, Agent Stub config APIs, and dify-agent config. Generic Agent Stub file upload and download behavior is unchanged.

Validation

  • Fast-forwarded and restored the implementation onto current origin/main (e3ab88f6) without conflicts.
  • Post-sync overlapping API regression suite: 241 passed.
  • Post-sync Dify Agent compositor regression suite: 4 passed.
  • Backend affected suites during implementation: 382 passed; focused rework suites: 252 passed and 90 passed; migration suite: 4 passed.
  • Dify Agent focused suite: 122 passed; import/export checks: 8 passed; make check: passed.
  • go test ./...: passed.
  • E2E TypeScript type-check and 46 unit tests: passed.
  • Contracts and Web type-checks: passed.
  • Focused backend Pyrefly checks completed with 0 diagnostics; affected Ruff checks and git diff --check passed.
  • uv run flask db heads confirmed 89919253ca7a as the single Alembic head.
  • Commit hooks completed API Ruff, ESLint, and formatting successfully.
  • All five staged implementation reviews passed after scoped code and test cleanup.

Screenshots

Before After
N/A — backend storage, API, Agent Stub, runtime CLI, generated contracts, tests, and documentation only. N/A — backend storage, API, Agent Stub, runtime CLI, generated contracts, tests, and documentation only.

Checklist

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.
  • I ran make lint && make type-check (backend) and cd web && pnpm exec vp staged (frontend) to appease the lint gods

This PR is made with gpt-5.6-sol (codex), while I'm responsible for all the changes.

@BeautyyuYanli
BeautyyuYanli requested a review from a team August 17, 2026 11:48
@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. refactor labels Aug 17, 2026
@github-actions github-actions Bot added web This relates to changes on the web. e2e End-to-end tests and E2E test infrastructure. labels Aug 17, 2026
@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-08-18 03:41:50.322509334 +0000
+++ /tmp/pyrefly_pr.txt	2026-08-18 03:41:36.709450582 +0000
@@ -1743,9 +1743,9 @@
 ERROR `None` is not subscriptable [unsupported-operation]
   --> tests/unit_tests/clients/agent_backend/test_event_adapter.py:58:12
 ERROR Object of class `list` has no attribute `startswith` [missing-attribute]
-   --> tests/unit_tests/clients/agent_backend/test_request_builder.py:176:12
+   --> tests/unit_tests/clients/agent_backend/test_request_builder.py:175:12
 ERROR Missing argument `backend_binding_ref` in function `clients.agent_backend.request_builder.AgentBackendWorkflowNodeRunInput.__init__` [missing-argument]
-   --> tests/unit_tests/clients/agent_backend/test_request_builder.py:295:41
+   --> tests/unit_tests/clients/agent_backend/test_request_builder.py:294:41
 ERROR Argument `list[FromClause]` is not assignable to parameter `tables` with type `Sequence[Table] | None` in function `sqlalchemy.sql.schema.MetaData.create_all` [bad-argument-type]
    --> tests/unit_tests/commands/test_archive_workflow_runs.py:181:16
 ERROR Expected a callable, got `None` [not-callable]
@@ -3319,33 +3319,29 @@
 ERROR No attribute `MethodView` in module `builtins` [missing-attribute]
  --> tests/unit_tests/controllers/common/test_fields.py:8:5
 ERROR `in` is not supported between `Literal['Incorrect API key provided']` and `None` [not-iterable]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:1644:12
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:1620:12
 ERROR Argument `test_drain_streaming_generate_response_returns_on_message_end.ClosableResponse` is not assignable to parameter `response` with type `Generator[str] | RateLimitGenerator` in function `controllers.console.app.completion._drain_streaming_generate_response` [bad-argument-type]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:1767:69
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:1743:69
 ERROR Argument `Iterator[Any]` is not assignable to parameter `response` with type `Generator[str] | RateLimitGenerator` in function `controllers.console.app.completion._drain_streaming_generate_response` [bad-argument-type]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:1774:66
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:1750:66
 ERROR Argument `Iterator[Any]` is not assignable to parameter `response` with type `Generator[str] | RateLimitGenerator` in function `controllers.console.app.completion._drain_streaming_generate_response` [bad-argument-type]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:1780:66
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:1756:66
 ERROR Object of class `object` has no attribute `data` [missing-attribute]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2192:50
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2168:50
 ERROR Object of class `object` has no attribute `limit` [missing-attribute]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2193:30
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2169:30
 ERROR Object of class `object` has no attribute `has_more` [missing-attribute]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2194:33
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2170:33
 ERROR Object of class `object` has no attribute `data` [missing-attribute]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2231:50
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2207:50
 ERROR Object of class `object` has no attribute `limit` [missing-attribute]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2232:30
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2208:30
 ERROR Object of class `object` has no attribute `has_more` [missing-attribute]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2233:33
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2209:33
 ERROR Argument `Literal['00000000-0000-0000-0000-000000000002']` is not assignable to parameter `message_id` with type `UUID` in function `controllers.console.app.message._get_message_suggested_questions` [bad-argument-type]
-    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2330:24
+    --> tests/unit_tests/controllers/console/agent/test_agent_controllers.py:2306:24
 ERROR Argument `SimpleNamespace` is not assignable to parameter `app_model` with type `App` in function `controllers.console.app.agent_config_inspector._resolve_agent_id` [bad-argument-type]
   --> tests/unit_tests/controllers/console/app/test_agent_config_inspector.py:54:51
-ERROR Argument `SimpleNamespace` is not assignable to parameter `app_model` with type `App` in function `controllers.console.app.agent_drive_inspector._resolve_agent_id` [bad-argument-type]
-  --> tests/unit_tests/controllers/console/app/test_agent_drive_inspector.py:50:59
-ERROR Argument `SimpleNamespace` is not assignable to parameter `app_model` with type `App` in function `controllers.console.app.agent._resolve_agent_id` [bad-argument-type]
-  --> tests/unit_tests/controllers/console/app/test_agent_skills.py:88:66
 ERROR Object of class `int` has no attribute `lower` [missing-attribute]
    --> tests/unit_tests/controllers/console/app/test_annotation_security.py:237:38
 ERROR Object of class `int` has no attribute `lower` [missing-attribute]
@@ -4908,16 +4904,14 @@
    --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:469:16
 ERROR Object of type `LayerConfig | Mapping[str, object] | bool | bytes | dict[str, JsonValue] | float | int | list[JsonValue] | str | None` has no attribute `model_dump` [missing-attribute]
    --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:484:16
-ERROR Object of type `LayerConfig | Mapping[str, object] | bool | bytes | dict[str, JsonValue] | float | int | list[JsonValue] | str | None` has no attribute `agent_stub_drive_ref` [missing-attribute]
-   --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:498:16
 ERROR Object of type `LayerConfig | Mapping[str, object] | bool | bytes | dict[str, JsonValue] | float | int | list[JsonValue] | str | None` has no attribute `model_dump` [missing-attribute]
-   --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:508:16
+   --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:507:16
 ERROR Object of type `LayerConfig | Mapping[str, object] | bool | bytes | dict[str, JsonValue] | float | int | list[JsonValue] | str | None` has no attribute `prefix` [missing-attribute]
-   --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:553:16
+   --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:552:16
 ERROR `not in` is not supported between `Literal['[§']` and `object` [not-iterable]
-   --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:554:16
+   --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:553:16
 ERROR Object of type `LayerConfig | Mapping[str, object] | bool | bytes | dict[str, JsonValue] | float | int | list[JsonValue] | str | None` has no attribute `prefix` [missing-attribute]
-   --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:570:16
+   --> tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py:569:16
 ERROR Argument `dict[str, dict[str, str]]` is not assignable to parameter `override_config_dict` with type `AppModelConfigDict | None` in function `core.app.apps.agent_chat.app_config_manager.AgentChatAppConfigManager.get_app_config` [bad-argument-type]
   --> tests/unit_tests/core/app/apps/agent_chat/test_agent_chat_app_config_manager.py:42:34
 ERROR Argument `dict[str, bool]` is not assignable to parameter `annotation_reply` with type `AnnotationReplyDisabledConfig | AnnotationReplyEnabledConfig | None` in function `core.app.apps.agent_chat.app_config_manager.AgentChatAppConfigManager.get_app_config` [bad-argument-type]
@@ -7691,9 +7685,9 @@
 ERROR Class member `LongRemoteUrlVariablePool.get` overrides a member in a parent class but is missing an `@override` decorator [missing-override-decorator]
     --> tests/unit_tests/core/workflow/nodes/agent_v2/test_runtime_request_builder.py:1364:13
 ERROR Object of type `LayerConfig | Mapping[str, object] | bool | bytes | dict[str, JsonValue] | float | int | list[JsonValue] | str | None` has no attribute `prefix` [missing-attribute]
-    --> tests/unit_tests/core/workflow/nodes/agent_v2/test_runtime_request_builder.py:1526:12
+    --> tests/unit_tests/core/workflow/nodes/agent_v2/test_runtime_request_builder.py:1525:12
 ERROR Object of type `LayerConfig | Mapping[str, object] | bool | bytes | dict[str, JsonValue] | float | int | list[JsonValue] | str | None` has no attribute `prefix` [missing-attribute]
-    --> tests/unit_tests/core/workflow/nodes/agent_v2/test_runtime_request_builder.py:1544:12
+    --> tests/unit_tests/core/workflow/nodes/agent_v2/test_runtime_request_builder.py:1543:12
 ERROR `not in` is not supported between `Literal['agent_workspace_binding_id']` and `None` [not-iterable]
    --> tests/unit_tests/core/workflow/nodes/agent_v2/test_session_store.py:185:12
 ERROR Class member `_ConcreteNode.version` overrides a member in a parent class but is missing an `@override` decorator [missing-override-decorator]
@@ -8334,12 +8328,6 @@
   --> tests/unit_tests/libs/test_time_parser.py:54:38
 ERROR Argument `SimpleNamespace` is not assignable to parameter `account` with type `Account | None` in function `libs.helper.TokenManager.generate_token` [bad-argument-type]
   --> tests/unit_tests/libs/test_token_manager.py:76:17
-ERROR Object of class `object` has no attribute `op` [missing-attribute]
-  --> tests/unit_tests/migrations/test_agent_drive_skill_metadata_refactor.py:59:23
-ERROR Object of class `object` has no attribute `op` [missing-attribute]
-  --> tests/unit_tests/migrations/test_agent_drive_skill_metadata_refactor.py:60:9
-ERROR Object of class `object` has no attribute `op` [missing-attribute]
-  --> tests/unit_tests/migrations/test_agent_drive_skill_metadata_refactor.py:64:13
 ERROR Argument `ModuleSpec | None` is not assignable to parameter `spec` with type `ModuleSpec` in function `_frozen_importlib.module_from_spec` [bad-argument-type]
   --> tests/unit_tests/migrations/test_uuidv7_pg18_migration.py:31:46
 ERROR Object of class `NoneType` has no attribute `loader` [missing-attribute]
@@ -8423,7 +8411,7 @@
 ERROR Class member `TestVolcengineTos.setup_method` overrides a member in a parent class but is missing an `@override` decorator [missing-override-decorator]
   --> tests/unit_tests/oss/volcengine_tos/test_volcengine_tos.py:17:9
 ERROR Object of class `NoneType` has no attribute `knowledge` [missing-attribute]
-   --> tests/unit_tests/services/agent/test_agent_composer_entities.py:408:17
+   --> tests/unit_tests/services/agent/test_agent_composer_entities.py:390:17
 ERROR `object` is not assignable to dict key `agent_binding` with type `str` [bad-assignment]
   --> tests/unit_tests/services/agent/test_agent_dsl_service.py:65:33
 ERROR Argument `SimpleNamespace` is not assignable to parameter `app` with type `App` in function `services.agent.dsl_service.AgentDslService.export_agent_app` [bad-argument-type]
@@ -8451,11 +8439,11 @@
 ERROR Argument `SimpleNamespace` is not assignable to parameter `source_snapshot` with type `AgentConfigSnapshot` in function `services.agent.dsl_service.AgentDslService.clone_inline_binding_for_node` [bad-argument-type]
    --> tests/unit_tests/services/agent/test_agent_dsl_service.py:487:25
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow` with type `Workflow` in function `services.agent.dsl_service.AgentDslService._create_imported_inline_agent` [bad-argument-type]
-   --> tests/unit_tests/services/agent/test_agent_dsl_service.py:577:18
+   --> tests/unit_tests/services/agent/test_agent_dsl_service.py:574:18
 ERROR Argument `SimpleNamespace` is not assignable to parameter `account` with type `Account` in function `services.agent.dsl_service.AgentDslService._create_imported_inline_agent` [bad-argument-type]
-   --> tests/unit_tests/services/agent/test_agent_dsl_service.py:579:17
+   --> tests/unit_tests/services/agent/test_agent_dsl_service.py:576:17
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow` with type `Workflow` in function `services.agent.dsl_service.AgentDslService._create_workflow_only_agent` [bad-argument-type]
-   --> tests/unit_tests/services/agent/test_agent_dsl_service.py:602:18
+   --> tests/unit_tests/services/agent/test_agent_dsl_service.py:599:18
 ERROR Argument `SimpleNamespace` is not assignable to parameter `message` with type `Message` in function `services.agent.observability_service.AgentObservabilityService.serialize_log_message` [bad-argument-type]
    --> tests/unit_tests/services/agent/test_agent_observability_service.py:630:9
 ERROR Argument `SimpleNamespace` is not assignable to parameter `conversation` with type `Conversation | None` in function `services.agent.observability_service.AgentObservabilityService.serialize_log_message` [bad-argument-type]
@@ -8463,61 +8451,55 @@
 ERROR Argument `list[SimpleNamespace]` is not assignable to parameter `feedbacks` with type `Sequence[MessageFeedback]` in function `services.agent.observability_service.AgentObservabilityService.serialize_log_message` [bad-argument-type]
    --> tests/unit_tests/services/agent/test_agent_observability_service.py:632:9
 ERROR Argument `SimpleNamespace` is not assignable to parameter `binding` with type `WorkflowAgentNodeBinding` in function `services.agent.composer_service.AgentComposerService._workflow_inline_debug_conversation_id` [bad-argument-type]
-   --> tests/unit_tests/services/agent/test_agent_services.py:402:17
+   --> tests/unit_tests/services/agent/test_agent_services.py:400:17
 ERROR Argument `SimpleNamespace` is not assignable to parameter `agent` with type `Agent | None` in function `services.agent.composer_service.AgentComposerService._workflow_inline_debug_conversation_id` [bad-argument-type]
-   --> tests/unit_tests/services/agent/test_agent_services.py:403:15
+   --> tests/unit_tests/services/agent/test_agent_services.py:401:15
 ERROR Argument `SimpleNamespace` is not assignable to parameter `binding` with type `WorkflowAgentNodeBinding` in function `services.agent.composer_service.AgentComposerService._workflow_inline_debug_conversation_id` [bad-argument-type]
-   --> tests/unit_tests/services/agent/test_agent_services.py:429:21
+   --> tests/unit_tests/services/agent/test_agent_services.py:427:21
 ERROR Argument `SimpleNamespace` is not assignable to parameter `agent` with type `Agent | None` in function `services.agent.composer_service.AgentComposerService._workflow_inline_debug_conversation_id` [bad-argument-type]
-   --> tests/unit_tests/services/agent/test_agent_services.py:430:19
+   --> tests/unit_tests/services/agent/test_agent_services.py:428:19
 ERROR Argument `SimpleNamespace` is not assignable to parameter `binding` with type `WorkflowAgentNodeBinding` in function `services.agent.composer_service.AgentComposerService._workflow_inline_debug_conversation_id` [bad-argument-type]
-   --> tests/unit_tests/services/agent/test_agent_services.py:439:21
+   --> tests/unit_tests/services/agent/test_agent_services.py:437:21
 ERROR Argument `SimpleNamespace` is not assignable to parameter `agent` with type `Agent | None` in function `services.agent.composer_service.AgentComposerService._workflow_inline_debug_conversation_id` [bad-argument-type]
-   --> tests/unit_tests/services/agent/test_agent_services.py:440:19
+   --> tests/unit_tests/services/agent/test_agent_services.py:438:19
 ERROR Object of class `NoneType` has no attribute `agent_workspace_binding_id` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:1310:12
+    --> tests/unit_tests/services/agent/test_agent_services.py:1308:12
 ERROR Object of class `object` has no attribute `prompt` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:2760:12
-ERROR Cannot index into `object` [bad-index]
-    --> tests/unit_tests/services/agent/test_agent_services.py:2950:12
+    --> tests/unit_tests/services/agent/test_agent_services.py:2741:12
 ERROR Cannot index into `object` [bad-index]
-    --> tests/unit_tests/services/agent/test_agent_services.py:2951:12
+    --> tests/unit_tests/services/agent/test_agent_services.py:2927:12
 ERROR Cannot index into `object` [bad-index]
-    --> tests/unit_tests/services/agent/test_agent_services.py:2952:12
+    --> tests/unit_tests/services/agent/test_agent_services.py:2928:12
 ERROR Cannot index into `object` [bad-index]
-    --> tests/unit_tests/services/agent/test_agent_services.py:2954:12
-ERROR Cannot index into `object` [bad-index]
-    --> tests/unit_tests/services/agent/test_agent_services.py:2955:12
+    --> tests/unit_tests/services/agent/test_agent_services.py:2929:12
 ERROR Argument `list[str | None]` is not assignable to parameter `version_ids` with type `list[str]` in function `services.agent.roster_service.AgentRosterService._load_versions_by_id` [bad-argument-type]
-    --> tests/unit_tests/services/agent/test_agent_services.py:4284:52
+    --> tests/unit_tests/services/agent/test_agent_services.py:4073:52
 ERROR Object of class `NoneType` has no attribute `conversation_id` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5177:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:4966:16
 ERROR Object of class `object` has no attribute `name` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5394:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:5183:16
 ERROR Object of class `object` has no attribute `mode` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5395:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:5184:16
 ERROR Object of class `object` has no attribute `agent_role` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5396:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:5185:16
 ERROR Object of class `object` has no attribute `config_snapshot` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5406:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:5195:16
 ERROR Object of class `object` has no attribute `home_snapshot_id` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5408:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:5197:16
 ERROR Object of class `object` has no attribute `summary` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5409:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:5198:16
 ERROR Object of class `object` has no attribute `version_note` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5410:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:5199:16
 ERROR Object of class `object` has no attribute `active_config_has_model` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5411:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:5200:16
 ERROR Object of class `object` has no attribute `active_config_is_published` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5412:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:5201:16
 ERROR Object of class `object` has no attribute `updated_by` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5413:16
+    --> tests/unit_tests/services/agent/test_agent_services.py:5202:16
 ERROR Object of class `object` has no attribute `id` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5414:35
+    --> tests/unit_tests/services/agent/test_agent_services.py:5203:35
 ERROR Object of class `object` has no attribute `agent_role` [missing-attribute]
-    --> tests/unit_tests/services/agent/test_agent_services.py:5479:16
-ERROR Cannot set item in `dict[str, str]` [unsupported-operation]
-    --> tests/unit_tests/services/agent/test_agent_services.py:7256:31
+    --> tests/unit_tests/services/agent/test_agent_services.py:5268:16
 ERROR Object of class `NoneType` has no attribute `workflow_prompt` [missing-attribute]
    --> tests/unit_tests/services/agent/test_composer_mention_validation.py:113:5
 ERROR Argument `object` is not assignable to parameter `pwd` with type `bytes | None` in function `zipfile.ZipFile.read` [bad-argument-type]
@@ -8830,12 +8812,6 @@
     --> tests/unit_tests/services/test_agent_app_sandbox_service.py:1020:52
 ERROR Argument `SimpleNamespace` is not assignable to parameter `version` with type `AgentConfigDraft | AgentConfigSnapshot` in function `services.agent_config_service.AgentConfigTarget.__init__` [bad-argument-type]
    --> tests/unit_tests/services/test_agent_config_service.py:145:17
-ERROR Object of class `FromClause` has no attribute `create` [missing-attribute]
-  --> tests/unit_tests/services/test_agent_drive_service.py:69:9
-ERROR Object of class `FromClause` has no attribute `drop` [missing-attribute]
-  --> tests/unit_tests/services/test_agent_drive_service.py:78:5
-ERROR Argument `Literal['created_at']` is not assignable to parameter `k` with type `Never` in function `_typeshed._type_checker_internals.TypedDictFallback.pop` [bad-argument-type]
-   --> tests/unit_tests/services/test_agent_drive_service.py:840:32
 ERROR Argument `dict[str, str]` is not assignable to parameter `args` with type `InsertAnnotationArgs` in function `services.annotation_service.AppAnnotationService.insert_app_annotation_directly` [bad-argument-type]
    --> tests/unit_tests/services/test_annotation_service.py:510:69
 ERROR TypedDict `AnnotationSettingDisabledDict` does not have key `embedding_model` [bad-typed-dict-key]

@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Pyrefly Type Coverage

Metric Base PR Delta
Type coverage 59.36% 59.32% -0.03%
Strict coverage 58.94% 58.90% -0.03%
Typed symbols 39,626 39,361 -265
Untyped symbols 27,328 27,182 -146
Modules 3174 3161 -13

@dosubot

dosubot Bot commented Aug 17, 2026

Copy link
Copy Markdown

📄 Knowledge review

✏️ Suggested updates

1 page suggestion needs review.

Page Library Status
Dify Agent Server 模块分析 (Commit 55f95dbc) dify 🟡 Review
📝 Dify Agent Server 模块分析 (Commit 55f95db)
@@ -1,6 +1,8 @@
 # Dify Agent Server 模块分析 (Commit 55f95dbc)
 
 > **注意**:自 PR #38841 起,shellctl 已用 Go 重写为 `dify-agent-runtime`。本文档描述的是 commit 55f95dbc 中的原始 Python 实现。
+
+> **重要变更**:自 PR #40887(2026-08-17)起,Agent Drive 系统已从 Dify 中移除。Agent 资产管理现在统一通过 `dify.config` 层实现(技能、文件、环境变量和笔记),Agent Drive 的数据表、API 端点、运行时 Layer、Agent Stub 协议和 CLI 命令已完全移除。历史 Agent Soul 中的 Drive 引用在数据库迁移中已清理。
 
 ## 概述
 
@@ -319,7 +321,7 @@
 
 #### 7. Dify Shell Layer
 
-**`DifyShellLayer`**(type_id: `dify.shell`):shell 适配器提供者/执行器机制支持的有状态工具层,暴露 `shell_run`、`shell_wait`、`shell_input` 和 `shell_interrupt` 四个工具。该层仅在 `runtime_state` 中持久化 JSON 安全的 shell 会话状态,而在 `resource_context()` 活跃时将活跃 `ShellctlHandle` 保存在 Layer 实例上。Agenton 在 `on_context_create` 或 `on_context_resume` 之前进入该资源作用域,并在 `on_context_suspend` 或 `on_context_delete` 之后退出,因此业务钩子和 shell 工具可以依赖活跃资源而无需将其序列化到快照中。该层将工作区生命周期委托给 `ShellProvisionProtocol`:`provision()` 分配新工作区,`reattach()` 从描述符重建句柄,`destroy()` 拆除工作区。内部工作区分配逻辑(`_allocate_workspace`、`_workspace_mkdir_script`、`_workspace_cleanup_script`)已移除,现由提供者处理。会话 ID 验证已放宽:现在仅拒绝包含 `/`、`..` 或单引号的值(不再要求精确的 5+2 十六进制格式)。该层具有可选依赖 `DifyShellLayerDeps`(包含 `drive: DifyDriveLayer | None`、`config: DifyConfigLayer | None` 和 `execution_context: DifyExecutionContextLayer | None`),并可通过 `build_shell_agent_stub_env` 和 `ShellAgentStubTokenFactory` 向用户可见的 `shell.run` 作业注入 Agent Stub 环境变量(`DIFY_AGENT_STUB_API_BASE_URL`、`DIFY_AGENT_STUB_AUTH_JWE` 和 `DIFY_AGENT_STUB_DRIVE_BASE`),仅当 shell layer 构建时传入了有效的 `agent_stub_api_base_url` 和 `agent_stub_token_factory` 参数。当运行包含 `dify.drive` 依赖时,注入的 drive base 从 Agent Stub drive 挂载和 drive 引用计算(如 `/mnt/drive/agent-123`)。没有 drive 依赖时,CLI 保留历史 `/mnt/drive` 回退值。服务器拥有的脚本(如 `run_remote_script`)通过 Go 作业执行器(`shellctl-runner`)运行,取代了之前生成的 bash/python runner 脚本。该层通过 `shell_home_root` 字段配置 per-agent HOME 目录的根路径:shell 命令以 `HOME=<shell_home_root>/<agent_id>` 环境变量运行。`shell_home_root` 默认为 `/home`(适用于 Linux 和容器部署),通过 `from_config_with_settings()` 构造器传入,并经 `_normalize_shell_home_root()` 辅助函数规范化(去除尾部斜杠,验证绝对路径)。`_shell_home_dir()` 方法现在使用 `shell_home_root` 构造 HOME 路径,替代硬编码的 `/home/<agent_id>`。对于本地 macOS 开发,应将 `shell_home_root` 设置为可写路径(如 `/tmp/dify-agent-home`)。
+**`DifyShellLayer`**(type_id: `dify.shell`):shell 适配器提供者/执行器机制支持的有状态工具层,暴露 `shell_run`、`shell_wait`、`shell_input` 和 `shell_interrupt` 四个工具。该层仅在 `runtime_state` 中持久化 JSON 安全的 shell 会话状态,而在 `resource_context()` 活跃时将活跃 `ShellctlHandle` 保存在 Layer 实例上。Agenton 在 `on_context_create` 或 `on_context_resume` 之前进入该资源作用域,并在 `on_context_suspend` 或 `on_context_delete` 之后退出,因此业务钩子和 shell 工具可以依赖活跃资源而无需将其序列化到快照中。该层将工作区生命周期委托给 `ShellProvisionProtocol`:`provision()` 分配新工作区,`reattach()` 从描述符重建句柄,`destroy()` 拆除工作区。内部工作区分配逻辑(`_allocate_workspace`、`_workspace_mkdir_script`、`_workspace_cleanup_script`)已移除,现由提供者处理。会话 ID 验证已放宽:现在仅拒绝包含 `/`、`..` 或单引号的值(不再要求精确的 5+2 十六进制格式)。该层具有可选依赖 `DifyShellLayerDeps`(包含 ~~`drive: DifyDriveLayer | None`~~(**已移除**,PR #40887)、`config: DifyConfigLayer | None` 和 `execution_context: DifyExecutionContextLayer | None`),并可通过 `build_shell_agent_stub_env` 和 `ShellAgentStubTokenFactory` 向用户可见的 `shell.run` 作业注入 Agent Stub 环境变量(`DIFY_AGENT_STUB_API_BASE_URL` 和 `DIFY_AGENT_STUB_AUTH_JWE`),仅当 shell layer 构建时传入了有效的 `agent_stub_api_base_url` 和 `agent_stub_token_factory` 参数。~~当运行包含 `dify.drive` 依赖时,注入的 drive base 从 Agent Stub drive 挂载和 drive 引用计算(如 `/mnt/drive/agent-123`)。没有 drive 依赖时,CLI 保留历史 `/mnt/drive` 回退值。~~(**Drive 注入已移除**,PR #40887:`DIFY_AGENT_STUB_DRIVE_BASE` 环境变量不再注入到 shell 环境中)服务器拥有的脚本(如 `run_remote_script`)通过 Go 作业执行器(`shellctl-runner`)运行,取代了之前生成的 bash/python runner 脚本。该层通过 `shell_home_root` 字段配置 per-agent HOME 目录的根路径:shell 命令以 `HOME=<shell_home_root>/<agent_id>` 环境变量运行。`shell_home_root` 默认为 `/home`(适用于 Linux 和容器部署),通过 `from_config_with_settings()` 构造器传入,并经 `_normalize_shell_home_root()` 辅助函数规范化(去除尾部斜杠,验证绝对路径)。`_shell_home_dir()` 方法现在使用 `shell_home_root` 构造 HOME 路径,替代硬编码的 `/home/<agent_id>`。对于本地 macOS 开发,应将 `shell_home_root` 设置为可写路径(如 `/tmp/dify-agent-home`)。
 
 **Shell Layer 系统提示**(PR #40623):该层通过 `_build_prefix_prompt()` 方法提供模式感知的前缀提示,而非静态函数 `_shell_layer_prefix_prompt()`。系统提示描述文件系统空间:
 
@@ -346,7 +348,7 @@
 - `DifyShellEnvVarConfig`:Shell 环境变量声明,包含 `name`(环境变量名)和 `value`(字符串值)字段
 - `DifyShellSecretRefConfig`:敏感凭证引用,包含 `name`(环境变量名)字段,值由外部系统注入
 - `DifyShellCliToolConfig`:CLI 工具声明,包含 `name`、`install_commands` 列表,以及工具专用的 `env: list[DifyShellEnvVarConfig]` 和 `secret_refs: list[DifyShellSecretRefConfig]` 字段
-- `DifyShellLayerConfig`:顶层配置,包含全局 `env`、`secret_refs`、`cli_tools` 列表、`sandbox` 配置和 `redact_patterns` 字段(regex 字符串列表,默认为空列表,用于定义 per-agent 的输出脱敏模式)
+- `DifyShellLayerConfig`:顶层配置,包含全局 `env`、`secret_refs`、`cli_tools` 列表、`sandbox` 配置和 `redact_patterns` 字段(regex 字符串列表,默认为空列表,用于定义 per-agent 的输出脱敏模式)。~~`agent_stub_drive_ref: str | None`~~(**已移除**,PR #40887:不再需要 Drive 引用配置)
 
 Shell layer 在工作区初始化时会检查是否有任何 CLI 工具需要安装。引导脚本由 `shellctl-runner` 在工作区首次创建时执行,环境变量注入是临时的(ephemeral),不持久化到工作区文件。
 
@@ -509,17 +511,28 @@
 - **已移除**:`job_id`、`done`、`offset`、`output_path`
 - **保留**:`status`、`exit_code`、`output`、`truncated`
 
-#### 8. Dify Drive Layer
-
-**`DifyDriveLayer`**(type_id: `dify.drive`):配置专用的 Skills & Files 目录声明层,基于 `PlainLayer` 实现。该层现在是一个提及驱动(mention-driven)的运行时层——drive 配置从使用 `@skill` 和 `@file` 提及的系统提示中派生。Drive 引用从提及解码并解析到 agent drive 目录。`DifyDriveLayerConfig` 现在包含 `mentioned_skill_keys` 和 `mentioned_file_keys` 列表用于急切拉取键。技能从 drive 服务编目,而不是从 skills_files 配置。运行时请求构建器现在使用 `build_drive_aware_soul_mention_resolver` 来解析针对 agent drive 的 skill/file 提及。
-
-**配置模型**(`dify-agent/src/dify_agent/layers/drive/configs.py`):
+#### 8. Dify Drive Layer(已移除)
+
+> **已移除**(PR #40887):`dify.drive` 层及其相关基础设施已完全从 Dify 中移除。Agent 资产管理现在通过 `dify.config` 层统一处理,无需单独的 Drive 表和 API。以下描述仅用于历史参考。
+
+**`DifyDriveLayer`**(type_id: `dify.drive`,**已弃用**):配置专用的 Skills & Files 目录声明层,基于 `PlainLayer` 实现。该层曾是一个提及驱动(mention-driven)的运行时层——drive 配置从使用 `@skill` 和 `@file` 提及的系统提示中派生。Drive 引用从提及解码并解析到 agent drive 目录。`DifyDriveLayerConfig` 包含 `mentioned_skill_keys` 和 `mentioned_file_keys` 列表用于急切拉取键。技能从 drive 服务编目,而不是从 skills_files 配置。
+
+**配置模型**(已移除文件 `dify-agent/src/dify_agent/layers/drive/configs.py`):
 
 - `DifyDriveLayerConfig`:主配置,包含 `drive_ref`(如 `"agent-<agent_id>"`)、`skills` 列表、`mentioned_skill_keys` 列表和 `mentioned_file_keys` 列表
 - `DifyDriveSkillConfig`:Skill 声明,包含 `path`、`name`、`description`、`skill_md_key`(如 `"<slug>/SKILL.md"`)和可选的 `archive_key`(如 `"<slug>/.DIFY-SKILL-FULL.zip"`)
 - `DIFY_DRIVE_LAYER_TYPE_ID`:常量,值为 `"dify.drive"`
 
-**设计原理**:API backend 编目并写入目录;Agent backend 通过 `drive_ref` 使用 back proxy 拉取条目来消费。这种分离维护了动态加载原则,而不会用完整内容使运行请求膨胀。Drive 配置现在是提及驱动的:配置器服务不再执行 drive 引用的预保存验证;相反,它检查缺失的 drive 提及。运行时警告现在报告 `mention_target_missing` 而不是 `skill_ref_dangling`/`file_ref_dangling`。该层在原始 commit(55f95dbc)之后引入,作为架构的扩展。
+**移除影响**:
+- 数据库迁移 `89919253ca7a` 删除了 `agent_drive_files` 表
+- 旧 Agent Soul 中的 `files` 顶层字段已移除
+- 工作流文件引用中的持久化 `drive_key` 值已清除
+- Console 和 Inner API 的 Drive 端点不再注册
+- Agent Stub 的 Drive 协议路由和 CLI 命令(`dify-agent drive list/pull/push`)已移除
+- Shell 层不再注入 `DIFY_AGENT_STUB_DRIVE_BASE` 环境变量
+- Generic `UploadFile` 和 `ToolFile` 记录及对象存储文件不受迁移影响(共享生命周期语义)
+
+**替代方案**:现有 Agent 资产通过 `dify.config` 层管理,包括 `config_skills`、`config_files`、环境变量和笔记。Config-native 流程通过 Agent Soul 快照和 Agent Stub config API 继续运作。
 
 #### 9. Dify Core Tools Layer
 
@@ -1025,7 +1038,7 @@
 - **安装 `[grpc]` 完整依赖**:此镜像合并了之前仅 shellctl 镜像与沙箱可见的 Agent Stub 客户端 CLI。它默认运行 shellctl,shellctl 管理的作业可以调用 `dify-agent ...` 而无需在运行时安装额外的包
 - **shell-session-manager 版本**:2.2.1(从 2.2.0 升级)
 - **Agent Stub CLI 包含**:包含带有 gRPC 传输 extra 的 dify-agent Agent Stub 客户端 CLI
-- **Drive 基础回退**:镜像设置回退 `DIFY_AGENT_STUB_DRIVE_BASE=/mnt/drive` 并预创建该目录,授予写访问权限
+- ~~**Drive 基础回退**~~(**已移除**,PR #40887):~~镜像设置回退 `DIFY_AGENT_STUB_DRIVE_BASE=/mnt/drive` 并预创建该目录,授予写访问权限~~
 - **布局与现有部署一致**:virtualenv 位于 `/opt/dify-agent/.venv`,非 root 用户 uid 1001(`dify`),与 `dify-api` 镜像约定保持一致
 - **暴露端口 5004**:默认监听端口为 5004
 - **启动命令**:`shellctl serve --listen 0.0.0.0:5004`
@@ -1328,7 +1341,7 @@
 
 - `create_agent_stub_token_codec() -> AgentStubTokenCodec | None`:当 `server_secret_key` 已配置时返回 Agent Stub token 编解码器
 - `create_agent_stub_file_request_handler() -> DifyApiAgentStubFileRequestHandler | None`:当 `inner_api_key` 已配置时返回文件请求处理器
-- `create_agent_stub_drive_request_handler() -> DifyApiAgentStubDriveRequestHandler | None`:当 `inner_api_url` 和 `inner_api_key` 都已配置时返回 Dify API drive 桥接处理器
+- ~~`create_agent_stub_drive_request_handler() -> DifyApiAgentStubDriveRequestHandler | None`~~(**已移除**,PR #40887):Drive 请求处理器不再提供
 - `create_outbound_http_timeout() -> httpx.Timeout`:从服务器设置构建共享出站 HTTP 超时对象
 - `get_shell_redact_patterns() -> list[str]`:解析 `shell_redact_patterns` 字段(JSON 数组格式),返回 regex 字符串列表。空/空白值返回空列表。若格式非法(非 JSON 数组)抛出 `ValueError`
 
@@ -1499,9 +1512,10 @@
 | `dify-agent connect [ARGV...]` | 建立 Agent Stub 连接 | `dify-agent connect my-tool arg1` |
 | `dify-agent file upload PATH` | 上传沙箱本地文件为 ToolFile 输出引用 | `dify-agent file upload output.csv` |
 | `dify-agent file download TRANSFER_METHOD REFERENCE [DIR]` | 下载工作流文件映射到本地沙箱目录 | `dify-agent file download tool_file dify-file-ref:... ./downloads` |
-| `dify-agent drive list [--prefix PREFIX] [--json]` | 列出 Agent 可见的 drive 条目 | `dify-agent drive list skills/` |
-| `dify-agent drive pull [--prefix PREFIX] [--drive-base PATH]` | 通过签名下载 URL 拉取 drive 文件到本地目录树 | `dify-agent drive pull skills/ --drive-base /mnt/drive` |
-| `dify-agent drive push LOCAL_PATH DRIVE_PATH [--recursive]` | 上传本地文件或目录并提交到 drive | `dify-agent drive push output.json data/output.json` |
+| ~~`dify-agent drive list`~~<br/>~~`dify-agent drive pull`~~<br/>~~`dify-agent drive push`~~ | **已移除**(PR #40887)| ~~`dify-agent drive list skills/`~~ |
+| `dify-agent config manifest` | 获取 Agent 配置 manifest | `dify-agent config manifest` |
+| `dify-agent config skills pull/push/delete` | 管理技能(config-native 路径) | `dify-agent config skills pull` |
+| `dify-agent config files pull/push/delete` | 管理文件(config-native 路径) | `dify-agent config files pull` |
 
 **未知命令的自动转发**:当用户执行 `dify-agent unknown-cmd arg1` 且 `unknown-cmd` 不是已知子命令时,CLI 会自动将其视为 `connect` 请求的 `argv`,即等价于 `dify-agent connect unknown-cmd arg1`。此设计简化了自定义命令的调用。
 
@@ -1516,8 +1530,9 @@
 | `POST` | `/agent-stub/connections` | 建立控制平面连接 |
 | `POST` | `/agent-stub/files/upload-request` | 分配签名上传 URL |
 | `POST` | `/agent-stub/files/download-request` | 分配签名下载 URL |
-| `GET` | `/agent-stub/drive/manifest` | 获取 drive manifest,支持 prefix 过滤和 download URL 包含选项 |
-| `POST` | `/agent-stub/drive/commit` | 提交 drive 批次,从 `AgentStubDriveCommitRequest` 载荷提交 drive 条目 |
+| ~~`GET /agent-stub/drive/manifest`~~<br/>~~`POST /agent-stub/drive/commit`~~ | **已移除**(PR #40887) | N/A |
+| `GET` | `/agent-stub/config/manifest` | 获取 config manifest(config-native 替代) |
+| `POST` | `/agent-stub/config/push` | 推送配置变更 |
 
 所有端点要求 `Authorization: Bearer <JWE>` 头。服务器通过 `AgentStubTokenCodec.decode_connection_token()` 验证令牌并恢复执行上下文。
 

Accept · Edit · Decline


Leave Feedback Ask Dosu about dify

@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.79%. Comparing base (09f8f43) to head (d9d5d5a).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
api/controllers/console/agent/composer.py 25.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #40887      +/-   ##
==========================================
+ Coverage   86.77%   86.79%   +0.02%     
==========================================
  Files        5206     5357     +151     
  Lines      292661   295351    +2690     
  Branches    58200    59182     +982     
==========================================
+ Hits       253942   256350    +2408     
- Misses      33717    34033     +316     
+ Partials     5002     4968      -34     
Flag Coverage Δ
api 86.77% <85.00%> (-0.02%) ⬇️
cli 89.33% <ø> (?)
dify-ui 93.60% <ø> (ø)
web 86.68% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@BeautyyuYanli
BeautyyuYanli force-pushed the lody/e8469012-ff4 branch 4 times, most recently from 34cf9ae to 508f550 Compare August 17, 2026 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

e2e End-to-end tests and E2E test infrastructure. refactor size:XXL This PR changes 1000+ lines, ignoring generated files. web This relates to changes on the web.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant