agent-dump 1.2.3__tar.gz → 1.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. {agent_dump-1.2.3 → agent_dump-1.2.4}/Cargo.lock +1 -1
  2. {agent_dump-1.2.3 → agent_dump-1.2.4}/Cargo.toml +1 -1
  3. {agent_dump-1.2.3 → agent_dump-1.2.4}/PKG-INFO +19 -1
  4. {agent_dump-1.2.3 → agent_dump-1.2.4}/README.md +18 -0
  5. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/config.rs +14 -0
  6. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/llm.rs +70 -26
  7. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/workflows/config.rs +3 -0
  8. {agent_dump-1.2.3 → agent_dump-1.2.4}/LICENSE +0 -0
  9. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/Cargo.toml +0 -0
  10. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/compat/json/diagnostic.rs +0 -0
  11. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/compat/json/encoding.rs +0 -0
  12. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/compat/json.rs +0 -0
  13. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/compat/mod.rs +0 -0
  14. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/compat/value.rs +0 -0
  15. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/lib.rs +0 -0
  16. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/output/diagnostics.rs +0 -0
  17. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/output/export.rs +0 -0
  18. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/output/formats.rs +0 -0
  19. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/output/i18n.rs +0 -0
  20. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/output/mod.rs +0 -0
  21. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/output/render.rs +0 -0
  22. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/parallel.rs +0 -0
  23. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/claude/mod.rs +0 -0
  24. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/claude/transcript.rs +0 -0
  25. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/codex/enrichment.rs +0 -0
  26. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/codex/mod.rs +0 -0
  27. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/codex/patch.rs +0 -0
  28. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/codex/transcript.rs +0 -0
  29. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/contract.rs +0 -0
  30. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/cursor/mod.rs +0 -0
  31. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/cursor/transcript.rs +0 -0
  32. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/desktop/cherry.rs +0 -0
  33. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/desktop/deepchat.rs +0 -0
  34. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/desktop/minimax.rs +0 -0
  35. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/desktop/mod.rs +0 -0
  36. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/desktop/tests.rs +0 -0
  37. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/error.rs +0 -0
  38. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/files.rs +0 -0
  39. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/jsonl.rs +0 -0
  40. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/kimi/mod.rs +0 -0
  41. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/kimi/transcript.rs +0 -0
  42. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/kimi/wire.rs +0 -0
  43. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/mod.rs +0 -0
  44. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/pi/mod.rs +0 -0
  45. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/pi/transcript.rs +0 -0
  46. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/registry.rs +0 -0
  47. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/source_tests.rs +0 -0
  48. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/sqlite/connection.rs +0 -0
  49. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/sqlite/legacy.rs +0 -0
  50. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/sqlite/mod.rs +0 -0
  51. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/sqlite/v2.rs +0 -0
  52. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/providers/title.rs +0 -0
  53. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/query/context.rs +0 -0
  54. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/query/filter.rs +0 -0
  55. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/query/index/tests.rs +0 -0
  56. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/query/index.rs +0 -0
  57. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/query/mod.rs +0 -0
  58. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/query/read.rs +0 -0
  59. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/query/scanner.rs +0 -0
  60. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/query/text.rs +0 -0
  61. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/query/transcript.rs +0 -0
  62. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/session/assembly.rs +0 -0
  63. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/session/cache/tests.rs +0 -0
  64. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/session/cache.rs +0 -0
  65. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/session/mod.rs +0 -0
  66. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/session/timestamp.rs +0 -0
  67. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/storage/mod.rs +0 -0
  68. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/storage/private_files.rs +0 -0
  69. {agent_dump-1.2.3 → agent_dump-1.2.4}/crates/agent-dump-core/src/storage/source_io.rs +0 -0
  70. {agent_dump-1.2.3 → agent_dump-1.2.4}/pyproject.toml +0 -0
  71. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/locales/en.json +0 -0
  72. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/locales/zh.json +0 -0
  73. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/.gitattributes +0 -0
  74. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/README.md +0 -0
  75. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/insight-chunk.txt +0 -0
  76. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/insight-handoff.txt +0 -0
  77. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/insight-merge.txt +0 -0
  78. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/insight-report.txt +0 -0
  79. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/insight-retry.txt +0 -0
  80. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/pm-chunk.txt +0 -0
  81. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/pm-handoff.txt +0 -0
  82. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/pm-merge.txt +0 -0
  83. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/pm-report.txt +0 -0
  84. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/pm-retry.txt +0 -0
  85. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/read-session-en.txt +0 -0
  86. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/read-session-zh.txt +0 -0
  87. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/system.txt +0 -0
  88. {agent_dump-1.2.3 → agent_dump-1.2.4}/resources/prompts/uri.txt +0 -0
  89. {agent_dump-1.2.3 → agent_dump-1.2.4}/rust-toolchain.toml +0 -0
  90. {agent_dump-1.2.3 → agent_dump-1.2.4}/rustfmt.toml +0 -0
  91. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/cli_args.rs +0 -0
  92. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/events.rs +0 -0
  93. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/handoff.rs +0 -0
  94. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/log.rs +0 -0
  95. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/mod.rs +0 -0
  96. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/model.rs +0 -0
  97. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/progress.rs +0 -0
  98. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/prompts.rs +0 -0
  99. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/reduction.rs +0 -0
  100. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/sessions.rs +0 -0
  101. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/collect/summary.rs +0 -0
  102. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/command.rs +0 -0
  103. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/date_input.rs +0 -0
  104. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/main.rs +0 -0
  105. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/shortcut.rs +0 -0
  106. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/terminal/mod.rs +0 -0
  107. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/terminal/reader.rs +0 -0
  108. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/terminal/selector.rs +0 -0
  109. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/terminal/tui.rs +0 -0
  110. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/workflows/collect.rs +0 -0
  111. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/workflows/interactive.rs +0 -0
  112. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/workflows/list.rs +0 -0
  113. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/workflows/machine.rs +0 -0
  114. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/workflows/maintenance.rs +0 -0
  115. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/workflows/mod.rs +0 -0
  116. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/workflows/read.rs +0 -0
  117. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/workflows/reader.rs +0 -0
  118. {agent_dump-1.2.3 → agent_dump-1.2.4}/src/workflows/uri.rs +0 -0
@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
10
10
 
11
11
  [[package]]
12
12
  name = "agent-dump"
13
- version = "1.2.3"
13
+ version = "1.2.4"
14
14
  dependencies = [
15
15
  "agent-dump-core",
16
16
  "caseless",
@@ -46,7 +46,7 @@ nix = { version = "0.31", default-features = false, features = ["fs", "user"] }
46
46
 
47
47
  [package]
48
48
  name = "agent-dump"
49
- version = "1.2.3"
49
+ version = "1.2.4"
50
50
  edition = "2024"
51
51
  rust-version = "1.90"
52
52
  publish = false
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-dump
3
- Version: 1.2.3
3
+ Version: 1.2.4
4
4
  Classifier: Environment :: Console
5
5
  Classifier: License :: OSI Approved :: MIT License
6
6
  Classifier: Programming Language :: Rust
@@ -479,6 +479,7 @@ provider = "openai" # openai | anthropic
479
479
  base_url = "https://api.openai.com/v1"
480
480
  model = "gpt-4.1-mini"
481
481
  api_key = "sk-..."
482
+ reasoning = "off" # off | default
482
483
 
483
484
  [collect]
484
485
  summary_concurrency = 4 # 1-32
@@ -501,6 +502,23 @@ deny = [
501
502
  ]
502
503
  ```
503
504
 
505
+ `[ai].reasoning` controls the model's thinking mode. `off` (the default) sends `enable_thinking: false` to OpenAI-compatible services and `thinking: {type: "disabled"}` to Anthropic. `default` sends neither and leaves the service default in place. Enabling reasoning or choosing an effort level uses vendor-specific parameters, so set them in `[ai.extra_body]`. The table is deep-merged into every request body: nested tables merge, other values replace.
506
+
507
+ ```toml
508
+ # OpenAI reasoning models
509
+ [ai.extra_body]
510
+ reasoning_effort = "low"
511
+ ```
512
+
513
+ ```toml
514
+ # Anthropic extended thinking; max_tokens must exceed budget_tokens
515
+ [ai.extra_body]
516
+ max_tokens = 8192
517
+ thinking = { type = "enabled", budget_tokens = 2048 }
518
+ ```
519
+
520
+ When an OpenAI-compatible service rejects the default `enable_thinking`, `temperature`, or `max_tokens`, agent-dump retries without it; `max_tokens` is renamed to `max_completion_tokens`. Parameters set in `extra_body` are never removed. `--config edit` does not prompt for `reasoning` or `extra_body` and keeps their values.
521
+
504
522
  `[agent.<name>].deny` only applies to `--collect`. When a session `cwd` matches one of the configured paths, or is inside that path, the session is ignored during collect.
505
523
 
506
524
  Collect, `--collect --dry-run`, and `--collect --emit-prompt` require valid TOML and exclusion arrays containing only nonempty path strings. Invalid configuration stops the command before session discovery or AI requests; compatibility parsing never disables exclusions for collect.
@@ -455,6 +455,7 @@ provider = "openai" # openai | anthropic
455
455
  base_url = "https://api.openai.com/v1"
456
456
  model = "gpt-4.1-mini"
457
457
  api_key = "sk-..."
458
+ reasoning = "off" # off | default
458
459
 
459
460
  [collect]
460
461
  summary_concurrency = 4 # 1-32
@@ -477,6 +478,23 @@ deny = [
477
478
  ]
478
479
  ```
479
480
 
481
+ `[ai].reasoning` controls the model's thinking mode. `off` (the default) sends `enable_thinking: false` to OpenAI-compatible services and `thinking: {type: "disabled"}` to Anthropic. `default` sends neither and leaves the service default in place. Enabling reasoning or choosing an effort level uses vendor-specific parameters, so set them in `[ai.extra_body]`. The table is deep-merged into every request body: nested tables merge, other values replace.
482
+
483
+ ```toml
484
+ # OpenAI reasoning models
485
+ [ai.extra_body]
486
+ reasoning_effort = "low"
487
+ ```
488
+
489
+ ```toml
490
+ # Anthropic extended thinking; max_tokens must exceed budget_tokens
491
+ [ai.extra_body]
492
+ max_tokens = 8192
493
+ thinking = { type = "enabled", budget_tokens = 2048 }
494
+ ```
495
+
496
+ When an OpenAI-compatible service rejects the default `enable_thinking`, `temperature`, or `max_tokens`, agent-dump retries without it; `max_tokens` is renamed to `max_completion_tokens`. Parameters set in `extra_body` are never removed. `--config edit` does not prompt for `reasoning` or `extra_body` and keeps their values.
497
+
480
498
  `[agent.<name>].deny` only applies to `--collect`. When a session `cwd` matches one of the configured paths, or is inside that path, the session is ignored during collect.
481
499
 
482
500
  Collect, `--collect --dry-run`, and `--collect --emit-prompt` require valid TOML and exclusion arrays containing only nonempty path strings. Invalid configuration stops the command before session discovery or AI requests; compatibility parsing never disables exclusions for collect.
@@ -10,6 +10,8 @@ pub struct AiConfig {
10
10
  pub base_url: String,
11
11
  pub model: String,
12
12
  pub api_key: String,
13
+ pub reasoning: String,
14
+ pub extra_body: Value,
13
15
  }
14
16
 
15
17
  pub struct CollectConfig {
@@ -183,6 +185,12 @@ impl Config {
183
185
  base_url: text(&self.data["ai"]["base_url"]),
184
186
  model: text(&self.data["ai"]["model"]),
185
187
  api_key: text(&self.data["ai"]["api_key"]),
188
+ reasoning: if self.data["ai"]["reasoning"].is_null() {
189
+ "off".into()
190
+ } else {
191
+ text(&self.data["ai"]["reasoning"])
192
+ },
193
+ extra_body: self.data["ai"]["extra_body"].clone(),
186
194
  })
187
195
  }
188
196
  pub fn output(&self) -> String {
@@ -436,6 +444,12 @@ pub fn validate_ai(
436
444
  if config.api_key.is_empty() {
437
445
  errors.push("api_key");
438
446
  }
447
+ if !matches!(config.reasoning.as_str(), "off" | "default") {
448
+ errors.push("reasoning");
449
+ }
450
+ if !config.extra_body.is_null() && !config.extra_body.is_object() {
451
+ errors.push("extra_body");
452
+ }
439
453
  if !config.base_url.is_empty() {
440
454
  let scheme = config
441
455
  .base_url
@@ -9,7 +9,7 @@ use std::time::Duration;
9
9
  pub struct RequestError {
10
10
  message: String,
11
11
  pub retryable: bool,
12
- rejected_thinking: bool,
12
+ rejected: Option<&'static str>,
13
13
  }
14
14
  impl fmt::Display for RequestError {
15
15
  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -22,7 +22,7 @@ const fn error(message: String, retryable: bool) -> RequestError {
22
22
  RequestError {
23
23
  message,
24
24
  retryable,
25
- rejected_thinking: false,
25
+ rejected: None,
26
26
  }
27
27
  }
28
28
 
@@ -56,29 +56,68 @@ fn respond(
56
56
  structured: Option<Mode>,
57
57
  ) -> Result<Value, RequestError> {
58
58
  let system = include_str!("../../resources/prompts/system.txt");
59
- let mut payload = if config.provider == "openai" {
60
- json!({"model":config.model, "messages":[{"role":"system", "content":system}, {"role":"user", "content":prompt}], "temperature":0.2, "enable_thinking":false})
59
+ let openai = config.provider == "openai";
60
+ let mut payload = if openai {
61
+ json!({"model":config.model, "messages":[{"role":"system", "content":system}, {"role":"user", "content":prompt}], "temperature":0.2})
61
62
  } else {
62
- json!({"model":config.model, "max_tokens":4096, "system":system, "messages":[{"role":"user", "content":prompt}], "thinking":{"type":"disabled"}})
63
+ json!({"model":config.model, "max_tokens":4096, "system":system, "messages":[{"role":"user", "content":prompt}]})
63
64
  };
65
+ if config.reasoning == "off" {
66
+ if openai {
67
+ payload["enable_thinking"] = false.into();
68
+ } else {
69
+ payload["thinking"] = json!({"type":"disabled"});
70
+ }
71
+ }
64
72
  if let Some(mode) = structured
65
- && config.provider == "openai"
73
+ && openai
66
74
  {
67
75
  payload["max_tokens"] = 4096.into();
68
76
  payload["response_format"] =
69
77
  json!({"type":"json_schema", "json_schema":schema(mode)});
70
78
  }
71
- match post(config, &payload, timeout) {
72
- Err(error)
73
- if error.rejected_thinking && config.provider == "openai" =>
74
- {
75
- payload.as_object_mut().unwrap().remove("enable_thinking");
76
- post(config, &payload, timeout)
79
+ merge(&mut payload, &config.extra_body);
80
+ loop {
81
+ let result = post(config, &payload, timeout);
82
+ let retry = match &result {
83
+ Err(error) if openai => error.rejected.is_some_and(|param| {
84
+ config.extra_body.get(param).is_none()
85
+ && drop_rejected(&mut payload, param)
86
+ }),
87
+ _ => false,
88
+ };
89
+ if !retry {
90
+ return result;
77
91
  }
78
- result => result,
79
92
  }
80
93
  }
81
94
 
95
+ fn merge(target: &mut Value, source: &Value) {
96
+ if let (Value::Object(target), Value::Object(source)) = (target, source) {
97
+ for (key, value) in source {
98
+ match target.get_mut(key) {
99
+ Some(slot) if slot.is_object() && value.is_object() => {
100
+ merge(slot, value);
101
+ }
102
+ _ => {
103
+ target.insert(key.clone(), value.clone());
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+ fn drop_rejected(payload: &mut Value, param: &str) -> bool {
111
+ let payload = payload.as_object_mut().unwrap();
112
+ let Some(value) = payload.shift_remove(param) else {
113
+ return false;
114
+ };
115
+ if param == "max_tokens" {
116
+ payload.insert("max_completion_tokens".into(), value);
117
+ }
118
+ true
119
+ }
120
+
82
121
  fn content(
83
122
  config: &AiConfig,
84
123
  response: &Value,
@@ -97,8 +136,8 @@ fn content(
97
136
  } else {
98
137
  response
99
138
  .get("content")
100
- .and_then(|v| v.get(0))
101
- .and_then(|v| v.get("text"))
139
+ .and_then(Value::as_array)
140
+ .and_then(|blocks| blocks.iter().find_map(|v| v.get("text")))
102
141
  };
103
142
  let content = content.ok_or_else(|| {
104
143
  error(format!("{provider} API response missing content"), false)
@@ -277,17 +316,22 @@ fn post(
277
316
  .as_str()
278
317
  .unwrap_or("")
279
318
  .to_lowercase();
280
- failure.rejected_thinking = param == "enable_thinking"
281
- || (message.contains("enable_thinking")
282
- && [
283
- "unrecognized request argument",
284
- "unknown parameter",
285
- "unsupported parameter",
286
- "unexpected keyword argument",
287
- "extra inputs are not permitted",
288
- ]
289
- .iter()
290
- .any(|s| message.contains(s)));
319
+ failure.rejected =
320
+ ["enable_thinking", "temperature", "max_tokens"]
321
+ .into_iter()
322
+ .find(|name| {
323
+ param == *name
324
+ || (message.contains(name)
325
+ && [
326
+ "unrecognized request argument",
327
+ "unknown parameter",
328
+ "unsupported parameter",
329
+ "unexpected keyword argument",
330
+ "extra inputs are not permitted",
331
+ ]
332
+ .iter()
333
+ .any(|s| message.contains(s)))
334
+ });
291
335
  }
292
336
  return Err(failure);
293
337
  }
@@ -343,6 +343,9 @@ fn prompt(
343
343
  base_url: values[0].trim().into(),
344
344
  model: values[1].trim().into(),
345
345
  api_key: values[2].trim().into(),
346
+ reasoning: existing.map_or("off", |ai| &ai.reasoning).into(),
347
+ extra_body: existing
348
+ .map_or(serde_json::Value::Null, |ai| ai.extra_body.clone()),
346
349
  });
347
350
  let output = values[3].trim().to_owned();
348
351
  writeln!(out, "{}", t("CONFIG_CONFIRM_TITLE", zh, &[]))?;
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes