Add SqlCopilotRepository implementing the Repository Protocol's session
lifecycle (create_session/get_session) and compare_and_advance as a real
DB-level version-CAS: a single UPDATE ... WHERE version=base_version, with
rowcount==0 disambiguated into NotFoundError (missing session) vs
ConflictError (stale version). A UNIQUE(session_id, seq) collision on
conversation items during compare_and_advance is caught and mapped to
ConflictError, making the DB the seq authority. Remaining Repository
methods (checkpoints/runs/test-inputs/list_conversation) are stubbed with
NotImplementedError, deferred to Task 5.
Tested against SQLite in-memory: create/get round-trip, CAS version bump,
stale-version conflict leaving the row unchanged, missing-session
NotFoundError, and duplicate-seq ConflictError.
Implements WorkflowServiceDifyPort, the real DifyPort adapter that wires
the pure P1 domain and Task 1-3 helpers to WorkflowService,
AppGenerateService, and the node-execution repository. Each method opens
its own session, resolves account/app via the identity helpers, and
mutates the draft graph client-side (no server-side patch primitive)
before writing it back with graph_only=True/sync_agent_bindings=False.
Pins the publish workflow_id+commit gotcha and the hash-mismatch
re-mapping. Confirmed via mocked-service unit tests and a runtime_checkable
isinstance(..., DifyPort) check.
Port dify-enterprise/server/pkg/enterprise/biz/copilot/{ports,errors}.go to
api/core/workflow_copilot as pure Python.
- errors.py: ConflictError, NotFoundError, BusyError (Exception subclasses,
replacing Go's sentinel error values).
- models.py: add Diagnosis, Risk, MutationIntent, ChangeSet, NodeEvent,
ApplyResult value dataclasses (Go: ports.go); tighten FixContext.diagnosis/
staged_repair/risk/change_set from Any to these real types now that they
live in the same module (avoids a models<->ports import cycle).
- ports.py: CopilotAgent / DifyPort / Repository as @runtime_checkable
Protocols, snake_case methods per the port plan; DifyPort methods take
actor: Actor instead of Go's ForwardAuth.
- test_ports.py: constructs each value type, asserts trivial stubs satisfy
each Protocol via isinstance, and checks the error types.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extend the Workflow Copilot editor panel to fix pre-publish checklist
errors alongside failed runs.
- Detect blocking checklist items client-side via useChecklist(nodes,
edges, {flowType}) and offer a "Fix N checklist issues" entry next to
the failed-run entry, splitting config errors (auto-fixable) from
unconnected/plugin-missing items (surfaced but not auto-fixed in v1).
- Extend use-copilot-session's create path to POST checklist_errors
(new startChecklistFix) alongside the existing failed_run_id path
(startFix unchanged).
- Drive checklist.await_recheck: re-run the checklist against the
current draft and submit the recheck action with
passed = (fixable remaining === 0) and the full remaining list.
- Add copilot.checklist* i18n keys to en-US, matching the existing
copilot.* keys' en-US-only precedent for this feature.
Add a copilot toggle button next to Test Run in the workflow header and
a left-mounted panel that runs the copilot Fix flow (start fix, live
SSE progress log, approve_repair/run_verify/provide_testdata/publish/
undo/re_fix actions, and a message box), auto-resolving the app id
(workflow store `appId`), workspace id (`currentWorkspaceAtom`), and
the most recent failed run (`useWorkflowRunHistory`) instead of
requiring manual entry.
Extracts the session/SSE request logic from the standalone
`/workflow-copilot-debug` page into a shared
`app/components/workflow-copilot` module (`use-copilot-session`) so
both the debug page and the new panel drive the same implementation.
Adds a `showWorkflowCopilotPanel` store flag (defaults false) mirroring
the existing `showEnvPanel` pattern, so the feature is fully additive
and does not affect rag-pipeline/snippet editors that reuse the same
header/panel shell.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>