Skip to content

Commit 8d7c11b

Browse files
committed
feat: add qianji bpmn repair flow
1 parent fdf896f commit 8d7c11b

39 files changed

Lines changed: 2068 additions & 132 deletions

File tree

.envrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# shellcheck shell=bash
2+
13
for profile in $NIX_PROFILES; do
24
if [ -d "$profile/bin" ]; then
35
PATH_add "$profile/bin"

.github/workflows/checks.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ jobs:
2525
- xiuxian-llm-release
2626
- xiuxian-logging-release
2727
- xiuxian-macros-release
28-
- xiuxian-memory-release
2928
- xiuxian-memory-engine-release
3029
- xiuxian-qianhuan-release
3130
- xiuxian-qianji-release

nix/packages/xiuxian-core-rs.nix

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,12 @@ python3Packages.buildPythonPackage {
113113
export PDF_INSPECTOR_REV="$(cargo_lock_git_rev_or_default "https://github.com/firecrawl/pdf-inspector" "63b55731337c18baf23319b73cc9780bb23ac61b")"
114114
export RUST_LANG_PROJECT_HARNESS_REV="$(cargo_lock_git_rev "https://github.com/tao3k/rust-lang-project-harness")"
115115
export LANCE_REV="$(cargo_lock_git_rev "https://github.com/lancedb/lance.git")"
116+
export LITELLM_RS_REV="$(cargo_lock_git_rev "https://github.com/majiayu000/litellm-rs")"
116117
117118
cat > .cargo/git-sources.toml <<EOF
118-
[source."git+https://github.com/tao3k/litellm-rs?branch=xiuxian"]
119-
git = "https://github.com/tao3k/litellm-rs"
120-
branch = "xiuxian"
119+
[source."git+https://github.com/majiayu000/litellm-rs?rev=''${LITELLM_RS_REV}"]
120+
git = "https://github.com/majiayu000/litellm-rs"
121+
rev = "''${LITELLM_RS_REV}"
121122
replace-with = "vendored-sources"
122123
123124
[source."git+https://github.com/J-F-Liu/lopdf?rev=''${LOPDF_REV}"]

packages/rust/crates/xiuxian-julia-core/src/integration_support/search_strategy_flow_flight/materialization.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ pub async fn materialize_search_strategy_flow_routes(
141141
let mut receipts = Vec::with_capacity(planned_routes.len());
142142
for route_wave in planned_routes.chunks(wave_size) {
143143
let client = SearchStrategyFlowFlightClient::connect(config).await?;
144-
let wave_receipts = try_join_all(route_wave.iter().cloned().map(|route| {
144+
let wave_receipts = try_join_all(route_wave.iter().map(|route| {
145+
let route = route.clone();
145146
let config = config.clone();
146147
let mut client = client.clone();
147148
async move { materialize_route(&mut client, &config, &route).await }

packages/rust/crates/xiuxian-julia-runtime/tests/unit/lib/wendao.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ fn link_graph_rerank_provider_binding_uses_runtime_route_and_launch_config() {
173173
assert_eq!(binding.selector.capability_id.0, JULIA_RERANK_CAPABILITY_ID);
174174
assert_eq!(binding.endpoint.route.as_deref(), Some("/custom-rerank"));
175175
assert_eq!(
176-
binding.launch.expect("launch").launcher_path,
176+
binding.launch.unwrap_or_else(|| panic!("launch config missing")).launcher_path,
177177
DEFAULT_JULIA_SEARCH_LAUNCHER_PATH
178178
);
179179
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//! Wendao model-routing constants.
2+
3+
/// Wendao model routing mode environment variable.
4+
pub const WENDAO_MODEL_ROUTING_MODE_ENV: &str = "WENDAO_MODEL_ROUTING_MODE";
5+
/// vLLM-SR base URL environment variable.
6+
pub const WENDAO_VLLM_SR_BASE_URL_ENV: &str = "WENDAO_VLLM_SR_BASE_URL";
7+
/// vLLM-SR config path environment variable.
8+
pub const WENDAO_VLLM_SR_CONFIG_PATH_ENV: &str = "WENDAO_VLLM_SR_CONFIG_PATH";
9+
10+
/// Stable route id metadata header.
11+
pub const WENDAO_ROUTE_ID_HEADER: &str = "x-wendao-route-id";
12+
/// Stable route task-kind metadata header.
13+
pub const WENDAO_ROUTE_TASK_KIND_HEADER: &str = "x-wendao-route-task-kind";
14+
/// Stable route modality metadata header.
15+
pub const WENDAO_ROUTE_MODALITY_HEADER: &str = "x-wendao-route-modality";
16+
/// Stable selected-provider metadata header.
17+
pub const WENDAO_ROUTE_SELECTED_PROVIDER_HEADER: &str = "x-wendao-route-selected-provider";
18+
/// Stable selected-model metadata header.
19+
pub const WENDAO_ROUTE_SELECTED_MODEL_HEADER: &str = "x-wendao-route-selected-model";
20+
/// Stable selected backend-profile metadata header.
21+
pub const WENDAO_ROUTE_SELECTED_BACKEND_PROFILE_HEADER: &str =
22+
"x-wendao-route-selected-backend-profile";
23+
/// Stable precision-tier metadata header.
24+
pub const WENDAO_ROUTE_PRECISION_TIER_HEADER: &str = "x-wendao-route-precision-tier";
25+
26+
/// Default vLLM-SR proxy endpoint used by Wendao.
27+
pub const DEFAULT_WENDAO_VLLM_SR_BASE_URL: &str = "http://127.0.0.1:8888";
28+
/// Default local model-routing mode for developer experience.
29+
pub const DEFAULT_WENDAO_MODEL_ROUTING_MODE: &str = "deterministic";
30+
/// vLLM-SR auto model token used by the OpenAI-compatible data plane.
31+
pub const VLLM_SR_AUTO_MODEL: &str = "auto";
32+
/// vLLM-SR selected decision response header.
33+
pub const VLLM_SR_SELECTED_DECISION_HEADER: &str = "x-vsr-selected-decision";
34+
/// vLLM-SR selected model response header.
35+
pub const VLLM_SR_SELECTED_MODEL_HEADER: &str = "x-vsr-selected-model";
36+
/// vLLM-SR selected confidence response header.
37+
pub const VLLM_SR_SELECTED_CONFIDENCE_HEADER: &str = "x-vsr-selected-confidence";
38+
/// vLLM-SR selected reasoning response header.
39+
pub const VLLM_SR_SELECTED_REASONING_HEADER: &str = "x-vsr-selected-reasoning";
40+
/// vLLM-SR selected modality response header.
41+
pub const VLLM_SR_SELECTED_MODALITY_HEADER: &str = "x-vsr-selected-modality";
42+
/// vLLM-SR request id response header.
43+
pub const VLLM_SR_REQUEST_ID_HEADER: &str = "x-request-id";

packages/rust/crates/xiuxian-llm/src/model_routing.rs renamed to packages/rust/crates/xiuxian-llm/src/model_routing/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
//! Model routing contracts shared by Wendao Gateway and model-plane adapters.
22
3-
#[path = "model_routing/attachment.rs"]
43
mod attachment;
5-
#[path = "model_routing/chat.rs"]
64
mod chat;
7-
#[path = "model_routing/config.rs"]
85
mod config;
96

107
use reqwest::header::{AUTHORIZATION, HeaderMap};

packages/rust/crates/xiuxian-qianji/README.md

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,9 @@ that the effective Valkey checkpoint backend responds to `PING`, and
233233
running process. Workflow-control clients should use `/capabilities` to reject
234234
stale qianji-server processes before relying on recently added routes such as
235235
`bpmn.workflow.task.complete-batch`, `bpmn.workflow.task.fail`, or
236-
`bpmn.workflow.activity-evidence`, `qianji.control.bpmn-source.admit`,
237-
`qianji.control.bpmn-source`,
236+
`bpmn.workflow.activity-evidence`,
237+
`qianji.control.workflow-source.admit`,
238+
`qianji.control.bpmn-source.admit`, `qianji.control.bpmn-source`,
238239
`qianji.control.history`, `qianji.control.recovery.apply`, or
239240
`qianji.control.worker.openai-compatible-llm.run`.
240241
`--control-ledger <path>` enables an optional DuckDB-backed append-only control
@@ -248,15 +249,38 @@ old clients may still render their own projection, but promotion-grade BPMN
248249
markers should bind to the server-owned XML.
249250
Skill.md and natural-language workflow authoring follow the same server-owned
250251
boundary in product deployments. qianji-server owns the legal BPMN source
251-
admission path: `POST /control/bpmn-source/admit` accepts a candidate BPMN XML
252-
payload, runs qianji lint and parse checks, verifies the requested process id,
253-
and returns a server-owned `bpmn_path`/source ref for `/workflows/start`.
254-
Model-assisted draft generation through pi-agent-capable worker surfaces,
255-
qianji lint/repair, source ref persistence, control-run creation, and durable
256-
execution stay server-side. pi-wendao may expose the same capability through a
257-
CLI for fast local tests, but server-side wendao.ai must call qianji-server and
258-
render the server-owned BPMN source instead of compiling or repairing BPMN in
259-
the UI process.
252+
admission path. `POST /control/workflow-source/admit` accepts authoring source
253+
such as `text/markdown`, compiles it inside qianji-server, runs qianji lint and
254+
parse checks on the derived BPMN XML, verifies the requested process id, and
255+
returns a server-owned `bpmn_path`/source ref for `/workflows/start`.
256+
The first deterministic Markdown compiler admits explicit `## Step N: Title`
257+
sections only. Free-form Markdown returns `workflow_source_repair_required`
258+
until the server-owned Skill.md/pi-agent repair compiler is enabled; it is not
259+
silently downgraded to a one-node BPMN fallback.
260+
The request accepts `compiler_mode = "deterministic_markdown_step"` by default;
261+
`compiler_mode = "server_repair"` enters the server-owned repair path. The
262+
route requires the qianji-server durable control ledger and worker hot state;
263+
without those substrates it returns a substrate-specific service-unavailable
264+
error before writing any final admitted BPMN source. With durable substrates
265+
installed, qianji-server starts the embedded
266+
`qianji.workflow_source_repair.v1` BPMN repair workflow from
267+
`resources/workflows/workflow_source_repair_v1.bpmn` and returns a
268+
`repair_started` admission response. That workflow separates deterministic
269+
source intake, qianji lint evidence, and final BPMN source admission from the
270+
LLM draft, repair, and reasoning lint judge nodes. The server completes
271+
`source_intake`, `run_qianji_lint`, and `admit_bpmn_source` itself and excludes
272+
those deterministic nodes from generic LLM scheduling; LLM workers only receive
273+
declared model-owned nodes such as `draft_bpmn`, `reason_lint_diagnostics`, and
274+
`repair_bpmn`. Structured output bindings such as `candidateBpmn`,
275+
`repairPlan`, and `admittedBpmnSourceRef` carry the repair state back through
276+
the existing BPMN host-work completion contract.
277+
`POST /control/bpmn-source/admit` remains the lower-level BPMN XML admission
278+
route for already-generated candidates. Model-assisted draft generation through
279+
pi-agent-capable worker surfaces, qianji lint/repair, source ref persistence,
280+
control-run creation, and durable execution stay server-side. pi-wendao may
281+
expose the same capability through a CLI for fast local tests, but server-side
282+
wendao.ai must call qianji-server and render the server-owned BPMN source
283+
instead of compiling or repairing BPMN in the UI process.
260284
`GET /control/runs/{run_id}/summary` returns the replay-derived
261285
`RunOperatorSummary` projection for operators that need activity, timer,
262286
signal, cost, and recovery counters without parsing raw events.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" id="defs_qianji_workflow_source_repair_v1">
3+
<bpmn:process id="qianji_workflow_source_repair_v1" isExecutable="true">
4+
<bpmn:startEvent id="start_repair" />
5+
<bpmn:serviceTask id="source_intake" name="Intake authoring source">
6+
<bpmn:documentation>Validate source media type, process id, source hash, and repair budget before any model call.</bpmn:documentation>
7+
<bpmn:ioSpecification>
8+
<bpmn:dataOutput id="source_intake_Output_sourceIntakeAccepted" name="sourceIntakeAccepted" />
9+
<bpmn:outputSet id="source_intake_OutputSet">
10+
<bpmn:dataOutputRefs>source_intake_Output_sourceIntakeAccepted</bpmn:dataOutputRefs>
11+
</bpmn:outputSet>
12+
</bpmn:ioSpecification>
13+
<bpmn:dataOutputAssociation>
14+
<bpmn:sourceRef>source_intake_Output_sourceIntakeAccepted</bpmn:sourceRef>
15+
<bpmn:targetRef>sourceIntakeAccepted</bpmn:targetRef>
16+
</bpmn:dataOutputAssociation>
17+
</bpmn:serviceTask>
18+
<bpmn:serviceTask id="draft_bpmn" name="Draft BPMN artifacts">
19+
<bpmn:documentation>Use the governed qianji LLM activity lane to draft candidate BPMN artifacts from the authoring source and qianji template context.</bpmn:documentation>
20+
<bpmn:ioSpecification>
21+
<bpmn:dataOutput id="draft_bpmn_Output_candidateBpmn" name="candidateBpmn" />
22+
<bpmn:outputSet id="draft_bpmn_OutputSet">
23+
<bpmn:dataOutputRefs>draft_bpmn_Output_candidateBpmn</bpmn:dataOutputRefs>
24+
</bpmn:outputSet>
25+
</bpmn:ioSpecification>
26+
<bpmn:dataOutputAssociation>
27+
<bpmn:sourceRef>draft_bpmn_Output_candidateBpmn</bpmn:sourceRef>
28+
<bpmn:targetRef>candidateBpmn</bpmn:targetRef>
29+
</bpmn:dataOutputAssociation>
30+
</bpmn:serviceTask>
31+
<bpmn:serviceTask id="run_qianji_lint" name="Run qianji lint evidence">
32+
<bpmn:documentation>Run deterministic qianji lint over the candidate artifact bundle and emit compact structured diagnostics for the reasoning judge.</bpmn:documentation>
33+
<bpmn:ioSpecification>
34+
<bpmn:dataOutput id="run_qianji_lint_Output_lintDiagnostics" name="lintDiagnostics" />
35+
<bpmn:outputSet id="run_qianji_lint_OutputSet">
36+
<bpmn:dataOutputRefs>run_qianji_lint_Output_lintDiagnostics</bpmn:dataOutputRefs>
37+
</bpmn:outputSet>
38+
</bpmn:ioSpecification>
39+
<bpmn:dataOutputAssociation>
40+
<bpmn:sourceRef>run_qianji_lint_Output_lintDiagnostics</bpmn:sourceRef>
41+
<bpmn:targetRef>lintDiagnostics</bpmn:targetRef>
42+
</bpmn:dataOutputAssociation>
43+
</bpmn:serviceTask>
44+
<bpmn:serviceTask id="reason_lint_diagnostics" name="Reason over lint diagnostics">
45+
<bpmn:documentation>Use the governed qianji LLM reasoning lane to judge lint diagnostics, decide whether repair is required, and emit a bounded artifact-local repair plan.</bpmn:documentation>
46+
<bpmn:ioSpecification>
47+
<bpmn:dataOutput id="reason_lint_diagnostics_Output_lintPassed" name="lintPassed" />
48+
<bpmn:dataOutput id="reason_lint_diagnostics_Output_repairRequired" name="repairRequired" />
49+
<bpmn:dataOutput id="reason_lint_diagnostics_Output_repairPlan" name="repairPlan" />
50+
<bpmn:outputSet id="reason_lint_diagnostics_OutputSet">
51+
<bpmn:dataOutputRefs>reason_lint_diagnostics_Output_lintPassed</bpmn:dataOutputRefs>
52+
<bpmn:dataOutputRefs>reason_lint_diagnostics_Output_repairRequired</bpmn:dataOutputRefs>
53+
<bpmn:dataOutputRefs>reason_lint_diagnostics_Output_repairPlan</bpmn:dataOutputRefs>
54+
</bpmn:outputSet>
55+
</bpmn:ioSpecification>
56+
<bpmn:dataOutputAssociation>
57+
<bpmn:sourceRef>reason_lint_diagnostics_Output_lintPassed</bpmn:sourceRef>
58+
<bpmn:targetRef>lintPassed</bpmn:targetRef>
59+
</bpmn:dataOutputAssociation>
60+
<bpmn:dataOutputAssociation>
61+
<bpmn:sourceRef>reason_lint_diagnostics_Output_repairRequired</bpmn:sourceRef>
62+
<bpmn:targetRef>repairRequired</bpmn:targetRef>
63+
</bpmn:dataOutputAssociation>
64+
<bpmn:dataOutputAssociation>
65+
<bpmn:sourceRef>reason_lint_diagnostics_Output_repairPlan</bpmn:sourceRef>
66+
<bpmn:targetRef>repairPlan</bpmn:targetRef>
67+
</bpmn:dataOutputAssociation>
68+
</bpmn:serviceTask>
69+
<bpmn:exclusiveGateway id="lint_decision" default="flow_lint_admit" />
70+
<bpmn:serviceTask id="repair_bpmn" name="Repair BPMN artifacts">
71+
<bpmn:documentation>Use the reasoning lint repair plan and previous artifacts to request the smallest artifact-local repair through the governed qianji LLM activity lane.</bpmn:documentation>
72+
<bpmn:ioSpecification>
73+
<bpmn:dataOutput id="repair_bpmn_Output_candidateBpmn" name="candidateBpmn" />
74+
<bpmn:outputSet id="repair_bpmn_OutputSet">
75+
<bpmn:dataOutputRefs>repair_bpmn_Output_candidateBpmn</bpmn:dataOutputRefs>
76+
</bpmn:outputSet>
77+
</bpmn:ioSpecification>
78+
<bpmn:dataOutputAssociation>
79+
<bpmn:sourceRef>repair_bpmn_Output_candidateBpmn</bpmn:sourceRef>
80+
<bpmn:targetRef>candidateBpmn</bpmn:targetRef>
81+
</bpmn:dataOutputAssociation>
82+
</bpmn:serviceTask>
83+
<bpmn:serviceTask id="admit_bpmn_source" name="Admit lint-clean BPMN source">
84+
<bpmn:documentation>Admit only lint-clean BPMN through qianji-server BPMN source admission and return the server-owned source reference.</bpmn:documentation>
85+
<bpmn:ioSpecification>
86+
<bpmn:dataOutput id="admit_bpmn_source_Output_admittedBpmnSourceRef" name="admittedBpmnSourceRef" />
87+
<bpmn:outputSet id="admit_bpmn_source_OutputSet">
88+
<bpmn:dataOutputRefs>admit_bpmn_source_Output_admittedBpmnSourceRef</bpmn:dataOutputRefs>
89+
</bpmn:outputSet>
90+
</bpmn:ioSpecification>
91+
<bpmn:dataOutputAssociation>
92+
<bpmn:sourceRef>admit_bpmn_source_Output_admittedBpmnSourceRef</bpmn:sourceRef>
93+
<bpmn:targetRef>admittedBpmnSourceRef</bpmn:targetRef>
94+
</bpmn:dataOutputAssociation>
95+
</bpmn:serviceTask>
96+
<bpmn:endEvent id="done_repair" />
97+
<bpmn:sequenceFlow id="flow_start_intake" sourceRef="start_repair" targetRef="source_intake" />
98+
<bpmn:sequenceFlow id="flow_intake_draft" sourceRef="source_intake" targetRef="draft_bpmn" />
99+
<bpmn:sequenceFlow id="flow_draft_lint" sourceRef="draft_bpmn" targetRef="run_qianji_lint" />
100+
<bpmn:sequenceFlow id="flow_lint_reason" sourceRef="run_qianji_lint" targetRef="reason_lint_diagnostics" />
101+
<bpmn:sequenceFlow id="flow_reason_decision" sourceRef="reason_lint_diagnostics" targetRef="lint_decision" />
102+
<bpmn:sequenceFlow id="flow_lint_admit" sourceRef="lint_decision" targetRef="admit_bpmn_source" />
103+
<bpmn:sequenceFlow id="flow_lint_repair" sourceRef="lint_decision" targetRef="repair_bpmn">
104+
<bpmn:conditionExpression>repairRequired</bpmn:conditionExpression>
105+
</bpmn:sequenceFlow>
106+
<bpmn:sequenceFlow id="flow_repair_lint" sourceRef="repair_bpmn" targetRef="run_qianji_lint" />
107+
<bpmn:sequenceFlow id="flow_admit_done" sourceRef="admit_bpmn_source" targetRef="done_repair" />
108+
</bpmn:process>
109+
</bpmn:definitions>

packages/rust/crates/xiuxian-qianji/src/bpmn/api.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ pub use super::http_transport::{
5959
QianjiControlBpmnSourceMediaType, QianjiControlDiagnosticsHttpResponse,
6060
QianjiControlHistoryHttpResponse, QianjiControlRecoveryApplyHttpRequest,
6161
QianjiControlRecoveryApplyHttpResponse, QianjiControlRecoveryHttpResponse,
62-
QianjiControlRunSummaryHttpResponse, qianji_bpmn_workflow_router,
62+
QianjiControlRunSummaryHttpResponse, QianjiControlWorkflowSourceAdmissionHttpRequest,
63+
QianjiControlWorkflowSourceAdmissionHttpResponse, QianjiControlWorkflowSourceCompilerMode,
64+
qianji_bpmn_workflow_router,
6365
};
6466
pub use super::identity::{
6567
QianjiBpmnActivityId, QianjiBpmnLeaseOwnerToken, QianjiBpmnPackageId, QianjiBpmnProcessId,

0 commit comments

Comments
 (0)