fix(editor): desktop chat session + builtin http handling
This commit is contained in:
parent
df57392a1a
commit
ea3f94093c
|
|
@ -98,6 +98,11 @@ op-mcp = { path = "../op-mcp" }
|
|||
# S3a design orchestrator — driven by `chat_orchestrator.rs` when a chat
|
||||
# message classifies as a design request.
|
||||
op-orchestrator = { path = "../op-orchestrator" }
|
||||
# Debug-mode logging: a tracing subscriber over the orchestrator's tracing
|
||||
# events (LLM calls + parse failures with raw output). Silent unless RUST_LOG
|
||||
# is set — see `init_tracing` in main.rs.
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { workspace = true }
|
||||
# Phase 7 strangler reorg: the transport-free AI chat data shapes
|
||||
# (`ChatProvider` trait + model catalog + agent-settings state) were
|
||||
# extracted into op-ai; the `src/chat_*.rs` real transports + the
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ use op_host_services::chat_canvas_tools::execute_chat_tool;
|
|||
#[path = "chat_session_launch.rs"]
|
||||
mod launch;
|
||||
#[cfg(test)]
|
||||
pub(crate) use launch::{builtin_provider_with_tools, clear_fresh_starter_frame_for_design};
|
||||
pub(crate) use launch::builtin_provider_with_tools;
|
||||
pub use launch::{drain_new_chat_request, drain_stop_request, launch_if_pending};
|
||||
pub(crate) use launch::{provider_for_selected_model, selected_cli_model_id};
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,15 @@ fn render_progress(progress: &[Progress]) -> String {
|
|||
fn progress_label(p: &Progress) -> String {
|
||||
match p {
|
||||
Progress::Planning => "• Planning…".into(),
|
||||
Progress::Planned { subtasks } => {
|
||||
// Full task checklist upfront (TS parity) — one row per planned
|
||||
// section so the user sees the whole plan immediately.
|
||||
let rows: String = subtasks
|
||||
.iter()
|
||||
.map(|(_, label)| format!("\n ☐ {label}"))
|
||||
.collect();
|
||||
format!("• Plan — {} sections:{}", subtasks.len(), rows)
|
||||
}
|
||||
Progress::ScaffoldDone => "• Scaffold ready".into(),
|
||||
Progress::SubtaskStarted { id, label } => format!("• Subtask `{id}` — {label}"),
|
||||
Progress::SubtaskDone { id, node_count } => {
|
||||
|
|
|
|||
|
|
@ -925,6 +925,21 @@ fn prompt_update_available(locale: op_editor_core::Locale, version: &str) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Install a stderr tracing subscriber for debug-mode logging — orchestrator
|
||||
/// LLM calls + parse failures (with the model's raw output). Writes to stderr
|
||||
/// so it never pollutes the `--mcp` stdout JSON-RPC stream. The default `warn`
|
||||
/// filter surfaces parse failures with no env var; `RUST_LOG=op_orchestrator=debug`
|
||||
/// (and/or `op_host_desktop=debug` for per-subtask design progress) opens the
|
||||
/// full firehose.
|
||||
fn init_tracing() {
|
||||
use tracing_subscriber::{fmt, EnvFilter};
|
||||
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("warn"));
|
||||
let _ = fmt()
|
||||
.with_env_filter(filter)
|
||||
.with_writer(std::io::stderr)
|
||||
.try_init();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Register the brand-logo catalog (omitted from the wasm bundle, embedded in
|
||||
// this binary) BEFORE any path that can render natively — the GUI app, the
|
||||
|
|
@ -932,6 +947,7 @@ fn main() {
|
|||
// simple-icons instead of the unknown-glyph fallback dot. Set-once /
|
||||
// idempotent.
|
||||
op_editor_ui::set_brand_catalog(op_host_services::web_static::ICONIFY_BRANDS_JSON);
|
||||
init_tracing();
|
||||
// `--mcp` / `--mcp-http` swap the GUI for an MCP server mode;
|
||||
// when one of those ran, exit instead of opening a window.
|
||||
if mcp_serve::run_cli_if_requested() {
|
||||
|
|
|
|||
|
|
@ -84,6 +84,10 @@ pub fn handle_save_as(
|
|||
match save_as_dialog(host.editor_state()) {
|
||||
Ok(Some(path)) => {
|
||||
crate::settings_io::touch_recent(host, &path);
|
||||
// Mirror handle_save: refresh the in-chrome file name too, not
|
||||
// just the OS window title — without this, first Save As writes
|
||||
// the file but the TopBar keeps showing "Untitled".
|
||||
set_display_name(host, Some(&path));
|
||||
*current_path = Some(path);
|
||||
refresh_title(current_path, window);
|
||||
true
|
||||
|
|
|
|||
|
|
@ -225,6 +225,15 @@ fn is_minimax_model(model: &str) -> bool {
|
|||
m.starts_with("minimax") || m.starts_with("abab")
|
||||
}
|
||||
|
||||
/// GLM-4.5+/GLM-5.x(智谱 / 方舟 coding plan)同为推理模型:reasoning 走
|
||||
/// `reasoning_content`,不关思考会烧光输出预算把 `content` 留空(实测 glm-5.2
|
||||
/// 一个设计子任务 thinking_len≈3 万、text_len=0,整段 parse 失败)。它接受和
|
||||
/// MiniMax 同样的 `thinking:{type:"disabled"}`(curl 对 ark glm-5.2 验证:关思考后
|
||||
/// reasoning_tokens=0、content 为干净 JSON)。按名判定,只对 GLM 下发。
|
||||
fn is_glm_model(model: &str) -> bool {
|
||||
model.to_ascii_lowercase().contains("glm")
|
||||
}
|
||||
|
||||
async fn run_openai_chat(
|
||||
provider: ConfiguredBuiltinProvider,
|
||||
system_prompt: String,
|
||||
|
|
@ -257,13 +266,13 @@ async fn run_openai_chat(
|
|||
"max_tokens": max_output_tokens,
|
||||
"messages": messages,
|
||||
});
|
||||
// MiniMax M 系是推理模型,默认把 `<think>…</think>` 注进 `content`,既烧光
|
||||
// 输出预算(JSON 被截断)又逼解析层去剥 think。当调用方明确要求关思考时
|
||||
// (`disable_thinking`,如编排器的设计子任务),在线级关掉(实测确认 MiniMax
|
||||
// 接受 `thinking:{type:"disabled"}` 返回干净 content)。普通对话用 `Adaptive`、
|
||||
// 不会进这里,保留 M3 推理。仅对 MiniMax 加此字段,不碰别的 openai-compat
|
||||
// provider(DeepSeek / 方舟 / Qwen)。
|
||||
if disable_thinking && is_minimax_model(&provider.model) {
|
||||
// MiniMax M 系和 GLM-5.x 都是推理模型:不关思考会把 reasoning 烧到占满输出
|
||||
// 预算,JSON content 被截断甚至留空(glm-5.2 实测一个设计子任务 thinking≈3 万
|
||||
// 字符、content 0,整段 parse 失败、重试也撞同一堵墙)。当调用方明确要求关思考
|
||||
// (`disable_thinking`,如编排器的设计子任务),在线级下发 `thinking:{type:"disabled"}`
|
||||
// (实测 MiniMax 与 ark glm-5.2 都接受、返回干净 content)。普通对话走 `Adaptive`
|
||||
// 不进这里,保留推理。只对这两类加此字段,不碰别的 openai-compat(DeepSeek / Qwen)。
|
||||
if disable_thinking && (is_minimax_model(&provider.model) || is_glm_model(&provider.model)) {
|
||||
if let Some(obj) = body.as_object_mut() {
|
||||
obj.insert("thinking".into(), json!({ "type": "disabled" }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -549,6 +549,9 @@ fn write_error_event<W: Write>(out: &mut W, message: &str) -> std::io::Result<()
|
|||
fn progress_label(p: &Progress) -> String {
|
||||
match p {
|
||||
Progress::Planning => "• Planning…".into(),
|
||||
Progress::Planned { subtasks } => {
|
||||
format!("• Plan — {} section(s)", subtasks.len())
|
||||
}
|
||||
Progress::ScaffoldDone => "• Scaffold ready".into(),
|
||||
Progress::SubtaskStarted { id, label } => format!("• Subtask `{id}` — {label}"),
|
||||
Progress::SubtaskDone { id, node_count } => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue